summaryrefslogtreecommitdiff
path: root/cras/src/libcras
diff options
context:
space:
mode:
Diffstat (limited to 'cras/src/libcras')
-rw-r--r--cras/src/libcras/cras_client.c4249
-rw-r--r--cras/src/libcras/cras_client.h2008
-rw-r--r--cras/src/libcras/cras_helpers.c159
-rw-r--r--cras/src/libcras/cras_helpers.h95
4 files changed, 0 insertions, 6511 deletions
diff --git a/cras/src/libcras/cras_client.c b/cras/src/libcras/cras_client.c
deleted file mode 100644
index 8420db1f..00000000
--- a/cras/src/libcras/cras_client.c
+++ /dev/null
@@ -1,4249 +0,0 @@
-/* Copyright (c) 2012 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.
- */
-
-/*
- * Basic playback flow:
- * cras_client_create - Create new structure and set to defaults.
- * cras_client_connect - Connect client to server - sets up server_fd to
- * communicate with the audio server. After the client connects, the server
- * will send back a message containing the client id.
- * cras_client_add_stream - Add a playback or capture stream. Creates a
- * client_stream struct and send a file descriptor to server. That file
- * descriptor and aud_fd are a pair created from socketpair().
- * client_connected - The server will send a connected message to indicate that
- * the client should start receiving audio events from aud_fd. This message
- * also specifies the shared memory region to use to share audio samples.
- * This region will be shmat'd.
- * running - Once the connections are established, the client will listen for
- * requests on aud_fd and fill the shm region with the requested number of
- * samples. This happens in the aud_cb specified in the stream parameters.
- */
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE /* For ppoll() */
-#endif
-
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <poll.h>
-#include <pthread.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <sys/eventfd.h>
-#include <sys/ipc.h>
-#include <sys/mman.h>
-#include <sys/param.h>
-#include <sys/signal.h>
-#include <sys/socket.h>
-#include <sys/timerfd.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <syslog.h>
-#include <unistd.h>
-
-#include "cras_client.h"
-#include "cras_config.h"
-#include "cras_file_wait.h"
-#include "cras_messages.h"
-#include "cras_observer_ops.h"
-#include "cras_shm.h"
-#include "cras_types.h"
-#include "cras_util.h"
-#include "utlist.h"
-
-static const size_t MAX_CMD_MSG_LEN = 256;
-static const size_t SERVER_SHUTDOWN_TIMEOUT_US = 500000;
-static const size_t SERVER_CONNECT_TIMEOUT_MS = 1000;
-static const size_t HOTWORD_FRAME_RATE = 16000;
-static const size_t HOTWORD_BLOCK_SIZE = 320;
-
-/* Commands sent from the user to the running client. */
-enum { CLIENT_STOP,
- CLIENT_ADD_STREAM,
- CLIENT_REMOVE_STREAM,
- CLIENT_SET_STREAM_VOLUME_SCALER,
- CLIENT_SERVER_CONNECT,
- CLIENT_SERVER_CONNECT_ASYNC,
-};
-
-struct command_msg {
- unsigned len;
- unsigned msg_id;
- cras_stream_id_t stream_id;
-};
-
-struct set_stream_volume_command_message {
- struct command_msg header;
- float volume_scaler;
-};
-
-/* Adds a stream to the client.
- * stream - The stream to add.
- * stream_id_out - Filled with the stream id of the new stream.
- * dev_idx - Index of the device to attach the newly created stream.
- * NO_DEVICE means not to pin the stream to a device.
- */
-struct add_stream_command_message {
- struct command_msg header;
- struct client_stream *stream;
- cras_stream_id_t *stream_id_out;
- uint32_t dev_idx;
-};
-
-/* Commands send from a running stream to the client. */
-enum { CLIENT_STREAM_EOF,
-};
-
-struct stream_msg {
- unsigned msg_id;
- cras_stream_id_t stream_id;
-};
-
-enum CRAS_THREAD_STATE {
- CRAS_THREAD_STOP,
- /* Isn't (shouldn't be) running. */
- CRAS_THREAD_WARMUP,
- /* Is started, but not fully functional: waiting
- * for resources to be ready for example. */
- CRAS_THREAD_RUNNING,
- /* Is running and fully functional. */
-};
-
-/* Manage information for a thread. */
-struct thread_state {
- pthread_t tid;
- enum CRAS_THREAD_STATE state;
-};
-
-/* Parameters used when setting up a capture or playback stream. See comment
- * above cras_client_stream_params_create or libcras_stream_params_set in the
- * header for descriptions. */
-struct cras_stream_params {
- enum CRAS_STREAM_DIRECTION direction;
- size_t buffer_frames;
- size_t cb_threshold;
- enum CRAS_STREAM_TYPE stream_type;
- enum CRAS_CLIENT_TYPE client_type;
- uint32_t flags;
- uint64_t effects;
- void *user_data;
- cras_playback_cb_t aud_cb;
- cras_unified_cb_t unified_cb;
- cras_error_cb_t err_cb;
- struct cras_audio_format format;
- libcras_stream_cb_t stream_cb;
-};
-
-/* Represents an attached audio stream.
- * id - Unique stream identifier.
- * aud_fd - After server connects audio messages come in here.
- * direction - playback, capture, or loopback (see CRAS_STREAM_DIRECTION).
- * flags - Currently only used for CRAS_INPUT_STREAM_FLAG.
- * volume_scaler - Amount to scale the stream by, 0.0 to 1.0. Client could
- * change this scaler value before stream actually connected, so we need
- * to cache it until shm is prepared and apply it.
- * tid - Thread id of the audio thread spawned for this stream.
- * running - Audio thread runs while this is non-zero.
- * wake_fds - Pipe to wake the audio thread.
- * client - The client this stream is attached to.
- * config - Audio stream configuration.
- * shm - Shared memory used to exchange audio samples with the server.
- * prev, next - Form a linked list of streams attached to a client.
- */
-struct client_stream {
- cras_stream_id_t id;
- int aud_fd; /* audio messages from server come in here. */
- enum CRAS_STREAM_DIRECTION direction;
- uint32_t flags;
- float volume_scaler;
- struct thread_state thread;
- int wake_fds[2]; /* Pipe to wake the thread */
- struct cras_client *client;
- struct cras_stream_params *config;
- struct cras_audio_shm *shm;
- struct client_stream *prev, *next;
-};
-
-/* State of the socket. */
-typedef enum cras_socket_state {
- CRAS_SOCKET_STATE_DISCONNECTED,
- /* Not connected. Also used to cleanup the current connection
- * before restarting the connection attempt. */
- CRAS_SOCKET_STATE_WAIT_FOR_SOCKET,
- /* Waiting for the socket file to exist. Socket file existence
- * is monitored using cras_file_wait. */
- CRAS_SOCKET_STATE_WAIT_FOR_WRITABLE,
- /* Waiting for the socket to have something at the other end. */
- CRAS_SOCKET_STATE_FIRST_MESSAGE,
- /* Waiting for the first messages from the server and set our
- * client ID. */
- CRAS_SOCKET_STATE_CONNECTED,
- /* The socket is connected and working. */
- CRAS_SOCKET_STATE_ERROR_DELAY,
- /* There was an error during one of the above states. Sleep for
- * a bit before continuing. If this state could not be initiated
- * then we move to the DISCONNECTED state and notify via the
- * connection callback. */
-} cras_socket_state_t;
-
-/* Represents a client used to communicate with the audio server.
- * id - Unique identifier for this client, negative until connected.
- * server_fd - Incoming messages from server.
- * server_fd_state - State of the server's socket.
- * server_event_fd - Eventfd to wait on until a connection is established.
- * stream_fds - Pipe for attached streams.
- * command_fds - Pipe for user commands to thread.
- * command_reply_fds - Pipe for acking/nacking command messages from thread.
- * sock_file - Server communication socket file.
- * sock_file_wait - Structure used to monitor existence of the socket file.
- * sock_file_exists - Set to true when the socket file exists.
- * running - The client thread will run while this is non zero.
- * next_stream_id - ID to give the next stream.
- * stream_start_cond - Condition used during stream startup.
- * stream_start_lock - Lock used during stream startup.
- * tid - Thread ID of the client thread started by "cras_client_run_thread".
- * last_command_result - Passes back the result of the last user command.
- * streams - Linked list of streams attached to this client.
- * server_state - RO shared memory region holding server state.
- * atlog_ro - RO shared memory region holding audio thread log.
- * debug_info_callback - Function to call when debug info is received.
- * atlog_access_callback - Function to call when atlog RO fd is received.
- * get_hotword_models_cb_t - Function to call when hotword models info is ready.
- * server_connection_cb - Function to called when a connection state changes.
- * server_connection_user_arg - User argument for server_connection_cb.
- * thread_priority_cb - Function to call for setting audio thread priority.
- * observer_ops - Functions to call when system state changes.
- * observer_context - Context passed to client in state change callbacks.
- */
-struct cras_client {
- int id;
- int server_fd;
- cras_socket_state_t server_fd_state;
- int server_event_fd;
- int stream_fds[2];
- int command_fds[2];
- int command_reply_fds[2];
- const char *sock_file;
- struct cras_file_wait *sock_file_wait;
- bool sock_file_exists;
- struct thread_state thread;
- cras_stream_id_t next_stream_id;
- pthread_cond_t stream_start_cond;
- pthread_mutex_t stream_start_lock;
- int last_command_result;
- struct client_stream *streams;
- const struct cras_server_state *server_state;
- struct audio_thread_event_log *atlog_ro;
- void (*debug_info_callback)(struct cras_client *);
- void (*atlog_access_callback)(struct cras_client *);
- get_hotword_models_cb_t get_hotword_models_cb;
- cras_connection_status_cb_t server_connection_cb;
- void *server_connection_user_arg;
- cras_thread_priority_cb_t thread_priority_cb;
- struct cras_observer_ops observer_ops;
- void *observer_context;
-};
-
-/*
- * Holds the client pointer plus internal book keeping.
- *
- * client - The client
- * server_state_rwlock - lock to make the client's server_state thread-safe.
- */
-struct client_int {
- struct cras_client client;
- pthread_rwlock_t server_state_rwlock;
-};
-
-#define to_client_int(cptr) \
- ((struct client_int *)((char *)cptr - \
- offsetof(struct client_int, client)))
-
-/*
- * Holds the hotword stream format, params, and ID used when waiting for a
- * hotword. The structure is created by cras_client_enable_hotword_callback and
- * destroyed by cras_client_disable_hotword_callback.
- */
-struct cras_hotword_handle {
- struct cras_audio_format *format;
- struct cras_stream_params *params;
- cras_stream_id_t stream_id;
- cras_hotword_trigger_cb_t trigger_cb;
- cras_hotword_error_cb_t err_cb;
- void *user_data;
-};
-
-struct cras_stream_cb_data {
- cras_stream_id_t stream_id;
- enum CRAS_STREAM_DIRECTION direction;
- uint8_t *buf;
- unsigned int frames;
- struct timespec sample_ts;
- void *user_arg;
-};
-
-int stream_cb_get_stream_id(struct cras_stream_cb_data *data,
- cras_stream_id_t *id)
-{
- *id = data->stream_id;
- return 0;
-}
-
-int stream_cb_get_buf(struct cras_stream_cb_data *data, uint8_t **buf)
-{
- *buf = data->buf;
- return 0;
-}
-
-int stream_cb_get_frames(struct cras_stream_cb_data *data, unsigned int *frames)
-{
- *frames = data->frames;
- return 0;
-}
-
-int stream_cb_get_latency(struct cras_stream_cb_data *data,
- struct timespec *latency)
-{
- if (data->direction == CRAS_STREAM_INPUT)
- cras_client_calc_capture_latency(&data->sample_ts, latency);
- else
- cras_client_calc_playback_latency(&data->sample_ts, latency);
- return 0;
-}
-
-int stream_cb_get_user_arg(struct cras_stream_cb_data *data, void **user_arg)
-{
- *user_arg = data->user_arg;
- return 0;
-}
-
-struct libcras_stream_cb_data *
-libcras_stream_cb_data_create(cras_stream_id_t stream_id,
- enum CRAS_STREAM_DIRECTION direction,
- uint8_t *buf, unsigned int frames,
- struct timespec sample_ts, void *user_arg)
-{
- struct libcras_stream_cb_data *data =
- (struct libcras_stream_cb_data *)calloc(
- 1, sizeof(struct libcras_stream_cb_data));
- if (!data) {
- syslog(LOG_ERR, "cras_client: calloc: %s", strerror(errno));
- return NULL;
- }
- data->data_ = (struct cras_stream_cb_data *)calloc(
- 1, sizeof(struct cras_stream_cb_data));
- if (!data->data_) {
- syslog(LOG_ERR, "cras_client: calloc: %s", strerror(errno));
- free(data);
- return NULL;
- }
- data->api_version = CRAS_API_VERSION;
- data->get_stream_id = stream_cb_get_stream_id;
- data->get_buf = stream_cb_get_buf;
- data->get_frames = stream_cb_get_frames;
- data->get_latency = stream_cb_get_latency;
- data->get_user_arg = stream_cb_get_user_arg;
- data->data_->stream_id = stream_id;
- data->data_->direction = direction;
- data->data_->buf = buf;
- data->data_->frames = frames;
- data->data_->sample_ts = sample_ts;
- data->data_->user_arg = user_arg;
- return data;
-}
-
-void libcras_stream_cb_data_destroy(struct libcras_stream_cb_data *data)
-{
- if (data)
- free(data->data_);
- free(data);
-}
-
-/*
- * Local Helpers
- */
-
-static int client_thread_rm_stream(struct cras_client *client,
- cras_stream_id_t stream_id);
-static int handle_message_from_server(struct cras_client *client);
-static int reregister_notifications(struct cras_client *client);
-
-static struct libcras_node_info *
-libcras_node_info_create(struct cras_iodev_info *iodev,
- struct cras_ionode_info *ionode);
-
-/*
- * Unlock the server_state_rwlock if lock_rc is 0.
- *
- * Args:
- * client - The CRAS client pointer.
- * lock_rc - The result of server_state_rdlock or
- * server_state_wrlock.
- */
-static void server_state_unlock(const struct cras_client *client, int lock_rc)
-{
- struct client_int *client_int;
-
- if (!client)
- return;
- client_int = to_client_int(client);
- if (lock_rc == 0)
- pthread_rwlock_unlock(&client_int->server_state_rwlock);
-}
-
-/*
- * Lock the server_state_rwlock for reading.
- *
- * Also checks that the server_state pointer is valid.
- *
- * Args:
- * client - The CRAS client pointer.
- * Returns:
- * 0 for success, positive error code on error.
- * Returns EINVAL if the server state pointer is NULL.
- */
-static int server_state_rdlock(const struct cras_client *client)
-{
- struct client_int *client_int;
- int lock_rc;
-
- if (!client)
- return EINVAL;
- client_int = to_client_int(client);
- lock_rc = pthread_rwlock_rdlock(&client_int->server_state_rwlock);
- if (lock_rc != 0)
- return lock_rc;
- if (!client->server_state) {
- pthread_rwlock_unlock(&client_int->server_state_rwlock);
- return EINVAL;
- }
- return 0;
-}
-
-/*
- * Lock the server_state_rwlock for writing.
- *
- * Args:
- * client - The CRAS client pointer.
- * Returns:
- * 0 for success, positive error code on error.
- */
-static int server_state_wrlock(const struct cras_client *client)
-{
- struct client_int *client_int;
-
- if (!client)
- return EINVAL;
- client_int = to_client_int(client);
- return pthread_rwlock_wrlock(&client_int->server_state_rwlock);
-}
-
-/* Get the stream pointer from a stream id. */
-static struct client_stream *stream_from_id(const struct cras_client *client,
- unsigned int id)
-{
- struct client_stream *out;
-
- DL_SEARCH_SCALAR(client->streams, out, id, id);
- return out;
-}
-
-/*
- * Fill a pollfd structure with the current server fd and events.
- */
-void server_fill_pollfd(const struct cras_client *client,
- struct pollfd *poll_fd)
-{
- int events = 0;
-
- poll_fd->fd = client->server_fd;
- switch (client->server_fd_state) {
- case CRAS_SOCKET_STATE_DISCONNECTED:
- break;
- case CRAS_SOCKET_STATE_WAIT_FOR_SOCKET:
- case CRAS_SOCKET_STATE_FIRST_MESSAGE:
- case CRAS_SOCKET_STATE_CONNECTED:
- case CRAS_SOCKET_STATE_ERROR_DELAY:
- events = POLLIN;
- break;
- case CRAS_SOCKET_STATE_WAIT_FOR_WRITABLE:
- events = POLLOUT;
- break;
- }
- poll_fd->events = events;
- poll_fd->revents = 0;
-}
-
-/*
- * Change the server_fd_state.
- */
-static void server_fd_move_to_state(struct cras_client *client,
- cras_socket_state_t state)
-{
- if (state == client->server_fd_state)
- return;
-
- client->server_fd_state = state;
-}
-
-/*
- * Action to take when in state ERROR_DELAY.
- *
- * In this state we want to sleep for a few seconds before retrying the
- * connection to the audio server.
- *
- * If server_fd is negative: create a timer and setup server_fd with the
- * timer's fd. If server_fd is not negative and there is input, then assume
- * that the timer has expired, and restart the connection by moving to
- * WAIT_FOR_SOCKET state.
- */
-static int error_delay_next_action(struct cras_client *client, int poll_revents)
-{
- int rc;
- struct itimerspec timeout;
-
- if (client->server_fd == -1) {
- client->server_fd = timerfd_create(CLOCK_MONOTONIC,
- TFD_NONBLOCK | TFD_CLOEXEC);
- if (client->server_fd == -1) {
- rc = -errno;
- syslog(LOG_ERR,
- "cras_client: Could not create timerfd: %s",
- strerror(-rc));
- return rc;
- }
-
- /* Setup a relative timeout of 2 seconds. */
- memset(&timeout, 0, sizeof(timeout));
- timeout.it_value.tv_sec = 2;
- rc = timerfd_settime(client->server_fd, 0, &timeout, NULL);
- if (rc != 0) {
- rc = -errno;
- syslog(LOG_ERR,
- "cras_client: Could not set timeout: %s",
- strerror(-rc));
- return rc;
- }
- return 0;
- } else if ((poll_revents & POLLIN) == 0) {
- return 0;
- }
-
- /* Move to the next state: close the timer fd first. */
- close(client->server_fd);
- client->server_fd = -1;
- server_fd_move_to_state(client, CRAS_SOCKET_STATE_WAIT_FOR_SOCKET);
- return 0;
-}
-
-/*
- * Action to take when in WAIT_FOR_SOCKET state.
- *
- * In this state we are waiting for the socket file to exist. The existence of
- * the socket file is continually monitored using the cras_file_wait structure
- * and a separate fd. When the sock_file_exists boolean is modified, the state
- * machine is invoked.
- *
- * If the socket file exists, then we move to the WAIT_FOR_WRITABLE state.
- */
-static void wait_for_socket_next_action(struct cras_client *client)
-{
- if (client->sock_file_exists)
- server_fd_move_to_state(client,
- CRAS_SOCKET_STATE_WAIT_FOR_WRITABLE);
-}
-
-/*
- * Action to take when in WAIT_FOR_WRITABLE state.
- *
- * In this state we are initiating a connection the server and waiting for the
- * server to ready for incoming messages.
- *
- * Create the socket to the server, and wait while a connect request results in
- * -EINPROGRESS. Otherwise, we assume that the socket file will be deleted by
- * the server and the server_fd_state will be changed in
- * sock_file_wait_dispatch().
- */
-static int wait_for_writable_next_action(struct cras_client *client,
- int poll_revents)
-{
- int rc;
- struct sockaddr_un address;
-
- if (client->server_fd == -1) {
- client->server_fd = socket(PF_UNIX, SOCK_SEQPACKET, 0);
- if (client->server_fd < 0) {
- rc = -errno;
- syslog(LOG_ERR, "cras_client: server socket failed: %s",
- strerror(-rc));
- return rc;
- }
- } else if ((poll_revents & POLLOUT) == 0) {
- return 0;
- }
-
- /* We make the file descriptor non-blocking when we do connect(), so we
- * don't block indefinitely. */
- cras_make_fd_nonblocking(client->server_fd);
-
- memset(&address, 0, sizeof(struct sockaddr_un));
- address.sun_family = AF_UNIX;
- strcpy(address.sun_path, client->sock_file);
- rc = connect(client->server_fd, (struct sockaddr *)&address,
- sizeof(struct sockaddr_un));
- if (rc != 0) {
- rc = -errno;
- /* For -EINPROGRESS, we wait for POLLOUT on the server_fd.
- * Otherwise CRAS is not running and we assume that the socket
- * file will be deleted and recreated. Notification of that will
- * happen via the sock_file_wait_dispatch(). */
- if (rc == -ECONNREFUSED) {
- /* CRAS is not running, don't log this error and just
- * stay in this state waiting sock_file_wait_dispatch()
- * to move the state machine. */
- close(client->server_fd);
- client->server_fd = -1;
- } else if (rc != -EINPROGRESS) {
- syslog(LOG_ERR,
- "cras_client: server connect failed: %s",
- strerror(-rc));
- return rc;
- }
- return 0;
- }
-
- cras_make_fd_blocking(client->server_fd);
- server_fd_move_to_state(client, CRAS_SOCKET_STATE_FIRST_MESSAGE);
- return 0;
-}
-
-/*
- * Action to take when transitioning to the CONNECTED state.
- */
-static int connect_transition_action(struct cras_client *client)
-{
- eventfd_t event_value;
- int rc;
-
- rc = reregister_notifications(client);
- if (rc < 0)
- return rc;
-
- server_fd_move_to_state(client, CRAS_SOCKET_STATE_CONNECTED);
- /* Notify anyone waiting on this state change that we're
- * connected. */
- eventfd_read(client->server_event_fd, &event_value);
- eventfd_write(client->server_event_fd, 1);
- if (client->server_connection_cb)
- client->server_connection_cb(
- client, CRAS_CONN_STATUS_CONNECTED,
- client->server_connection_user_arg);
- return 0;
-}
-
-/*
- * Action to take when in the FIRST_MESSAGE state.
- *
- * We are waiting for the first message from the server. When our client ID has
- * been set, then we can move to the CONNECTED state.
- */
-static int first_message_next_action(struct cras_client *client,
- int poll_revents)
-{
- int rc;
-
- if (client->server_fd < 0)
- return -EINVAL;
-
- if ((poll_revents & POLLIN) == 0)
- return 0;
-
- rc = handle_message_from_server(client);
- if (rc < 0) {
- syslog(LOG_ERR, "handle first message: %s", strerror(-rc));
- } else if (client->id >= 0) {
- rc = connect_transition_action(client);
- } else {
- syslog(LOG_ERR, "did not get ID after first message!");
- rc = -EINVAL;
- }
- return rc;
-}
-
-/*
- * Play nice and shutdown the server socket.
- */
-static inline int shutdown_and_close_socket(int sockfd)
-{
- int rc;
- uint8_t buffer[CRAS_CLIENT_MAX_MSG_SIZE];
- struct timeval tv;
-
- tv.tv_sec = 0;
- tv.tv_usec = SERVER_SHUTDOWN_TIMEOUT_US;
- setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv));
-
- rc = shutdown(sockfd, SHUT_WR);
- if (rc < 0)
- return rc;
- /* Wait until the socket is closed by the peer. */
- for (;;) {
- rc = recv(sockfd, buffer, sizeof(buffer), 0);
- if (rc <= 0)
- break;
- }
- return close(sockfd);
-}
-
-/*
- * Action to take when disconnecting from the server.
- *
- * Clean up the server socket, and the server_state pointer. Move to the next
- * logical state.
- */
-static void disconnect_transition_action(struct cras_client *client, bool force)
-{
- eventfd_t event_value;
- cras_socket_state_t old_state = client->server_fd_state;
- struct client_stream *s;
- int lock_rc;
-
- /* Stop all playing streams.
- * TODO(muirj): Pause and resume streams. */
- DL_FOREACH (client->streams, s) {
- s->config->err_cb(client, s->id, -ENOTCONN,
- s->config->user_data);
- client_thread_rm_stream(client, s->id);
- }
-
- /* Clean up the server_state pointer. */
- lock_rc = server_state_wrlock(client);
- if (client->server_state) {
- munmap((void *)client->server_state,
- sizeof(*client->server_state));
- client->server_state = NULL;
- }
- server_state_unlock(client, lock_rc);
-
- /* Our ID is unknown now. */
- client->id = -1;
-
- /* Clean up the server fd. */
- if (client->server_fd >= 0) {
- if (!force)
- shutdown_and_close_socket(client->server_fd);
- else
- close(client->server_fd);
- client->server_fd = -1;
- }
-
- /* Reset the server_event_fd value to 0 (and cause subsequent threads
- * waiting on the connection to wait). */
- eventfd_read(client->server_event_fd, &event_value);
-
- switch (old_state) {
- case CRAS_SOCKET_STATE_DISCONNECTED:
- /* Do nothing: already disconnected. */
- break;
- case CRAS_SOCKET_STATE_ERROR_DELAY:
- /* We're disconnected and there was a failure to setup
- * automatic reconnection, so call the server error
- * callback now. */
- server_fd_move_to_state(client, CRAS_SOCKET_STATE_DISCONNECTED);
- if (client->server_connection_cb)
- client->server_connection_cb(
- client, CRAS_CONN_STATUS_FAILED,
- client->server_connection_user_arg);
- break;
- case CRAS_SOCKET_STATE_WAIT_FOR_SOCKET:
- case CRAS_SOCKET_STATE_WAIT_FOR_WRITABLE:
- case CRAS_SOCKET_STATE_FIRST_MESSAGE:
- /* We are running this state transition while a connection is
- * in progress for an error case. When there is no error, we
- * come into this function in the DISCONNECTED state. */
- server_fd_move_to_state(client, CRAS_SOCKET_STATE_ERROR_DELAY);
- break;
- case CRAS_SOCKET_STATE_CONNECTED:
- /* Disconnected from CRAS (for an error), wait for the socket
- * file to be (re)created. */
- server_fd_move_to_state(client,
- CRAS_SOCKET_STATE_WAIT_FOR_SOCKET);
- /* Notify the caller that we aren't connected anymore. */
- if (client->server_connection_cb)
- client->server_connection_cb(
- client, CRAS_CONN_STATUS_DISCONNECTED,
- client->server_connection_user_arg);
- break;
- }
-}
-
-static int server_fd_dispatch(struct cras_client *client, int poll_revents)
-{
- int rc = 0;
- cras_socket_state_t old_state;
-
- if ((poll_revents & POLLHUP) != 0) {
- /* Error or disconnect: cleanup and make a state change now. */
- disconnect_transition_action(client, true);
- }
- old_state = client->server_fd_state;
-
- switch (client->server_fd_state) {
- case CRAS_SOCKET_STATE_DISCONNECTED:
- /* Assume that we've taken the necessary actions. */
- return -ENOTCONN;
- case CRAS_SOCKET_STATE_ERROR_DELAY:
- rc = error_delay_next_action(client, poll_revents);
- break;
- case CRAS_SOCKET_STATE_WAIT_FOR_SOCKET:
- wait_for_socket_next_action(client);
- break;
- case CRAS_SOCKET_STATE_WAIT_FOR_WRITABLE:
- rc = wait_for_writable_next_action(client, poll_revents);
- break;
- case CRAS_SOCKET_STATE_FIRST_MESSAGE:
- rc = first_message_next_action(client, poll_revents);
- break;
- case CRAS_SOCKET_STATE_CONNECTED:
- if ((poll_revents & POLLIN) != 0)
- rc = handle_message_from_server(client);
- break;
- }
-
- if (rc != 0) {
- /* If there is an error, then start-over. */
- rc = server_fd_dispatch(client, POLLHUP);
- } else if (old_state != client->server_fd_state) {
- /* There was a state change, process the new state now. */
- rc = server_fd_dispatch(client, 0);
- }
- return rc;
-}
-
-/*
- * Start connecting to the server if we aren't already.
- */
-static int server_connect(struct cras_client *client)
-{
- if (client->server_fd_state != CRAS_SOCKET_STATE_DISCONNECTED)
- return 0;
- /* Start waiting for the server socket to exist. */
- server_fd_move_to_state(client, CRAS_SOCKET_STATE_WAIT_FOR_SOCKET);
- return server_fd_dispatch(client, 0);
-}
-
-/*
- * Disconnect from the server if we haven't already.
- */
-static void server_disconnect(struct cras_client *client)
-{
- if (client->server_fd_state == CRAS_SOCKET_STATE_DISCONNECTED)
- return;
- /* Set the disconnected state first so that the disconnect
- * transition doesn't move the server state to ERROR_DELAY. */
- server_fd_move_to_state(client, CRAS_SOCKET_STATE_DISCONNECTED);
- disconnect_transition_action(client, false);
-}
-
-/*
- * Called when something happens to the socket file.
- */
-static void sock_file_wait_callback(void *context, cras_file_wait_event_t event,
- const char *filename)
-{
- struct cras_client *client = (struct cras_client *)context;
- switch (event) {
- case CRAS_FILE_WAIT_EVENT_CREATED:
- client->sock_file_exists = 1;
- switch (client->server_fd_state) {
- case CRAS_SOCKET_STATE_DISCONNECTED:
- case CRAS_SOCKET_STATE_ERROR_DELAY:
- case CRAS_SOCKET_STATE_FIRST_MESSAGE:
- case CRAS_SOCKET_STATE_CONNECTED:
- break;
- case CRAS_SOCKET_STATE_WAIT_FOR_SOCKET:
- case CRAS_SOCKET_STATE_WAIT_FOR_WRITABLE:
- /* The socket file exists. Tell the server state
- * machine. */
- server_fd_dispatch(client, 0);
- break;
- }
- break;
- case CRAS_FILE_WAIT_EVENT_DELETED:
- client->sock_file_exists = 0;
- switch (client->server_fd_state) {
- case CRAS_SOCKET_STATE_DISCONNECTED:
- break;
- case CRAS_SOCKET_STATE_WAIT_FOR_SOCKET:
- case CRAS_SOCKET_STATE_WAIT_FOR_WRITABLE:
- case CRAS_SOCKET_STATE_ERROR_DELAY:
- case CRAS_SOCKET_STATE_FIRST_MESSAGE:
- case CRAS_SOCKET_STATE_CONNECTED:
- /* Restart the connection process. */
- server_disconnect(client);
- server_connect(client);
- break;
- }
- break;
- case CRAS_FILE_WAIT_EVENT_NONE:
- break;
- }
-}
-
-/*
- * Service the sock_file_wait's fd.
- *
- * If the socket file is deleted, then cause a disconnect from the server.
- * Otherwise, start a reconnect depending on the server_fd_state.
- */
-static int sock_file_wait_dispatch(struct cras_client *client, int poll_revents)
-{
- int rc;
-
- if ((poll_revents & POLLIN) == 0)
- return 0;
-
- rc = cras_file_wait_dispatch(client->sock_file_wait);
- if (rc == -EAGAIN || rc == -EWOULDBLOCK)
- rc = 0;
- else if (rc != 0)
- syslog(LOG_ERR, "cras_file_wait_dispatch: %s", strerror(-rc));
- return rc;
-}
-
-/*
- * Waits until we have heard back from the server so that we know we are
- * connected.
- *
- * The connected success/failure message is always the first message the server
- * sends. Return non zero if client is connected to the server. A return code
- * of zero means that the client is not connected to the server.
- */
-static int check_server_connected_wait(struct cras_client *client,
- struct timespec *timeout)
-{
- int rc = 0;
- struct pollfd poll_fd;
-
- poll_fd.fd = client->server_event_fd;
- poll_fd.events = POLLIN;
- poll_fd.revents = 0;
-
- /* The server_event_fd is only read and written by the functions
- * that connect to the server. When a connection is established the
- * eventfd has a value of 1 and cras_poll will return immediately
- * with 1. When there is no connection to the server, then this
- * function waits until the timeout has expired or a non-zero value
- * is written to the server_event_fd. */
- while (rc == 0)
- rc = cras_poll(&poll_fd, 1, timeout, NULL);
- return rc > 0;
-}
-
-/* Returns non-zero if the thread is running (not stopped). */
-static inline int thread_is_running(struct thread_state *thread)
-{
- return thread->state != CRAS_THREAD_STOP;
-}
-
-/*
- * Opens the server socket and connects to it.
- * Args:
- * client - Client pointer created with cras_client_create().
- * timeout - Connection timeout.
- * Returns:
- * 0 for success, negative error code on failure.
- */
-static int connect_to_server(struct cras_client *client,
- struct timespec *timeout, bool use_command_thread)
-{
- int rc;
- struct pollfd poll_fd[2];
- struct timespec connected_timeout;
-
- if (!client)
- return -EINVAL;
-
- if (thread_is_running(&client->thread) && use_command_thread) {
- rc = cras_client_connect_async(client);
- if (rc == 0) {
- rc = check_server_connected_wait(client, timeout);
- return rc ? 0 : -ESHUTDOWN;
- }
- }
-
- connected_timeout.tv_sec = 0;
- connected_timeout.tv_nsec = 0;
- if (check_server_connected_wait(client, &connected_timeout))
- return 0;
-
- poll_fd[0].fd = cras_file_wait_get_fd(client->sock_file_wait);
- poll_fd[0].events = POLLIN;
-
- rc = server_connect(client);
- while (rc == 0) {
- // Wait until we've connected or until there is a timeout.
- // Meanwhile handle incoming actions on our fds.
-
- server_fill_pollfd(client, &(poll_fd[1]));
- rc = cras_poll(poll_fd, 2, timeout, NULL);
- if (rc <= 0)
- continue;
-
- if (poll_fd[0].revents) {
- rc = sock_file_wait_dispatch(client,
- poll_fd[0].revents);
- continue;
- }
-
- if (poll_fd[1].revents) {
- rc = server_fd_dispatch(client, poll_fd[1].revents);
- if (rc == 0 && client->server_fd_state ==
- CRAS_SOCKET_STATE_CONNECTED)
- break;
- }
- }
-
- if (rc != 0)
- syslog(LOG_ERR, "cras_client: Connect server failed: %s",
- strerror(-rc));
-
- return rc;
-}
-
-static int connect_to_server_wait_retry(struct cras_client *client,
- int timeout_ms, bool use_command_thread)
-{
- struct timespec timeout_value;
- struct timespec *timeout;
-
- if (timeout_ms < 0) {
- timeout = NULL;
- } else {
- timeout = &timeout_value;
- ms_to_timespec(timeout_ms, timeout);
- }
-
- /* If connected, wait for the first message from the server
- * indicating it's ready. */
- return connect_to_server(client, timeout, use_command_thread);
-}
-
-/*
- * Tries to connect to the server. Waits for the initial message from the
- * server. This will happen near instantaneously if the server is already
- * running.
- */
-static int connect_to_server_wait(struct cras_client *client,
- bool use_command_thread)
-{
- return connect_to_server_wait_retry(client, SERVER_CONNECT_TIMEOUT_MS,
- use_command_thread);
-}
-
-/*
- * Audio thread.
- */
-
-/* Sends a message from the stream to the client to indicate an error.
- * If the running stream encounters an error, then it must tell the client
- * to stop running it.
- */
-static int send_stream_message(const struct client_stream *stream,
- unsigned msg_id)
-{
- int res;
- struct stream_msg msg;
-
- msg.stream_id = stream->id;
- msg.msg_id = msg_id;
- res = write(stream->client->stream_fds[1], &msg, sizeof(msg));
- if (res != sizeof(msg))
- return -EPIPE;
-
- return 0;
-}
-
-/* Blocks until there is data to be read from the read_fd or until woken by an
- * incoming "poke" on wake_fd. Up to "len" bytes are read into "buf". */
-static int read_with_wake_fd(int wake_fd, int read_fd, uint8_t *buf, size_t len)
-{
- struct pollfd pollfds[2];
- int nread = 0;
- int nfds = 1;
- int rc;
- char tmp;
-
- pollfds[0].fd = wake_fd;
- pollfds[0].events = POLLIN;
- if (read_fd >= 0) {
- nfds++;
- pollfds[1].fd = read_fd;
- pollfds[1].events = POLLIN;
- }
-
- rc = poll(pollfds, nfds, -1);
- if (rc < 0)
- return rc;
- if (read_fd >= 0 && pollfds[1].revents & POLLIN) {
- nread = read(read_fd, buf, len);
- if (nread != (int)len)
- return -EIO;
- }
- if (pollfds[0].revents & POLLIN) {
- rc = read(wake_fd, &tmp, 1);
- if (rc < 0)
- return rc;
- }
-
- return nread;
-}
-/* Check the availability and configures a capture buffer.
- * Args:
- * stream - The input stream to configure buffer for.
- * captured_frames - To be filled with the pointer to the beginning of
- * captured buffer.
- * num_frames - Number of captured frames.
- * Returns:
- * Number of frames available in captured_frames.
- */
-static unsigned int config_capture_buf(struct client_stream *stream,
- uint8_t **captured_frames,
- unsigned int num_frames)
-{
- /* Always return the beginning of the read buffer because Chrome expects
- * so. */
- *captured_frames = cras_shm_get_read_buffer_base(stream->shm);
-
- /* Don't ask for more frames than the client desires. */
- if (stream->flags & BULK_AUDIO_OK)
- num_frames = MIN(num_frames, stream->config->buffer_frames);
- else
- num_frames = MIN(num_frames, stream->config->cb_threshold);
-
- /* If shm readable frames is less than client requests, that means
- * overrun has happened in server side. Don't send partial corrupted
- * buffer to client. */
- if (cras_shm_get_curr_read_frames(stream->shm) < num_frames)
- return 0;
-
- return num_frames;
-}
-
-static void complete_capture_read_current(struct client_stream *stream,
- unsigned int num_frames)
-{
- cras_shm_buffer_read_current(stream->shm, num_frames);
-}
-
-static int send_capture_reply(struct client_stream *stream, unsigned int frames,
- int err)
-{
- struct audio_message aud_msg;
- int rc;
-
- if (!cras_stream_uses_input_hw(stream->direction))
- return 0;
-
- aud_msg.id = AUDIO_MESSAGE_DATA_CAPTURED;
- aud_msg.frames = frames;
- aud_msg.error = err;
-
- rc = write(stream->aud_fd, &aud_msg, sizeof(aud_msg));
- if (rc != sizeof(aud_msg))
- return -EPIPE;
-
- return 0;
-}
-
-/* For capture streams this handles the message signalling that data is ready to
- * be passed to the user of this stream. Calls the audio callback with the new
- * samples, and mark them as read.
- * Args:
- * stream - The stream the message was received for.
- * num_frames - The number of captured frames.
- * Returns:
- * 0, unless there is a fatal error or the client declares enod of file.
- */
-static int handle_capture_data_ready(struct client_stream *stream,
- unsigned int num_frames)
-{
- int frames;
- struct cras_stream_params *config;
- uint8_t *captured_frames;
- struct timespec ts;
- int rc = 0;
- struct libcras_stream_cb_data *data;
-
- config = stream->config;
- /* If this message is for an output stream, log error and drop it. */
- if (!cras_stream_has_input(stream->direction)) {
- syslog(LOG_ERR, "cras_client: Play data to input\n");
- return 0;
- }
-
- num_frames = config_capture_buf(stream, &captured_frames, num_frames);
- if (num_frames == 0)
- return 0;
-
- cras_timespec_to_timespec(&ts, &stream->shm->header->ts);
-
- if (config->stream_cb) {
- data = libcras_stream_cb_data_create(
- stream->id, stream->direction, captured_frames,
- num_frames, ts, config->user_data);
- if (!data)
- return -errno;
- frames = config->stream_cb(data);
- libcras_stream_cb_data_destroy(data);
- data = NULL;
- } else if (config->unified_cb) {
- frames = config->unified_cb(stream->client, stream->id,
- captured_frames, NULL, num_frames,
- &ts, NULL, config->user_data);
- } else {
- frames = config->aud_cb(stream->client, stream->id,
- captured_frames, num_frames, &ts,
- config->user_data);
- }
- if (frames < 0) {
- send_stream_message(stream, CLIENT_STREAM_EOF);
- rc = frames;
- goto reply_captured;
- }
- if (frames == 0)
- return 0;
-
- complete_capture_read_current(stream, frames);
-reply_captured:
- return send_capture_reply(stream, frames, rc);
-}
-
-/* Notifies the server that "frames" samples have been written. */
-static int send_playback_reply(struct client_stream *stream,
- unsigned int frames, int error)
-{
- struct audio_message aud_msg;
- int rc;
-
- if (!cras_stream_uses_output_hw(stream->direction))
- return 0;
-
- aud_msg.id = AUDIO_MESSAGE_DATA_READY;
- aud_msg.frames = frames;
- aud_msg.error = error;
-
- rc = write(stream->aud_fd, &aud_msg, sizeof(aud_msg));
- if (rc != sizeof(aud_msg))
- return -EPIPE;
-
- return 0;
-}
-
-/* For playback streams when current buffer is empty, this handles the request
- * for more samples by calling the audio callback for the thread, and signaling
- * the server that the samples have been written. */
-static int handle_playback_request(struct client_stream *stream,
- unsigned int num_frames)
-{
- uint8_t *buf;
- int frames;
- int rc = 0;
- struct cras_stream_params *config;
- struct cras_audio_shm *shm = stream->shm;
- struct timespec ts;
- struct libcras_stream_cb_data *data;
-
- config = stream->config;
-
- /* If this message is for an input stream, log error and drop it. */
- if (stream->direction != CRAS_STREAM_OUTPUT) {
- syslog(LOG_ERR, "cras_client: Record data from output\n");
- return 0;
- }
-
- buf = cras_shm_get_write_buffer_base(shm);
-
- /* Limit the amount of frames to the configured amount. */
- num_frames = MIN(num_frames, config->cb_threshold);
-
- cras_timespec_to_timespec(&ts, &shm->header->ts);
-
- /* Get samples from the user */
- if (config->stream_cb) {
- data = libcras_stream_cb_data_create(stream->id,
- stream->direction, buf,
- num_frames, ts,
- config->user_data);
- if (!data)
- return -errno;
- frames = config->stream_cb(data);
- libcras_stream_cb_data_destroy(data);
- data = NULL;
- } else if (config->unified_cb) {
- frames = config->unified_cb(stream->client, stream->id, NULL,
- buf, num_frames, NULL, &ts,
- config->user_data);
- } else {
- frames = config->aud_cb(stream->client, stream->id, buf,
- num_frames, &ts, config->user_data);
- }
- if (frames < 0) {
- send_stream_message(stream, CLIENT_STREAM_EOF);
- rc = frames;
- goto reply_written;
- }
-
- cras_shm_buffer_written_start(shm, frames);
-
-reply_written:
- /* Signal server that data is ready, or that an error has occurred. */
- rc = send_playback_reply(stream, frames, rc);
- return rc;
-}
-
-static void audio_thread_set_priority(struct client_stream *stream)
-{
- /* Use provided callback to set priority if available. */
- if (stream->client->thread_priority_cb) {
- stream->client->thread_priority_cb(stream->client);
- return;
- }
-
- /* Try to get RT scheduling, if that fails try to set the nice value. */
- if (cras_set_rt_scheduling(CRAS_CLIENT_RT_THREAD_PRIORITY) ||
- cras_set_thread_priority(CRAS_CLIENT_RT_THREAD_PRIORITY))
- cras_set_nice_level(CRAS_CLIENT_NICENESS_LEVEL);
-}
-
-/* Listens to the audio socket for messages from the server indicating that
- * the stream needs to be serviced. One of these runs per stream. */
-static void *audio_thread(void *arg)
-{
- struct client_stream *stream = (struct client_stream *)arg;
- int thread_terminated = 0;
- struct audio_message aud_msg;
- int aud_fd;
- int num_read;
-
- if (arg == NULL)
- return (void *)-EIO;
-
- audio_thread_set_priority(stream);
-
- /* Notify the control thread that we've started. */
- pthread_mutex_lock(&stream->client->stream_start_lock);
- pthread_cond_broadcast(&stream->client->stream_start_cond);
- pthread_mutex_unlock(&stream->client->stream_start_lock);
-
- while (thread_is_running(&stream->thread) && !thread_terminated) {
- /* While we are warming up, aud_fd may not be valid and some
- * shared memory resources may not yet be available. */
- aud_fd = (stream->thread.state == CRAS_THREAD_WARMUP) ?
- -1 :
- stream->aud_fd;
- num_read =
- read_with_wake_fd(stream->wake_fds[0], aud_fd,
- (uint8_t *)&aud_msg, sizeof(aud_msg));
- if (num_read < 0)
- return (void *)-EIO;
- if (num_read == 0)
- continue;
-
- switch (aud_msg.id) {
- case AUDIO_MESSAGE_DATA_READY:
- thread_terminated = handle_capture_data_ready(
- stream, aud_msg.frames);
- break;
- case AUDIO_MESSAGE_REQUEST_DATA:
- thread_terminated =
- handle_playback_request(stream, aud_msg.frames);
- break;
- default:
- break;
- }
- }
-
- return NULL;
-}
-
-/* Pokes the audio thread so that it can notice if it has been terminated. */
-static int wake_aud_thread(struct client_stream *stream)
-{
- int rc;
-
- rc = write(stream->wake_fds[1], &rc, 1);
- if (rc != 1)
- return rc;
- return 0;
-}
-
-/* Stop the audio thread for the given stream.
- * Args:
- * stream - Stream for which to stop the audio thread.
- * join - When non-zero, attempt to join the audio thread (wait for it to
- * complete).
- */
-static void stop_aud_thread(struct client_stream *stream, int join)
-{
- if (thread_is_running(&stream->thread)) {
- stream->thread.state = CRAS_THREAD_STOP;
- wake_aud_thread(stream);
- if (join)
- pthread_join(stream->thread.tid, NULL);
- }
-
- if (stream->wake_fds[0] >= 0) {
- close(stream->wake_fds[0]);
- close(stream->wake_fds[1]);
- stream->wake_fds[0] = -1;
- }
-}
-
-/* Start the audio thread for this stream.
- * Returns when the thread has started and is waiting.
- * Args:
- * stream - The stream that needs an audio thread.
- * Returns:
- * 0 for success, or a negative error code.
- */
-static int start_aud_thread(struct client_stream *stream)
-{
- int rc;
- struct timespec future;
-
- rc = pipe(stream->wake_fds);
- if (rc < 0) {
- rc = -errno;
- syslog(LOG_ERR, "cras_client: pipe: %s", strerror(-rc));
- return rc;
- }
-
- stream->thread.state = CRAS_THREAD_WARMUP;
-
- pthread_mutex_lock(&stream->client->stream_start_lock);
- rc = pthread_create(&stream->thread.tid, NULL, audio_thread, stream);
- if (rc) {
- pthread_mutex_unlock(&stream->client->stream_start_lock);
- syslog(LOG_ERR, "cras_client: Couldn't create audio stream: %s",
- strerror(rc));
- stream->thread.state = CRAS_THREAD_STOP;
- stop_aud_thread(stream, 0);
- return -rc;
- }
-
- clock_gettime(CLOCK_REALTIME, &future);
- future.tv_sec += 2; /* Wait up to two seconds. */
- rc = pthread_cond_timedwait(&stream->client->stream_start_cond,
- &stream->client->stream_start_lock,
- &future);
- pthread_mutex_unlock(&stream->client->stream_start_lock);
- if (rc != 0) {
- /* Something is very wrong: try to cancel the thread and don't
- * wait for it. */
- syslog(LOG_ERR, "cras_client: Client thread not responding: %s",
- strerror(rc));
- stop_aud_thread(stream, 0);
- return -rc;
- }
- return 0;
-}
-
-/*
- * Client thread.
- */
-
-/* Gets the update_count of the server state shm region. */
-static inline unsigned
-begin_server_state_read(const struct cras_server_state *state)
-{
- unsigned count;
-
- /* Version will be odd when the server is writing. */
- while ((count = *(volatile unsigned *)&state->update_count) & 1)
- sched_yield();
- __sync_synchronize();
- return count;
-}
-
-/* Checks if the update count of the server state shm region has changed from
- * count. Returns 0 if the count still matches.
- */
-static inline int end_server_state_read(const struct cras_server_state *state,
- unsigned count)
-{
- __sync_synchronize();
- if (count != *(volatile unsigned *)&state->update_count)
- return -EAGAIN;
- return 0;
-}
-
-/* Release shm areas if references to them are held. */
-static void free_shm(struct client_stream *stream)
-{
- cras_audio_shm_destroy(stream->shm);
- stream->shm = NULL;
-}
-
-/* Handles the stream connected message from the server. Check if we need a
- * format converter, configure the shared memory region, and start the audio
- * thread that will handle requests from the server. */
-static int stream_connected(struct client_stream *stream,
- const struct cras_client_stream_connected *msg,
- const int stream_fds[2], const unsigned int num_fds)
-{
- int rc, samples_prot;
- unsigned int i;
- struct cras_shm_info header_info, samples_info;
-
- if (msg->err || num_fds != 2) {
- syslog(LOG_ERR, "cras_client: Error setting up stream %d\n",
- msg->err);
- rc = msg->err;
- goto err_ret;
- }
-
- rc = cras_shm_info_init_with_fd(stream_fds[0], cras_shm_header_size(),
- &header_info);
- if (rc < 0)
- goto err_ret;
-
- rc = cras_shm_info_init_with_fd(stream_fds[1], msg->samples_shm_size,
- &samples_info);
- if (rc < 0) {
- cras_shm_info_cleanup(&header_info);
- goto err_ret;
- }
-
- if (stream->direction == CRAS_STREAM_OUTPUT)
- samples_prot = PROT_WRITE;
- else
- samples_prot = PROT_READ;
-
- rc = cras_audio_shm_create(&header_info, &samples_info, samples_prot,
- &stream->shm);
- if (rc < 0) {
- syslog(LOG_ERR, "cras_client: Error configuring shm");
- goto err_ret;
- }
- cras_shm_copy_shared_config(stream->shm);
- cras_shm_set_volume_scaler(stream->shm, stream->volume_scaler);
-
- stream->thread.state = CRAS_THREAD_RUNNING;
- wake_aud_thread(stream);
-
- close(stream_fds[0]);
- close(stream_fds[1]);
- return 0;
-err_ret:
- stop_aud_thread(stream, 1);
- for (i = 0; i < num_fds; i++)
- close(stream_fds[i]);
- free_shm(stream);
- return rc;
-}
-
-static int send_connect_message(struct cras_client *client,
- struct client_stream *stream, uint32_t dev_idx)
-{
- int rc;
- struct cras_connect_message serv_msg;
- int sock[2] = { -1, -1 };
-
- /* Create a socket pair for the server to notify of audio events. */
- rc = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
- if (rc != 0) {
- rc = -errno;
- syslog(LOG_ERR, "cras_client: socketpair: %s", strerror(-rc));
- goto fail;
- }
-
- cras_fill_connect_message(&serv_msg, stream->config->direction,
- stream->id, stream->config->stream_type,
- stream->config->client_type,
- stream->config->buffer_frames,
- stream->config->cb_threshold, stream->flags,
- stream->config->effects,
- stream->config->format, dev_idx);
-
- rc = cras_send_with_fds(client->server_fd, &serv_msg, sizeof(serv_msg),
- &sock[1], 1);
- if (rc != sizeof(serv_msg)) {
- rc = EIO;
- syslog(LOG_ERR,
- "cras_client: add_stream: Send server message failed.");
- goto fail;
- }
-
- stream->aud_fd = sock[0];
- close(sock[1]);
- return 0;
-
-fail:
- if (sock[0] != -1)
- close(sock[0]);
- if (sock[1] != -1)
- close(sock[1]);
- return rc;
-}
-
-/* Adds a stream to a running client. Checks to make sure that the client is
- * attached, waits if it isn't. The stream is prepared on the main thread and
- * passed here. */
-static int client_thread_add_stream(struct cras_client *client,
- struct client_stream *stream,
- cras_stream_id_t *stream_id_out,
- uint32_t dev_idx)
-{
- int rc;
- cras_stream_id_t new_id;
- struct client_stream *out;
-
- if ((stream->flags & HOTWORD_STREAM) == HOTWORD_STREAM) {
- int hotword_idx;
- hotword_idx = cras_client_get_first_dev_type_idx(
- client, CRAS_NODE_TYPE_HOTWORD, CRAS_STREAM_INPUT);
-
- /* Find the hotword device index. */
- if (dev_idx == NO_DEVICE) {
- if (hotword_idx < 0) {
- syslog(LOG_ERR,
- "cras_client: add_stream: No hotword dev");
- return hotword_idx;
- } else {
- dev_idx = (uint32_t)hotword_idx;
- }
- }
- /* A known Use case for client to pin hotword stream on a not
- * hotword device is to use internal mic for Assistant to work
- * on board without usable DSP hotwording. We assume there will
- * be only one hotword device exists. */
- else if (dev_idx != (uint32_t)hotword_idx) {
- /* Unmask the flag to fallback to normal pinned stream
- * on specified device. */
- stream->flags &= ~HOTWORD_STREAM;
- }
- }
-
- /* Find an available stream id. */
- do {
- new_id = cras_get_stream_id(client->id, client->next_stream_id);
- client->next_stream_id++;
- DL_SEARCH_SCALAR(client->streams, out, id, new_id);
- } while (out != NULL);
-
- stream->id = new_id;
- *stream_id_out = new_id;
- stream->client = client;
-
- /* Start the audio thread. */
- rc = start_aud_thread(stream);
- if (rc != 0)
- return rc;
-
- /* Start the thread associated with this stream. */
- /* send a message to the server asking that the stream be started. */
- rc = send_connect_message(client, stream, dev_idx);
- if (rc != 0) {
- stop_aud_thread(stream, 1);
- return rc;
- }
-
- /* Add the stream to the linked list */
- DL_APPEND(client->streams, stream);
-
- return 0;
-}
-
-/* Removes a stream from a running client from within the running client's
- * context. */
-static int client_thread_rm_stream(struct cras_client *client,
- cras_stream_id_t stream_id)
-{
- struct cras_disconnect_stream_message msg;
- struct client_stream *stream = stream_from_id(client, stream_id);
- int rc;
-
- if (stream == NULL)
- return 0;
-
- /* Tell server to remove. */
- if (client->server_fd_state == CRAS_SOCKET_STATE_CONNECTED) {
- cras_fill_disconnect_stream_message(&msg, stream_id);
- rc = write(client->server_fd, &msg, sizeof(msg));
- if (rc < 0)
- syslog(LOG_ERR,
- "cras_client: error removing stream from server\n");
- }
-
- /* And shut down locally. */
- stop_aud_thread(stream, 1);
-
- free_shm(stream);
-
- DL_DELETE(client->streams, stream);
- if (stream->aud_fd >= 0)
- close(stream->aud_fd);
-
- free(stream->config);
- free(stream);
-
- return 0;
-}
-
-/* Sets the volume scaling factor for a playback or capture stream. */
-static int client_thread_set_stream_volume(struct cras_client *client,
- cras_stream_id_t stream_id,
- float volume_scaler)
-{
- struct client_stream *stream;
-
- stream = stream_from_id(client, stream_id);
- if (stream == NULL || volume_scaler > 1.0 || volume_scaler < 0.0)
- return -EINVAL;
-
- stream->volume_scaler = volume_scaler;
- if (stream->shm)
- cras_shm_set_volume_scaler(stream->shm, volume_scaler);
-
- return 0;
-}
-
-/* Attach to the shm region containing the audio thread log. */
-static void attach_atlog_shm(struct cras_client *client, int fd)
-{
- client->atlog_ro = (struct audio_thread_event_log *)mmap(
- NULL, sizeof(*client->atlog_ro), PROT_READ, MAP_SHARED, fd, 0);
- close(fd);
-}
-
-/* Attach to the shm region containing the server state. */
-static int client_attach_shm(struct cras_client *client, int shm_fd)
-{
- int lock_rc;
- int rc;
-
- lock_rc = server_state_wrlock(client);
- if (client->server_state) {
- rc = -EBUSY;
- goto error;
- }
-
- client->server_state = (struct cras_server_state *)mmap(
- NULL, sizeof(*client->server_state), PROT_READ, MAP_SHARED,
- shm_fd, 0);
- rc = -errno;
- close(shm_fd);
- if (client->server_state == (struct cras_server_state *)-1) {
- syslog(LOG_ERR,
- "cras_client: mmap failed to map shm for client: %s",
- strerror(-rc));
- goto error;
- }
-
- if (client->server_state->state_version != CRAS_SERVER_STATE_VERSION) {
- munmap((void *)client->server_state,
- sizeof(*client->server_state));
- client->server_state = NULL;
- rc = -EINVAL;
- syslog(LOG_ERR, "cras_client: Unknown server_state version.");
- } else {
- rc = 0;
- }
-
-error:
- server_state_unlock(client, lock_rc);
- return rc;
-}
-
-static void cras_client_get_hotword_models_ready(struct cras_client *client,
- const char *hotword_models)
-{
- if (!client->get_hotword_models_cb)
- return;
- client->get_hotword_models_cb(client, hotword_models);
- client->get_hotword_models_cb = NULL;
-}
-
-/* Handles messages from the cras server. */
-static int handle_message_from_server(struct cras_client *client)
-{
- uint8_t buf[CRAS_CLIENT_MAX_MSG_SIZE];
- struct cras_client_message *msg;
- int rc = 0;
- int nread;
- int server_fds[2];
- unsigned int num_fds = 2;
-
- msg = (struct cras_client_message *)buf;
- nread = cras_recv_with_fds(client->server_fd, buf, sizeof(buf),
- server_fds, &num_fds);
- if (nread < (int)sizeof(msg->length) || (int)msg->length != nread)
- return -EIO;
-
- switch (msg->id) {
- case CRAS_CLIENT_CONNECTED: {
- struct cras_client_connected *cmsg =
- (struct cras_client_connected *)msg;
- if (num_fds != 1)
- return -EINVAL;
- rc = client_attach_shm(client, server_fds[0]);
- if (rc)
- return rc;
- client->id = cmsg->client_id;
-
- break;
- }
- case CRAS_CLIENT_STREAM_CONNECTED: {
- struct cras_client_stream_connected *cmsg =
- (struct cras_client_stream_connected *)msg;
- struct client_stream *stream =
- stream_from_id(client, cmsg->stream_id);
- if (stream == NULL) {
- if (num_fds != 2) {
- syslog(LOG_ERR,
- "cras_client: Error receiving "
- "stream 0x%x connected message",
- cmsg->stream_id);
- return -EINVAL;
- }
-
- /*
- * Usually, the fds should be closed in stream_connected
- * callback. However, sometimes a stream is removed
- * before it is connected.
- */
- close(server_fds[0]);
- close(server_fds[1]);
- break;
- }
- rc = stream_connected(stream, cmsg, server_fds, num_fds);
- if (rc < 0)
- stream->config->err_cb(stream->client, stream->id, rc,
- stream->config->user_data);
- break;
- }
- case CRAS_CLIENT_AUDIO_DEBUG_INFO_READY:
- if (client->debug_info_callback)
- client->debug_info_callback(client);
- client->debug_info_callback = NULL;
- break;
- case CRAS_CLIENT_ATLOG_FD_READY:
- if (num_fds != 1 || server_fds[0] < 0)
- return -EINVAL;
- attach_atlog_shm(client, server_fds[0]);
- if (client->atlog_access_callback)
- client->atlog_access_callback(client);
- client->atlog_access_callback = NULL;
- break;
- case CRAS_CLIENT_GET_HOTWORD_MODELS_READY: {
- struct cras_client_get_hotword_models_ready *cmsg =
- (struct cras_client_get_hotword_models_ready *)msg;
- cras_client_get_hotword_models_ready(
- client, (const char *)cmsg->hotword_models);
- break;
- }
- case CRAS_CLIENT_OUTPUT_VOLUME_CHANGED: {
- struct cras_client_volume_changed *cmsg =
- (struct cras_client_volume_changed *)msg;
- if (client->observer_ops.output_volume_changed)
- client->observer_ops.output_volume_changed(
- client->observer_context, cmsg->volume);
- break;
- }
- case CRAS_CLIENT_OUTPUT_MUTE_CHANGED: {
- struct cras_client_mute_changed *cmsg =
- (struct cras_client_mute_changed *)msg;
- if (client->observer_ops.output_mute_changed)
- client->observer_ops.output_mute_changed(
- client->observer_context, cmsg->muted,
- cmsg->user_muted, cmsg->mute_locked);
- break;
- }
- case CRAS_CLIENT_CAPTURE_GAIN_CHANGED: {
- struct cras_client_volume_changed *cmsg =
- (struct cras_client_volume_changed *)msg;
- if (client->observer_ops.capture_gain_changed)
- client->observer_ops.capture_gain_changed(
- client->observer_context, cmsg->volume);
- break;
- }
- case CRAS_CLIENT_CAPTURE_MUTE_CHANGED: {
- struct cras_client_mute_changed *cmsg =
- (struct cras_client_mute_changed *)msg;
- if (client->observer_ops.capture_mute_changed)
- client->observer_ops.capture_mute_changed(
- client->observer_context, cmsg->muted,
- cmsg->mute_locked);
- break;
- }
- case CRAS_CLIENT_NODES_CHANGED: {
- if (client->observer_ops.nodes_changed)
- client->observer_ops.nodes_changed(
- client->observer_context);
- break;
- }
- case CRAS_CLIENT_ACTIVE_NODE_CHANGED: {
- struct cras_client_active_node_changed *cmsg =
- (struct cras_client_active_node_changed *)msg;
- enum CRAS_STREAM_DIRECTION direction =
- (enum CRAS_STREAM_DIRECTION)cmsg->direction;
- if (client->observer_ops.active_node_changed)
- client->observer_ops.active_node_changed(
- client->observer_context, direction,
- cmsg->node_id);
- break;
- }
- case CRAS_CLIENT_OUTPUT_NODE_VOLUME_CHANGED: {
- struct cras_client_node_value_changed *cmsg =
- (struct cras_client_node_value_changed *)msg;
- if (client->observer_ops.output_node_volume_changed)
- client->observer_ops.output_node_volume_changed(
- client->observer_context, cmsg->node_id,
- cmsg->value);
- break;
- }
- case CRAS_CLIENT_NODE_LEFT_RIGHT_SWAPPED_CHANGED: {
- struct cras_client_node_value_changed *cmsg =
- (struct cras_client_node_value_changed *)msg;
- if (client->observer_ops.node_left_right_swapped_changed)
- client->observer_ops.node_left_right_swapped_changed(
- client->observer_context, cmsg->node_id,
- cmsg->value);
- break;
- }
- case CRAS_CLIENT_INPUT_NODE_GAIN_CHANGED: {
- struct cras_client_node_value_changed *cmsg =
- (struct cras_client_node_value_changed *)msg;
- if (client->observer_ops.input_node_gain_changed)
- client->observer_ops.input_node_gain_changed(
- client->observer_context, cmsg->node_id,
- cmsg->value);
- break;
- }
- case CRAS_CLIENT_NUM_ACTIVE_STREAMS_CHANGED: {
- struct cras_client_num_active_streams_changed *cmsg =
- (struct cras_client_num_active_streams_changed *)msg;
- enum CRAS_STREAM_DIRECTION direction =
- (enum CRAS_STREAM_DIRECTION)cmsg->direction;
- if (client->observer_ops.num_active_streams_changed)
- client->observer_ops.num_active_streams_changed(
- client->observer_context, direction,
- cmsg->num_active_streams);
- break;
- }
- default:
- break;
- }
-
- return 0;
-}
-
-/* Handles messages from streams to this client. */
-static int handle_stream_message(struct cras_client *client, int poll_revents)
-{
- struct stream_msg msg;
- int rc;
-
- if ((poll_revents & POLLIN) == 0)
- return 0;
-
- rc = read(client->stream_fds[0], &msg, sizeof(msg));
- if (rc < 0)
- syslog(LOG_ERR, "cras_client: Stream read failed %d\n", errno);
- /* The only reason a stream sends a message is if it needs to be
- * removed. An error on read would mean the same thing so regardless of
- * what gets us here, just remove the stream */
- client_thread_rm_stream(client, msg.stream_id);
- return 0;
-}
-
-/* Handles messages from users to this client. */
-static int handle_command_message(struct cras_client *client, int poll_revents)
-{
- uint8_t buf[MAX_CMD_MSG_LEN];
- struct command_msg *msg = (struct command_msg *)buf;
- int rc, to_read;
-
- if ((poll_revents & POLLIN) == 0)
- return 0;
-
- rc = read(client->command_fds[0], buf, sizeof(msg->len));
- if (rc != sizeof(msg->len) || msg->len > MAX_CMD_MSG_LEN) {
- rc = -EIO;
- goto cmd_msg_complete;
- }
- to_read = msg->len - rc;
- rc = read(client->command_fds[0], &buf[0] + rc, to_read);
- if (rc != to_read) {
- rc = -EIO;
- goto cmd_msg_complete;
- }
-
- switch (msg->msg_id) {
- case CLIENT_STOP: {
- struct client_stream *s;
-
- /* Stop all playing streams */
- DL_FOREACH (client->streams, s)
- client_thread_rm_stream(client, s->id);
-
- /* And stop this client */
- client->thread.state = CRAS_THREAD_STOP;
- rc = 0;
- break;
- }
- case CLIENT_ADD_STREAM: {
- struct add_stream_command_message *add_msg =
- (struct add_stream_command_message *)msg;
- rc = client_thread_add_stream(client, add_msg->stream,
- add_msg->stream_id_out,
- add_msg->dev_idx);
- break;
- }
- case CLIENT_REMOVE_STREAM:
- rc = client_thread_rm_stream(client, msg->stream_id);
- break;
- case CLIENT_SET_STREAM_VOLUME_SCALER: {
- struct set_stream_volume_command_message *vol_msg =
- (struct set_stream_volume_command_message *)msg;
- rc = client_thread_set_stream_volume(client,
- vol_msg->header.stream_id,
- vol_msg->volume_scaler);
- break;
- }
- case CLIENT_SERVER_CONNECT:
- rc = connect_to_server_wait(client, false);
- break;
- case CLIENT_SERVER_CONNECT_ASYNC:
- rc = server_connect(client);
- break;
- default:
- assert(0);
- break;
- }
-
-cmd_msg_complete:
- /* Wake the waiting main thread with the result of the command. */
- if (write(client->command_reply_fds[1], &rc, sizeof(rc)) != sizeof(rc))
- return -EIO;
- return rc;
-}
-
-/* This thread handles non audio sample communication with the audio server.
- * The client program will call fucntions below to send messages to this thread
- * to add or remove streams or change parameters.
- */
-static void *client_thread(void *arg)
-{
- struct cras_client *client = (struct cras_client *)arg;
- struct pollfd pollfds[4];
- int (*cbs[4])(struct cras_client * client, int poll_revents);
- unsigned int num_pollfds, i;
- int rc;
-
- if (arg == NULL)
- return (void *)-EINVAL;
-
- while (thread_is_running(&client->thread)) {
- num_pollfds = 0;
-
- rc = cras_file_wait_get_fd(client->sock_file_wait);
- if (rc >= 0) {
- cbs[num_pollfds] = sock_file_wait_dispatch;
- pollfds[num_pollfds].fd = rc;
- pollfds[num_pollfds].events = POLLIN;
- pollfds[num_pollfds].revents = 0;
- num_pollfds++;
- } else
- syslog(LOG_ERR, "file wait fd: %d", rc);
- if (client->server_fd >= 0) {
- cbs[num_pollfds] = server_fd_dispatch;
- server_fill_pollfd(client, &(pollfds[num_pollfds]));
- num_pollfds++;
- }
- if (client->command_fds[0] >= 0) {
- cbs[num_pollfds] = handle_command_message;
- pollfds[num_pollfds].fd = client->command_fds[0];
- pollfds[num_pollfds].events = POLLIN;
- pollfds[num_pollfds].revents = 0;
- num_pollfds++;
- }
- if (client->stream_fds[0] >= 0) {
- cbs[num_pollfds] = handle_stream_message;
- pollfds[num_pollfds].fd = client->stream_fds[0];
- pollfds[num_pollfds].events = POLLIN;
- pollfds[num_pollfds].revents = 0;
- num_pollfds++;
- }
-
- rc = poll(pollfds, num_pollfds, -1);
- if (rc <= 0)
- continue;
-
- for (i = 0; i < num_pollfds; i++) {
- /* Only do one at a time, since some messages may
- * result in change to other fds. */
- if (pollfds[i].revents) {
- cbs[i](client, pollfds[i].revents);
- break;
- }
- }
- }
-
- /* close the command reply pipe. */
- close(client->command_reply_fds[1]);
- client->command_reply_fds[1] = -1;
-
- return NULL;
-}
-
-/* Sends a message to the client thread to complete an action requested by the
- * user. Then waits for the action to complete and returns the result. */
-static int send_command_message(struct cras_client *client,
- struct command_msg *msg)
-{
- int rc, cmd_res;
- if (client == NULL || !thread_is_running(&client->thread))
- return -EINVAL;
-
- rc = write(client->command_fds[1], msg, msg->len);
- if (rc != (int)msg->len)
- return -EPIPE;
-
- /* Wait for command to complete. */
- rc = read(client->command_reply_fds[0], &cmd_res, sizeof(cmd_res));
- if (rc != sizeof(cmd_res))
- return -EPIPE;
- return cmd_res;
-}
-
-/* Send a simple message to the client thread that holds no data. */
-static int send_simple_cmd_msg(struct cras_client *client,
- cras_stream_id_t stream_id, unsigned msg_id)
-{
- struct command_msg msg;
-
- msg.len = sizeof(msg);
- msg.stream_id = stream_id;
- msg.msg_id = msg_id;
-
- return send_command_message(client, &msg);
-}
-
-/* Sends the set volume message to the client thread. */
-static int send_stream_volume_command_msg(struct cras_client *client,
- cras_stream_id_t stream_id,
- float volume_scaler)
-{
- struct set_stream_volume_command_message msg;
-
- msg.header.len = sizeof(msg);
- msg.header.stream_id = stream_id;
- msg.header.msg_id = CLIENT_SET_STREAM_VOLUME_SCALER;
- msg.volume_scaler = volume_scaler;
-
- return send_command_message(client, &msg.header);
-}
-
-/* Sends a message back to the client and returns the error code. */
-static int write_message_to_server(struct cras_client *client,
- const struct cras_server_message *msg)
-{
- ssize_t write_rc = -EPIPE;
-
- if (client->server_fd_state == CRAS_SOCKET_STATE_CONNECTED ||
- client->server_fd_state == CRAS_SOCKET_STATE_FIRST_MESSAGE) {
- write_rc = write(client->server_fd, msg, msg->length);
- if (write_rc < 0)
- write_rc = -errno;
- }
-
- if (write_rc != (ssize_t)msg->length &&
- client->server_fd_state != CRAS_SOCKET_STATE_FIRST_MESSAGE)
- return -EPIPE;
-
- if (write_rc < 0)
- return write_rc;
- else if (write_rc != (ssize_t)msg->length)
- return -EIO;
- else
- return 0;
-}
-
-/* Fills server socket file to connect by client's connection type. */
-static int fill_socket_file(struct cras_client *client,
- enum CRAS_CONNECTION_TYPE conn_type)
-{
- int rc;
-
- client->sock_file =
- (const char *)calloc(CRAS_MAX_SOCKET_PATH_SIZE, sizeof(char));
- if (client->sock_file == NULL)
- return -ENOMEM;
-
- rc = cras_fill_socket_path(conn_type, (char *)client->sock_file);
- if (rc < 0) {
- free((void *)client->sock_file);
- return rc;
- }
- return 0;
-}
-
-/*
- * Exported Client Interface
- */
-
-int cras_client_create_with_type(struct cras_client **client,
- enum CRAS_CONNECTION_TYPE conn_type)
-{
- int rc;
- struct client_int *client_int;
- pthread_condattr_t cond_attr;
-
- if (!cras_validate_connection_type(conn_type)) {
- syslog(LOG_ERR, "Input connection type is not supported.\n");
- return -EINVAL;
- }
-
- /* Ignore SIGPIPE while using this API. */
- signal(SIGPIPE, SIG_IGN);
-
- client_int = (struct client_int *)calloc(1, sizeof(*client_int));
- if (!client_int)
- return -ENOMEM;
- *client = &client_int->client;
- (*client)->server_fd = -1;
- (*client)->id = -1;
-
- rc = pthread_rwlock_init(&client_int->server_state_rwlock, NULL);
- if (rc != 0) {
- syslog(LOG_ERR, "cras_client: Could not init state rwlock.");
- rc = -rc;
- goto free_client;
- }
-
- rc = pthread_mutex_init(&(*client)->stream_start_lock, NULL);
- if (rc != 0) {
- syslog(LOG_ERR, "cras_client: Could not init start lock.");
- rc = -rc;
- goto free_rwlock;
- }
-
- pthread_condattr_init(&cond_attr);
- pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
- rc = pthread_cond_init(&(*client)->stream_start_cond, &cond_attr);
- pthread_condattr_destroy(&cond_attr);
- if (rc != 0) {
- syslog(LOG_ERR, "cras_client: Could not init start cond.");
- rc = -rc;
- goto free_lock;
- }
-
- (*client)->server_event_fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
- if ((*client)->server_event_fd < 0) {
- syslog(LOG_ERR, "cras_client: Could not setup server eventfd.");
- rc = -errno;
- goto free_cond;
- }
-
- rc = fill_socket_file((*client), conn_type);
- if (rc < 0) {
- goto free_server_event_fd;
- }
-
- rc = cras_file_wait_create((*client)->sock_file,
- CRAS_FILE_WAIT_FLAG_NONE,
- sock_file_wait_callback, *client,
- &(*client)->sock_file_wait);
- if (rc < 0 && rc != -ENOENT) {
- syslog(LOG_ERR,
- "cras_client: Could not setup watch for '%s': %s",
- (*client)->sock_file, strerror(-rc));
- goto free_error;
- }
- (*client)->sock_file_exists = (rc == 0);
-
- /* Pipes used by the main thread and the client thread to send commands
- * and replies. */
- rc = pipe((*client)->command_fds);
- if (rc < 0)
- goto free_error;
- /* Pipe used to communicate between the client thread and the audio
- * thread. */
- rc = pipe((*client)->stream_fds);
- if (rc < 0) {
- close((*client)->command_fds[0]);
- close((*client)->command_fds[1]);
- goto free_error;
- }
- (*client)->command_reply_fds[0] = -1;
- (*client)->command_reply_fds[1] = -1;
-
- return 0;
-free_error:
- cras_file_wait_destroy((*client)->sock_file_wait);
- free((void *)(*client)->sock_file);
-free_server_event_fd:
- if ((*client)->server_event_fd >= 0)
- close((*client)->server_event_fd);
-free_cond:
- pthread_cond_destroy(&(*client)->stream_start_cond);
-free_lock:
- pthread_mutex_destroy(&(*client)->stream_start_lock);
-free_rwlock:
- pthread_rwlock_destroy(&client_int->server_state_rwlock);
-free_client:
- *client = NULL;
- free(client_int);
- return rc;
-}
-
-int cras_client_create(struct cras_client **client)
-{
- return cras_client_create_with_type(client, CRAS_CONTROL);
-}
-
-void cras_client_destroy(struct cras_client *client)
-{
- struct client_int *client_int;
- if (client == NULL)
- return;
- client_int = to_client_int(client);
- client->server_connection_cb = NULL;
- cras_client_stop(client);
- server_disconnect(client);
- close(client->server_event_fd);
- close(client->command_fds[0]);
- close(client->command_fds[1]);
- close(client->stream_fds[0]);
- close(client->stream_fds[1]);
- cras_file_wait_destroy(client->sock_file_wait);
- pthread_rwlock_destroy(&client_int->server_state_rwlock);
- free((void *)client->sock_file);
- free(client_int);
-}
-
-int cras_client_connect(struct cras_client *client)
-{
- return connect_to_server(client, NULL, true);
-}
-
-int cras_client_connect_timeout(struct cras_client *client,
- unsigned int timeout_ms)
-{
- return connect_to_server_wait_retry(client, timeout_ms, true);
-}
-
-int cras_client_connected_wait(struct cras_client *client)
-{
- return send_simple_cmd_msg(client, 0, CLIENT_SERVER_CONNECT);
-}
-
-int cras_client_connect_async(struct cras_client *client)
-{
- return send_simple_cmd_msg(client, 0, CLIENT_SERVER_CONNECT_ASYNC);
-}
-
-struct cras_stream_params *cras_client_stream_params_create(
- enum CRAS_STREAM_DIRECTION direction, size_t buffer_frames,
- size_t cb_threshold, size_t unused, enum CRAS_STREAM_TYPE stream_type,
- uint32_t flags, void *user_data, cras_playback_cb_t aud_cb,
- cras_error_cb_t err_cb, struct cras_audio_format *format)
-{
- struct cras_stream_params *params;
-
- params = (struct cras_stream_params *)malloc(sizeof(*params));
- if (params == NULL)
- return NULL;
-
- params->direction = direction;
- params->buffer_frames = buffer_frames;
- params->cb_threshold = cb_threshold;
- params->effects = 0;
- params->stream_type = stream_type;
- params->client_type = CRAS_CLIENT_TYPE_UNKNOWN;
- params->flags = flags;
- params->user_data = user_data;
- params->aud_cb = aud_cb;
- params->unified_cb = 0;
- params->stream_cb = 0;
- params->err_cb = err_cb;
- memcpy(&(params->format), format, sizeof(*format));
- return params;
-}
-
-void cras_client_stream_params_set_client_type(
- struct cras_stream_params *params, enum CRAS_CLIENT_TYPE client_type)
-{
- params->client_type = client_type;
-}
-
-void cras_client_stream_params_enable_aec(struct cras_stream_params *params)
-{
- params->effects |= APM_ECHO_CANCELLATION;
-}
-
-void cras_client_stream_params_disable_aec(struct cras_stream_params *params)
-{
- params->effects &= ~APM_ECHO_CANCELLATION;
-}
-
-void cras_client_stream_params_enable_ns(struct cras_stream_params *params)
-{
- params->effects |= APM_NOISE_SUPRESSION;
-}
-
-void cras_client_stream_params_disable_ns(struct cras_stream_params *params)
-{
- params->effects &= ~APM_NOISE_SUPRESSION;
-}
-
-void cras_client_stream_params_enable_agc(struct cras_stream_params *params)
-{
- params->effects |= APM_GAIN_CONTROL;
-}
-
-void cras_client_stream_params_disable_agc(struct cras_stream_params *params)
-{
- params->effects &= ~APM_GAIN_CONTROL;
-}
-
-void cras_client_stream_params_enable_vad(struct cras_stream_params *params)
-{
- params->effects |= APM_VOICE_DETECTION;
-}
-
-void cras_client_stream_params_disable_vad(struct cras_stream_params *params)
-{
- params->effects &= ~APM_VOICE_DETECTION;
-}
-
-struct cras_stream_params *cras_client_unified_params_create(
- enum CRAS_STREAM_DIRECTION direction, unsigned int block_size,
- enum CRAS_STREAM_TYPE stream_type, uint32_t flags, void *user_data,
- cras_unified_cb_t unified_cb, cras_error_cb_t err_cb,
- struct cras_audio_format *format)
-{
- struct cras_stream_params *params;
-
- params = (struct cras_stream_params *)malloc(sizeof(*params));
- if (params == NULL)
- return NULL;
-
- params->direction = direction;
- params->buffer_frames = block_size * 2;
- params->cb_threshold = block_size;
- params->stream_type = stream_type;
- params->client_type = CRAS_CLIENT_TYPE_UNKNOWN;
- params->flags = flags;
- params->effects = 0;
- params->user_data = user_data;
- params->aud_cb = 0;
- params->unified_cb = unified_cb;
- params->stream_cb = 0;
- params->err_cb = err_cb;
- memcpy(&(params->format), format, sizeof(*format));
-
- return params;
-}
-
-void cras_client_stream_params_destroy(struct cras_stream_params *params)
-{
- free(params);
-}
-
-static inline int cras_client_send_add_stream_command_message(
- struct cras_client *client, uint32_t dev_idx,
- cras_stream_id_t *stream_id_out, struct cras_stream_params *config)
-{
- struct add_stream_command_message cmd_msg;
- struct client_stream *stream;
- int rc = 0;
-
- if (client == NULL || config == NULL || stream_id_out == NULL)
- return -EINVAL;
-
- if (config->stream_cb == NULL && config->aud_cb == NULL &&
- config->unified_cb == NULL)
- return -EINVAL;
-
- if (config->err_cb == NULL)
- return -EINVAL;
-
- stream = (struct client_stream *)calloc(1, sizeof(*stream));
- if (stream == NULL) {
- rc = -ENOMEM;
- goto add_failed;
- }
- stream->config =
- (struct cras_stream_params *)malloc(sizeof(*(stream->config)));
- if (stream->config == NULL) {
- rc = -ENOMEM;
- goto add_failed;
- }
- memcpy(stream->config, config, sizeof(*config));
- stream->aud_fd = -1;
- stream->wake_fds[0] = -1;
- stream->wake_fds[1] = -1;
- stream->direction = config->direction;
- stream->flags = config->flags;
-
- /* Caller might not set this volume scaler after stream created,
- * so always initialize it to 1.0f */
- stream->volume_scaler = 1.0f;
-
- cmd_msg.header.len = sizeof(cmd_msg);
- cmd_msg.header.msg_id = CLIENT_ADD_STREAM;
- cmd_msg.header.stream_id = stream->id;
- cmd_msg.stream = stream;
- cmd_msg.stream_id_out = stream_id_out;
- cmd_msg.dev_idx = dev_idx;
- rc = send_command_message(client, &cmd_msg.header);
- if (rc < 0) {
- syslog(LOG_ERR,
- "cras_client: adding stream failed in thread %d", rc);
- goto add_failed;
- }
-
- return 0;
-
-add_failed:
- if (stream) {
- if (stream->config)
- free(stream->config);
- free(stream);
- }
- return rc;
-}
-
-int cras_client_add_stream(struct cras_client *client,
- cras_stream_id_t *stream_id_out,
- struct cras_stream_params *config)
-{
- return cras_client_send_add_stream_command_message(
- client, NO_DEVICE, stream_id_out, config);
-}
-
-int cras_client_add_pinned_stream(struct cras_client *client, uint32_t dev_idx,
- cras_stream_id_t *stream_id_out,
- struct cras_stream_params *config)
-{
- return cras_client_send_add_stream_command_message(
- client, dev_idx, stream_id_out, config);
-}
-
-int cras_client_rm_stream(struct cras_client *client,
- cras_stream_id_t stream_id)
-{
- if (client == NULL)
- return -EINVAL;
-
- return send_simple_cmd_msg(client, stream_id, CLIENT_REMOVE_STREAM);
-}
-
-int cras_client_set_stream_volume(struct cras_client *client,
- cras_stream_id_t stream_id,
- float volume_scaler)
-{
- if (client == NULL)
- return -EINVAL;
-
- return send_stream_volume_command_msg(client, stream_id, volume_scaler);
-}
-
-int cras_client_set_system_volume(struct cras_client *client, size_t volume)
-{
- struct cras_set_system_volume msg;
-
- if (client == NULL)
- return -EINVAL;
-
- cras_fill_set_system_volume(&msg, volume);
- return write_message_to_server(client, &msg.header);
-}
-
-int cras_client_set_system_mute(struct cras_client *client, int mute)
-{
- struct cras_set_system_mute msg;
-
- if (client == NULL)
- return -EINVAL;
-
- cras_fill_set_system_mute(&msg, mute);
- return write_message_to_server(client, &msg.header);
-}
-
-int cras_client_set_user_mute(struct cras_client *client, int mute)
-{
- struct cras_set_system_mute msg;
-
- if (client == NULL)
- return -EINVAL;
-
- cras_fill_set_user_mute(&msg, mute);
- return write_message_to_server(client, &msg.header);
-}
-
-int cras_client_set_system_mute_locked(struct cras_client *client, int locked)
-{
- struct cras_set_system_mute msg;
-
- if (client == NULL)
- return -EINVAL;
-
- cras_fill_set_system_mute_locked(&msg, locked);
- return write_message_to_server(client, &msg.header);
-}
-
-int cras_client_set_system_capture_mute(struct cras_client *client, int mute)
-{
- struct cras_set_system_mute msg;
-
- if (client == NULL)
- return -EINVAL;
-
- cras_fill_set_system_capture_mute(&msg, mute);
- return write_message_to_server(client, &msg.header);
-}
-
-int cras_client_set_system_capture_mute_locked(struct cras_client *client,
- int locked)
-{
- struct cras_set_system_mute msg;
-
- if (client == NULL)
- return -EINVAL;
-
- cras_fill_set_system_capture_mute_locked(&msg, locked);
- return write_message_to_server(client, &msg.header);
-}
-
-size_t cras_client_get_system_volume(const struct cras_client *client)
-{
- size_t volume;
- int lock_rc;
-
- lock_rc = server_state_rdlock(client);
- if (lock_rc)
- return 0;
-
- volume = client->server_state->volume;
- server_state_unlock(client, lock_rc);
- return volume;
-}
-
-long cras_client_get_system_capture_gain(const struct cras_client *client)
-{
- long gain;
- int lock_rc;
-
- lock_rc = server_state_rdlock(client);
- if (lock_rc)
- return 0;
-
- gain = client->server_state->capture_gain;
- server_state_unlock(client, lock_rc);
- return gain;
-}
-
-int cras_client_get_system_muted(const struct cras_client *client)
-{
- int muted;
- int lock_rc;
-
- lock_rc = server_state_rdlock(client);
- if (lock_rc)
- return 0;
-
- muted = client->server_state->mute;
- server_state_unlock(client, lock_rc);
- return muted;
-}
-
-int cras_client_get_user_muted(const struct cras_client *client)
-{
- int muted;
- int lock_rc;
-
- lock_rc = server_state_rdlock(client);
- if (lock_rc)
- return 0;
-
- muted = client->server_state->user_mute;
- server_state_unlock(client, lock_rc);
- return muted;
-}
-
-int cras_client_get_system_capture_muted(const struct cras_client *client)
-{
- int muted;
- int lock_rc;
-
- lock_rc = server_state_rdlock(client);
- if (lock_rc)
- return 0;
-
- muted = client->server_state->capture_mute;
- server_state_unlock(client, lock_rc);
- return muted;
-}
-
-long cras_client_get_system_min_volume(const struct cras_client *client)
-{
- long min_volume;
- int lock_rc;
-
- lock_rc = server_state_rdlock(client);
- if (lock_rc)
- return 0;
-
- min_volume = client->server_state->min_volume_dBFS;
- server_state_unlock(client, lock_rc);
- return min_volume;
-}
-
-long cras_client_get_system_max_volume(const struct cras_client *client)
-{
- long max_volume;
- int lock_rc;
-
- lock_rc = server_state_rdlock(client);
- if (lock_rc)
- return 0;
-
- max_volume = client->server_state->max_volume_dBFS;
- server_state_unlock(client, lock_rc);
- return max_volume;
-}
-
-int cras_client_get_default_output_buffer_size(struct cras_client *client)
-{
- int default_output_buffer_size;
- int lock_rc;
-
- lock_rc = server_state_rdlock(client);
- if (lock_rc)
- return -EINVAL;
-
- default_output_buffer_size =
- client->server_state->default_output_buffer_size;
- server_state_unlock(client, lock_rc);
- return default_output_buffer_size;
-}
-
-const struct audio_debug_info *
-cras_client_get_audio_debug_info(const struct cras_client *client)
-{
- const struct audio_debug_info *debug_info;
- int lock_rc;
-
- lock_rc = server_state_rdlock(client);
- if (lock_rc)
- return 0;
-
- debug_info = &client->server_state->audio_debug_info;
- server_state_unlock(client, lock_rc);
- return debug_info;
-}
-
-const struct main_thread_debug_info *
-cras_client_get_main_thread_debug_info(const struct cras_client *client)
-{
- const struct main_thread_debug_info *debug_info;
- int lock_rc;
-
- lock_rc = server_state_rdlock(client);
- if (lock_rc)
- return 0;
-
- debug_info = &client->server_state->main_thread_debug_info;
- server_state_unlock(client, lock_rc);
- return debug_info;
-}
-
-const struct cras_bt_debug_info *
-cras_client_get_bt_debug_info(const struct cras_client *client)
-{
- const struct cras_bt_debug_info *debug_info;
- int lock_rc;
-
- lock_rc = server_state_rdlock(client);
- if (lock_rc)
- return 0;
-
- debug_info = &client->server_state->bt_debug_info;
- server_state_unlock(client, lock_rc);
- return debug_info;
-}
-
-const struct cras_audio_thread_snapshot_buffer *
-cras_client_get_audio_thread_snapshot_buffer(const struct cras_client *client)
-{
- const struct cras_audio_thread_snapshot_buffer *snapshot_buffer;
- int lock_rc;
-
- lock_rc = server_state_rdlock(client);
- if (lock_rc)
- return 0;
-
- snapshot_buffer = &client->server_state->snapshot_buffer;
- server_state_unlock(client, lock_rc);
- return snapshot_buffer;
-}
-
-unsigned cras_client_get_num_active_streams(const struct cras_client *client,
- struct timespec *ts)
-{
- unsigned num_streams, version, i;
- int lock_rc;
-
- lock_rc = server_state_rdlock(client);
- if (lock_rc)
- return 0;
-
-read_active_streams_again:
- version = begin_server_state_read(client->server_state);
- num_streams = 0;
- for (i = 0; i < CRAS_NUM_DIRECTIONS; i++)
- num_streams += client->server_state->num_active_streams[i];
- if (ts) {
- if (num_streams)
- clock_gettime(CLOCK_MONOTONIC_RAW, ts);
- else
- cras_timespec_to_timespec(
- ts,
- &client->server_state->last_active_stream_time);
- }
- if (end_server_state_read(client->server_state, version))
- goto read_active_streams_again;
-
- server_state_unlock(client, lock_rc);
- return num_streams;
-}
-
-int cras_client_run_thread(struct cras_client *client)
-{
- int rc;
-
- if (client == NULL)
- return -EINVAL;
- if (thread_is_running(&client->thread))
- return 0;
-
- assert(client->command_reply_fds[0] == -1 &&
- client->command_reply_fds[1] == -1);
-
- if (pipe(client->command_reply_fds) < 0)
- return -EIO;
- client->thread.state = CRAS_THREAD_RUNNING;
- rc = pthread_create(&client->thread.tid, NULL, client_thread, client);
- if (rc) {
- client->thread.state = CRAS_THREAD_STOP;
- return -rc;
- }
-
- return 0;
-}
-
-int cras_client_stop(struct cras_client *client)
-{
- if (client == NULL)
- return -EINVAL;
- if (!thread_is_running(&client->thread))
- return 0;
-
- send_simple_cmd_msg(client, 0, CLIENT_STOP);
- pthread_join(client->thread.tid, NULL);
-
- /* The other end of the reply pipe is closed by the client thread, just
- * clost the read end here. */
- close(client->command_reply_fds[0]);
- client->command_reply_fds[0] = -1;
-
- return 0;
-}
-
-void cras_client_set_connection_status_cb(
- struct cras_client *client, cras_connection_status_cb_t connection_cb,
- void *user_arg)
-{
- client->server_connection_cb = connection_cb;
- client->server_connection_user_arg = user_arg;
-}
-
-void cras_client_set_thread_priority_cb(struct cras_client *client,
- cras_thread_priority_cb_t cb)
-{
- client->thread_priority_cb = cb;
-}
-
-int cras_client_get_output_devices(const struct cras_client *client,
- struct cras_iodev_info *devs,
- struct cras_ionode_info *nodes,
- size_t *num_devs, size_t *num_nodes)
-{
- const struct cras_server_state *state;
- unsigned avail_devs, avail_nodes, version;
- int lock_rc;
-
- lock_rc = server_state_rdlock(client);
- if (lock_rc)
- return -EINVAL;
- state = client->server_state;
-
-read_outputs_again:
- version = begin_server_state_read(state);
- avail_devs = MIN(*num_devs, state->num_output_devs);
- memcpy(devs, state->output_devs, avail_devs * sizeof(*devs));
- avail_nodes = MIN(*num_nodes, state->num_output_nodes);
- memcpy(nodes, state->output_nodes, avail_nodes * sizeof(*nodes));
- if (end_server_state_read(state, version))
- goto read_outputs_again;
- server_state_unlock(client, lock_rc);
-
- *num_devs = avail_devs;
- *num_nodes = avail_nodes;
-
- return 0;
-}
-
-int cras_client_get_input_devices(const struct cras_client *client,
- struct cras_iodev_info *devs,
- struct cras_ionode_info *nodes,
- size_t *num_devs, size_t *num_nodes)
-{
- const struct cras_server_state *state;
- unsigned avail_devs, avail_nodes, version;
- int lock_rc;
-
- lock_rc = server_state_rdlock(client);
- if (!client)
- return -EINVAL;
- state = client->server_state;
-
-read_inputs_again:
- version = begin_server_state_read(state);
- avail_devs = MIN(*num_devs, state->num_input_devs);
- memcpy(devs, state->input_devs, avail_devs * sizeof(*devs));
- avail_nodes = MIN(*num_nodes, state->num_input_nodes);
- memcpy(nodes, state->input_nodes, avail_nodes * sizeof(*nodes));
- if (end_server_state_read(state, version))
- goto read_inputs_again;
- server_state_unlock(client, lock_rc);
-
- *num_devs = avail_devs;
- *num_nodes = avail_nodes;
-
- return 0;
-}
-
-int cras_client_get_attached_clients(const struct cras_client *client,
- struct cras_attached_client_info *clients,
- size_t max_clients)
-{
- const struct cras_server_state *state;
- unsigned num, version;
- int lock_rc;
-
- lock_rc = server_state_rdlock(client);
- if (lock_rc)
- return -EINVAL;
- state = client->server_state;
-
-read_clients_again:
- version = begin_server_state_read(state);
- num = MIN(max_clients, state->num_attached_clients);
- memcpy(clients, state->client_info, num * sizeof(*clients));
- if (end_server_state_read(state, version))
- goto read_clients_again;
- server_state_unlock(client, lock_rc);
-
- return num;
-}
-
-/* Find an output ionode on an iodev with the matching name.
- *
- * Args:
- * dev_name - The prefix of the iodev name.
- * node_name - The prefix of the ionode name.
- * dev_info - The information about the iodev will be returned here.
- * node_info - The information about the ionode will be returned here.
- * Returns:
- * 0 if successful, -1 if the node cannot be found.
- */
-static int cras_client_find_output_node(const struct cras_client *client,
- const char *dev_name,
- const char *node_name,
- struct cras_iodev_info *dev_info,
- struct cras_ionode_info *node_info)
-{
- size_t ndevs, nnodes;
- struct cras_iodev_info *devs = NULL;
- struct cras_ionode_info *nodes = NULL;
- int rc = -1;
- unsigned i, j;
-
- if (!client || !dev_name || !node_name)
- goto quit;
-
- devs = (struct cras_iodev_info *)malloc(CRAS_MAX_IODEVS *
- sizeof(*devs));
- if (!devs)
- goto quit;
-
- nodes = (struct cras_ionode_info *)malloc(CRAS_MAX_IONODES *
- sizeof(*nodes));
- if (!nodes)
- goto quit;
-
- ndevs = CRAS_MAX_IODEVS;
- nnodes = CRAS_MAX_IONODES;
- rc = cras_client_get_output_devices(client, devs, nodes, &ndevs,
- &nnodes);
- if (rc < 0)
- goto quit;
-
- for (i = 0; i < ndevs; i++)
- if (!strncmp(dev_name, devs[i].name, strlen(dev_name)))
- goto found_dev;
- rc = -1;
- goto quit;
-
-found_dev:
- for (j = 0; j < nnodes; j++)
- if (nodes[j].iodev_idx == devs[i].idx &&
- !strncmp(node_name, nodes[j].name, strlen(node_name)))
- goto found_node;
- rc = -1;
- goto quit;
-
-found_node:
- *dev_info = devs[i];
- *node_info = nodes[j];
- rc = 0;
-
-quit:
- free(devs);
- free(nodes);
- return rc;
-}
-
-int cras_client_get_node_by_id(const struct cras_client *client, int input,
- const cras_node_id_t node_id,
- struct cras_ionode_info *node_info)
-{
- size_t ndevs, nnodes;
- struct cras_iodev_info *devs = NULL;
- struct cras_ionode_info *nodes = NULL;
- int rc = -EINVAL;
- unsigned i;
-
- if (!client || !node_info) {
- rc = -EINVAL;
- goto quit;
- }
-
- devs = (struct cras_iodev_info *)malloc(CRAS_MAX_IODEVS *
- sizeof(*devs));
- if (!devs) {
- rc = -ENOMEM;
- goto quit;
- }
-
- nodes = (struct cras_ionode_info *)malloc(CRAS_MAX_IONODES *
- sizeof(*nodes));
- if (!nodes) {
- rc = -ENOMEM;
- goto quit;
- }
-
- ndevs = CRAS_MAX_IODEVS;
- nnodes = CRAS_MAX_IONODES;
- if (input)
- rc = cras_client_get_input_devices(client, devs, nodes, &ndevs,
- &nnodes);
- else
- rc = cras_client_get_output_devices(client, devs, nodes, &ndevs,
- &nnodes);
- if (rc < 0)
- goto quit;
-
- rc = -ENOENT;
- for (i = 0; i < nnodes; i++) {
- if (node_id == cras_make_node_id(nodes[i].iodev_idx,
- nodes[i].ionode_idx)) {
- memcpy(node_info, &nodes[i], sizeof(*node_info));
- rc = 0;
- break;
- }
- }
-
-quit:
- free(devs);
- free(nodes);
- return rc;
-}
-
-int cras_client_output_dev_plugged(const struct cras_client *client,
- const char *name)
-{
- struct cras_iodev_info dev_info;
- struct cras_ionode_info node_info = { 0 };
-
- if (cras_client_find_output_node(client, name, "Front Headphone Jack",
- &dev_info, &node_info) < 0)
- return 0;
-
- return node_info.plugged;
-}
-
-int cras_client_set_node_attr(struct cras_client *client,
- cras_node_id_t node_id, enum ionode_attr attr,
- int value)
-{
- struct cras_set_node_attr msg;
-
- if (client == NULL)
- return -EINVAL;
-
- cras_fill_set_node_attr(&msg, node_id, attr, value);
- return write_message_to_server(client, &msg.header);
-}
-
-int cras_client_select_node(struct cras_client *client,
- enum CRAS_STREAM_DIRECTION direction,
- cras_node_id_t node_id)
-{
- struct cras_select_node msg;
-
- if (client == NULL)
- return -EINVAL;
-
- cras_fill_select_node(&msg, direction, node_id);
- return write_message_to_server(client, &msg.header);
-}
-
-int cras_client_add_active_node(struct cras_client *client,
- enum CRAS_STREAM_DIRECTION direction,
- cras_node_id_t node_id)
-{
- struct cras_add_active_node msg;
-
- if (client == NULL)
- return -EINVAL;
-
- cras_fill_add_active_node(&msg, direction, node_id);
- return write_message_to_server(client, &msg.header);
-}
-
-int cras_client_rm_active_node(struct cras_client *client,
- enum CRAS_STREAM_DIRECTION direction,
- cras_node_id_t node_id)
-{
- struct cras_rm_active_node msg;
-
- if (client == NULL)
- return -EINVAL;
-
- cras_fill_rm_active_node(&msg, direction, node_id);
- return write_message_to_server(client, &msg.header);
-}
-
-int cras_client_format_bytes_per_frame(struct cras_audio_format *fmt)
-{
- if (fmt == NULL)
- return -EINVAL;
-
- return cras_get_format_bytes(fmt);
-}
-
-int cras_client_calc_playback_latency(const struct timespec *sample_time,
- struct timespec *delay)
-{
- struct timespec now;
-
- if (delay == NULL)
- return -EINVAL;
-
- clock_gettime(CLOCK_MONOTONIC_RAW, &now);
-
- /* for output return time until sample is played (t - now) */
- subtract_timespecs(sample_time, &now, delay);
- return 0;
-}
-
-int cras_client_calc_capture_latency(const struct timespec *sample_time,
- struct timespec *delay)
-{
- struct timespec now;
-
- if (delay == NULL)
- return -EINVAL;
-
- clock_gettime(CLOCK_MONOTONIC_RAW, &now);
-
- /* For input want time since sample read (now - t) */
- subtract_timespecs(&now, sample_time, delay);
- return 0;
-}
-
-int cras_client_reload_dsp(struct cras_client *client)
-{
- struct cras_reload_dsp msg;
-
- if (client == NULL)
- return -EINVAL;
-
- cras_fill_reload_dsp(&msg);
- return write_message_to_server(client, &msg.header);
-}
-
-int cras_client_dump_dsp_info(struct cras_client *client)
-{
- struct cras_dump_dsp_info msg;
-
- if (client == NULL)
- return -EINVAL;
-
- cras_fill_dump_dsp_info(&msg);
- return write_message_to_server(client, &msg.header);
-}
-
-int cras_client_update_audio_debug_info(
- struct cras_client *client, void (*debug_info_cb)(struct cras_client *))
-{
- struct cras_dump_audio_thread msg;
-
- if (client == NULL)
- return -EINVAL;
-
- if (client->debug_info_callback != NULL)
- return -EINVAL;
- client->debug_info_callback = debug_info_cb;
-
- cras_fill_dump_audio_thread(&msg);
- return write_message_to_server(client, &msg.header);
-}
-
-int cras_client_get_atlog_access(struct cras_client *client,
- void (*atlog_access_cb)(struct cras_client *))
-{
- struct cras_get_atlog_fd msg;
-
- if (client == NULL)
- return -EINVAL;
-
- if (client->atlog_access_callback != NULL)
- return -EINVAL;
- client->atlog_access_callback = atlog_access_cb;
-
- cras_fill_get_atlog_fd(&msg);
- return write_message_to_server(client, &msg.header);
-}
-
-int cras_client_read_atlog(struct cras_client *client, uint64_t *read_idx,
- uint64_t *missing,
- struct audio_thread_event_log *buf)
-{
- struct audio_thread_event_log log;
- uint64_t i, sync_write_pos, len = 0;
- struct timespec timestamp, last_timestamp;
-
- if (!client->atlog_ro)
- return -EINVAL;
-
- sync_write_pos = client->atlog_ro->sync_write_pos;
- __sync_synchronize();
- memcpy(&log, client->atlog_ro, sizeof(log));
-
- if (sync_write_pos <= *read_idx)
- return 0;
-
- *missing = 0;
- for (i = sync_write_pos - 1; i >= *read_idx; --i) {
- uint64_t pos = i % log.len;
- timestamp.tv_sec = log.log[pos].tag_sec & 0x00ffffff;
- timestamp.tv_nsec = log.log[pos].nsec;
-
- if (i != sync_write_pos - 1 &&
- timespec_after(&timestamp, &last_timestamp)) {
- if (*read_idx)
- *missing = i - *read_idx + 1;
- *read_idx = i + 1;
- break;
- }
- last_timestamp = timestamp;
-
- if (!i)
- break;
- }
-
- /* Copies the continuous part of log. */
- if ((sync_write_pos - 1) % log.len < *read_idx % log.len) {
- len = log.len - *read_idx % log.len;
- memcpy(buf->log, &log.log[*read_idx % log.len],
- sizeof(struct audio_thread_event) * len);
- memcpy(&buf->log[len], log.log,
- sizeof(struct audio_thread_event) *
- ((sync_write_pos - 1) % log.len + 1));
- len = sync_write_pos - *read_idx;
- } else {
- len = sync_write_pos - *read_idx;
- memcpy(buf->log, &log.log[*read_idx % log.len],
- sizeof(struct audio_thread_event) * len);
- }
-
- *read_idx = sync_write_pos;
- return len;
-}
-
-int cras_client_update_main_thread_debug_info(
- struct cras_client *client, void (*debug_info_cb)(struct cras_client *))
-{
- struct cras_dump_main msg;
-
- if (client == NULL)
- return -EINVAL;
- if (client->debug_info_callback != NULL)
- return -EINVAL;
- client->debug_info_callback = debug_info_cb;
- cras_fill_dump_main(&msg);
- return write_message_to_server(client, &msg.header);
-}
-
-int cras_client_update_bt_debug_info(
- struct cras_client *client, void (*debug_info_cb)(struct cras_client *))
-{
- struct cras_dump_bt msg;
-
- if (client == NULL)
- return -EINVAL;
-
- if (client->debug_info_callback != NULL)
- return -EINVAL;
- client->debug_info_callback = debug_info_cb;
-
- cras_fill_dump_bt(&msg);
- return write_message_to_server(client, &msg.header);
-}
-
-int cras_client_update_audio_thread_snapshots(
- struct cras_client *client, void (*debug_info_cb)(struct cras_client *))
-{
- struct cras_dump_snapshots msg;
-
- if (client == NULL)
- return -EINVAL;
-
- if (client->debug_info_callback != NULL)
- return -EINVAL;
- client->debug_info_callback = debug_info_cb;
-
- cras_fill_dump_snapshots(&msg);
- return write_message_to_server(client, &msg.header);
-}
-
-int cras_client_get_max_supported_channels(const struct cras_client *client,
- cras_node_id_t node_id,
- uint32_t *max_channels)
-{
- size_t ndevs, nnodes;
- struct cras_iodev_info *devs = NULL;
- struct cras_ionode_info *nodes = NULL;
- int rc = -EINVAL;
- unsigned i;
-
- if (!client) {
- rc = -EINVAL;
- goto quit;
- }
-
- devs = (struct cras_iodev_info *)malloc(CRAS_MAX_IODEVS *
- sizeof(*devs));
- if (!devs) {
- rc = -ENOMEM;
- goto quit;
- }
-
- nodes = (struct cras_ionode_info *)malloc(CRAS_MAX_IONODES *
- sizeof(*nodes));
- if (!nodes) {
- rc = -ENOMEM;
- goto quit;
- }
-
- ndevs = CRAS_MAX_IODEVS;
- nnodes = CRAS_MAX_IONODES;
- rc = cras_client_get_output_devices(client, devs, nodes, &ndevs,
- &nnodes);
- if (rc < 0)
- goto quit;
-
- rc = -ENOENT;
- uint32_t iodev_idx;
- for (i = 0; i < nnodes; i++) {
- if (node_id == cras_make_node_id(nodes[i].iodev_idx,
- nodes[i].ionode_idx)) {
- iodev_idx = nodes[i].iodev_idx;
- rc = 0;
- break;
- }
- }
-
- if (rc < 0)
- goto quit;
-
- rc = -ENOENT;
- for (i = 0; i < ndevs; i++) {
- if (iodev_idx == devs[i].idx) {
- *max_channels = devs[i].max_supported_channels;
- rc = 0;
- break;
- }
- }
-
-quit:
- free(devs);
- free(nodes);
- return rc;
-}
-
-int cras_client_set_node_volume(struct cras_client *client,
- cras_node_id_t node_id, uint8_t volume)
-{
- struct cras_set_node_attr msg;
-
- if (client == NULL)
- return -EINVAL;
-
- cras_fill_set_node_attr(&msg, node_id, IONODE_ATTR_VOLUME, volume);
- return write_message_to_server(client, &msg.header);
-}
-
-int cras_client_swap_node_left_right(struct cras_client *client,
- cras_node_id_t node_id, int enable)
-{
- struct cras_set_node_attr msg;
-
- if (client == NULL)
- return -EINVAL;
-
- cras_fill_set_node_attr(&msg, node_id, IONODE_ATTR_SWAP_LEFT_RIGHT,
- enable);
- return write_message_to_server(client, &msg.header);
-}
-
-int cras_client_set_node_capture_gain(struct cras_client *client,
- cras_node_id_t node_id, long gain)
-{
- struct cras_set_node_attr msg;
-
- if (client == NULL)
- return -EINVAL;
- if (gain > INT_MAX || gain < INT_MIN)
- return -EINVAL;
-
- cras_fill_set_node_attr(&msg, node_id, IONODE_ATTR_CAPTURE_GAIN, gain);
- return write_message_to_server(client, &msg.header);
-}
-
-int cras_client_add_test_iodev(struct cras_client *client,
- enum TEST_IODEV_TYPE type)
-{
- struct cras_add_test_dev msg;
-
- cras_fill_add_test_dev(&msg, type);
- return write_message_to_server(client, &msg.header);
-}
-
-int cras_client_test_iodev_command(struct cras_client *client,
- unsigned int iodev_idx,
- enum CRAS_TEST_IODEV_CMD command,
- unsigned int data_len, const uint8_t *data)
-{
- struct cras_test_dev_command *msg;
- int rc;
-
- msg = (struct cras_test_dev_command *)malloc(sizeof(*msg) + data_len);
- cras_fill_test_dev_command(msg, iodev_idx, command, data_len, data);
- rc = write_message_to_server(client, &msg->header);
- free(msg);
- return rc;
-}
-
-int cras_client_config_global_remix(struct cras_client *client,
- unsigned num_channels, float *coefficient)
-{
- struct cras_config_global_remix *msg;
- int rc;
- size_t nchan = (size_t)num_channels;
-
- msg = (struct cras_config_global_remix *)malloc(
- sizeof(*msg) + nchan * nchan * sizeof(*coefficient));
- cras_fill_config_global_remix_command(msg, num_channels, coefficient,
- num_channels * num_channels);
- rc = write_message_to_server(client, &msg->header);
- free(msg);
- return rc;
-}
-
-int cras_client_get_first_node_type_idx(const struct cras_client *client,
- enum CRAS_NODE_TYPE type,
- enum CRAS_STREAM_DIRECTION direction,
- cras_node_id_t *node_id)
-{
- const struct cras_server_state *state;
- unsigned int version;
- unsigned int i;
- const struct cras_ionode_info *node_list;
- unsigned int num_nodes;
- int lock_rc;
-
- lock_rc = server_state_rdlock(client);
- if (lock_rc)
- return -EINVAL;
- state = client->server_state;
-
-read_nodes_again:
- version = begin_server_state_read(state);
- if (direction == CRAS_STREAM_OUTPUT) {
- node_list = state->output_nodes;
- num_nodes = state->num_output_nodes;
- } else {
- node_list = state->input_nodes;
- num_nodes = state->num_input_nodes;
- }
- for (i = 0; i < num_nodes; i++) {
- if ((enum CRAS_NODE_TYPE)node_list[i].type_enum == type) {
- *node_id = cras_make_node_id(node_list[i].iodev_idx,
- node_list[i].ionode_idx);
- server_state_unlock(client, lock_rc);
- return 0;
- }
- }
- if (end_server_state_read(state, version))
- goto read_nodes_again;
- server_state_unlock(client, lock_rc);
-
- return -ENODEV;
-}
-
-int cras_client_get_first_dev_type_idx(const struct cras_client *client,
- enum CRAS_NODE_TYPE type,
- enum CRAS_STREAM_DIRECTION direction)
-{
- cras_node_id_t node_id;
- int rc;
-
- rc = cras_client_get_first_node_type_idx(client, type, direction,
- &node_id);
- if (rc)
- return rc;
-
- return dev_index_of(node_id);
-}
-
-int cras_client_set_suspend(struct cras_client *client, int suspend)
-{
- struct cras_server_message msg;
-
- cras_fill_suspend_message(&msg, suspend);
- return write_message_to_server(client, &msg);
-}
-
-int cras_client_get_hotword_models(struct cras_client *client,
- cras_node_id_t node_id,
- get_hotword_models_cb_t cb)
-{
- struct cras_get_hotword_models msg;
-
- if (!client)
- return -EINVAL;
- client->get_hotword_models_cb = cb;
-
- cras_fill_get_hotword_models_message(&msg, node_id);
- return write_message_to_server(client, &msg.header);
-}
-
-int cras_client_set_hotword_model(struct cras_client *client,
- cras_node_id_t node_id,
- const char *model_name)
-{
- struct cras_set_hotword_model msg;
-
- cras_fill_set_hotword_model_message(&msg, node_id, model_name);
- return write_message_to_server(client, &msg.header);
-}
-
-int cras_client_set_aec_dump(struct cras_client *client,
- cras_stream_id_t stream_id, int start, int fd)
-{
- struct cras_set_aec_dump msg;
-
- cras_fill_set_aec_dump_message(&msg, stream_id, start);
-
- if (fd != -1)
- return cras_send_with_fds(client->server_fd, &msg, sizeof(msg),
- &fd, 1);
- else
- return write_message_to_server(client, &msg.header);
-}
-
-int cras_client_reload_aec_config(struct cras_client *client)
-{
- struct cras_reload_aec_config msg;
-
- cras_fill_reload_aec_config(&msg);
- return write_message_to_server(client, &msg.header);
-}
-
-int cras_client_get_aec_supported(struct cras_client *client)
-{
- int aec_supported;
- int lock_rc;
-
- lock_rc = server_state_rdlock(client);
- if (lock_rc)
- return 0;
-
- aec_supported = client->server_state->aec_supported;
- server_state_unlock(client, lock_rc);
- return aec_supported;
-}
-
-int cras_client_get_aec_group_id(struct cras_client *client)
-{
- int aec_group_id;
- int lock_rc;
-
- lock_rc = server_state_rdlock(client);
- if (lock_rc)
- return -1;
-
- aec_group_id = client->server_state->aec_group_id;
- server_state_unlock(client, lock_rc);
- return aec_group_id;
-}
-
-int cras_client_set_bt_wbs_enabled(struct cras_client *client, bool enabled)
-{
- struct cras_set_bt_wbs_enabled msg;
-
- cras_fill_set_bt_wbs_enabled(&msg, enabled);
- return write_message_to_server(client, &msg.header);
-}
-
-void cras_client_set_state_change_callback_context(struct cras_client *client,
- void *context)
-{
- if (!client)
- return;
- client->observer_context = context;
-}
-
-static int cras_send_register_notification(struct cras_client *client,
- enum CRAS_CLIENT_MESSAGE_ID msg_id,
- int do_register)
-{
- struct cras_register_notification msg;
- int rc;
-
- /* This library automatically re-registers notifications when
- * reconnecting, so we can ignore message send failure due to no
- * connection. */
- cras_fill_register_notification_message(&msg, msg_id, do_register);
- rc = write_message_to_server(client, &msg.header);
- if (rc == -EPIPE)
- rc = 0;
- return rc;
-}
-
-int cras_client_set_output_volume_changed_callback(
- struct cras_client *client,
- cras_client_output_volume_changed_callback cb)
-{
- if (!client)
- return -EINVAL;
- client->observer_ops.output_volume_changed = cb;
- return cras_send_register_notification(
- client, CRAS_CLIENT_OUTPUT_VOLUME_CHANGED, cb != NULL);
-}
-
-int cras_client_set_output_mute_changed_callback(
- struct cras_client *client, cras_client_output_mute_changed_callback cb)
-{
- if (!client)
- return -EINVAL;
- client->observer_ops.output_mute_changed = cb;
- return cras_send_register_notification(
- client, CRAS_CLIENT_OUTPUT_MUTE_CHANGED, cb != NULL);
-}
-
-int cras_client_set_capture_gain_changed_callback(
- struct cras_client *client,
- cras_client_capture_gain_changed_callback cb)
-{
- if (!client)
- return -EINVAL;
- client->observer_ops.capture_gain_changed = cb;
- return cras_send_register_notification(
- client, CRAS_CLIENT_CAPTURE_GAIN_CHANGED, cb != NULL);
-}
-
-int cras_client_set_capture_mute_changed_callback(
- struct cras_client *client,
- cras_client_capture_mute_changed_callback cb)
-{
- if (!client)
- return -EINVAL;
- client->observer_ops.capture_mute_changed = cb;
- return cras_send_register_notification(
- client, CRAS_CLIENT_CAPTURE_MUTE_CHANGED, cb != NULL);
-}
-
-int cras_client_set_nodes_changed_callback(
- struct cras_client *client, cras_client_nodes_changed_callback cb)
-{
- if (!client)
- return -EINVAL;
- client->observer_ops.nodes_changed = cb;
- return cras_send_register_notification(
- client, CRAS_CLIENT_NODES_CHANGED, cb != NULL);
-}
-
-int cras_client_set_active_node_changed_callback(
- struct cras_client *client, cras_client_active_node_changed_callback cb)
-{
- if (!client)
- return -EINVAL;
- client->observer_ops.active_node_changed = cb;
- return cras_send_register_notification(
- client, CRAS_CLIENT_ACTIVE_NODE_CHANGED, cb != NULL);
-}
-
-int cras_client_set_output_node_volume_changed_callback(
- struct cras_client *client,
- cras_client_output_node_volume_changed_callback cb)
-{
- if (!client)
- return -EINVAL;
- client->observer_ops.output_node_volume_changed = cb;
- return cras_send_register_notification(
- client, CRAS_CLIENT_OUTPUT_NODE_VOLUME_CHANGED, cb != NULL);
-}
-
-int cras_client_set_node_left_right_swapped_changed_callback(
- struct cras_client *client,
- cras_client_node_left_right_swapped_changed_callback cb)
-{
- if (!client)
- return -EINVAL;
- client->observer_ops.node_left_right_swapped_changed = cb;
- return cras_send_register_notification(
- client, CRAS_CLIENT_NODE_LEFT_RIGHT_SWAPPED_CHANGED,
- cb != NULL);
-}
-
-int cras_client_set_input_node_gain_changed_callback(
- struct cras_client *client,
- cras_client_input_node_gain_changed_callback cb)
-{
- if (!client)
- return -EINVAL;
- client->observer_ops.input_node_gain_changed = cb;
- return cras_send_register_notification(
- client, CRAS_CLIENT_INPUT_NODE_GAIN_CHANGED, cb != NULL);
-}
-
-int cras_client_set_num_active_streams_changed_callback(
- struct cras_client *client,
- cras_client_num_active_streams_changed_callback cb)
-{
- if (!client)
- return -EINVAL;
- client->observer_ops.num_active_streams_changed = cb;
- return cras_send_register_notification(
- client, CRAS_CLIENT_NUM_ACTIVE_STREAMS_CHANGED, cb != NULL);
-}
-
-static int reregister_notifications(struct cras_client *client)
-{
- int rc;
-
- if (client->observer_ops.output_volume_changed) {
- rc = cras_client_set_output_volume_changed_callback(
- client, client->observer_ops.output_volume_changed);
- if (rc != 0)
- return rc;
- }
- if (client->observer_ops.output_mute_changed) {
- rc = cras_client_set_output_mute_changed_callback(
- client, client->observer_ops.output_mute_changed);
- if (rc != 0)
- return rc;
- }
- if (client->observer_ops.capture_gain_changed) {
- rc = cras_client_set_capture_gain_changed_callback(
- client, client->observer_ops.capture_gain_changed);
- if (rc != 0)
- return rc;
- }
- if (client->observer_ops.capture_mute_changed) {
- rc = cras_client_set_capture_mute_changed_callback(
- client, client->observer_ops.capture_mute_changed);
- if (rc != 0)
- return rc;
- }
- if (client->observer_ops.nodes_changed) {
- rc = cras_client_set_nodes_changed_callback(
- client, client->observer_ops.nodes_changed);
- if (rc != 0)
- return rc;
- }
- if (client->observer_ops.active_node_changed) {
- rc = cras_client_set_active_node_changed_callback(
- client, client->observer_ops.active_node_changed);
- if (rc != 0)
- return rc;
- }
- if (client->observer_ops.output_node_volume_changed) {
- rc = cras_client_set_output_node_volume_changed_callback(
- client,
- client->observer_ops.output_node_volume_changed);
- if (rc != 0)
- return rc;
- }
- if (client->observer_ops.node_left_right_swapped_changed) {
- rc = cras_client_set_node_left_right_swapped_changed_callback(
- client,
- client->observer_ops.node_left_right_swapped_changed);
- if (rc != 0)
- return rc;
- }
- if (client->observer_ops.input_node_gain_changed) {
- rc = cras_client_set_input_node_gain_changed_callback(
- client, client->observer_ops.input_node_gain_changed);
- if (rc != 0)
- return rc;
- }
- if (client->observer_ops.num_active_streams_changed) {
- rc = cras_client_set_num_active_streams_changed_callback(
- client,
- client->observer_ops.num_active_streams_changed);
- if (rc != 0)
- return rc;
- }
- return 0;
-}
-
-static int hotword_read_cb(struct cras_client *client,
- cras_stream_id_t stream_id,
- uint8_t *captured_samples, uint8_t *playback_samples,
- unsigned int frames,
- const struct timespec *captured_time,
- const struct timespec *playback_time, void *user_arg)
-{
- struct cras_hotword_handle *handle;
-
- handle = (struct cras_hotword_handle *)user_arg;
- if (handle->trigger_cb)
- handle->trigger_cb(client, handle, handle->user_data);
-
- return 0;
-}
-
-static int hotword_err_cb(struct cras_client *client,
- cras_stream_id_t stream_id, int error, void *user_arg)
-{
- struct cras_hotword_handle *handle;
-
- handle = (struct cras_hotword_handle *)user_arg;
- if (handle->err_cb)
- handle->err_cb(client, handle, error, handle->user_data);
-
- return 0;
-}
-
-int cras_client_enable_hotword_callback(struct cras_client *client,
- void *user_data,
- cras_hotword_trigger_cb_t trigger_cb,
- cras_hotword_error_cb_t err_cb,
- struct cras_hotword_handle **handle_out)
-{
- struct cras_hotword_handle *handle;
- int ret = 0;
-
- if (!client)
- return -EINVAL;
-
- handle = (struct cras_hotword_handle *)calloc(1, sizeof(*handle));
- if (!handle)
- return -ENOMEM;
-
- handle->format = cras_audio_format_create(SND_PCM_FORMAT_S16_LE,
- HOTWORD_FRAME_RATE, 1);
- if (!handle->format) {
- ret = -ENOMEM;
- goto cleanup;
- }
-
- handle->params = cras_client_unified_params_create(
- CRAS_STREAM_INPUT, HOTWORD_BLOCK_SIZE, CRAS_STREAM_TYPE_DEFAULT,
- HOTWORD_STREAM | TRIGGER_ONLY, (void *)handle, hotword_read_cb,
- hotword_err_cb, handle->format);
- if (!handle->params) {
- ret = -ENOMEM;
- goto cleanup_format;
- }
-
- handle->trigger_cb = trigger_cb;
- handle->err_cb = err_cb;
- handle->user_data = user_data;
-
- ret = cras_client_add_stream(client, &handle->stream_id,
- handle->params);
- if (ret)
- goto cleanup_params;
-
- *handle_out = handle;
- return 0;
-
-cleanup_params:
- cras_client_stream_params_destroy(handle->params);
-cleanup_format:
- cras_audio_format_destroy(handle->format);
-cleanup:
- free(handle);
- return ret;
-}
-
-int cras_client_disable_hotword_callback(struct cras_client *client,
- struct cras_hotword_handle *handle)
-{
- if (!client || !handle)
- return -EINVAL;
-
- cras_client_rm_stream(client, handle->stream_id);
- cras_audio_format_destroy(handle->format);
- cras_client_stream_params_destroy(handle->params);
- free(handle);
- return 0;
-}
-
-int get_nodes(struct cras_client *client, enum CRAS_STREAM_DIRECTION direction,
- struct libcras_node_info ***nodes, size_t *num)
-{
- struct cras_iodev_info iodevs[CRAS_MAX_IODEVS];
- struct cras_ionode_info ionodes[CRAS_MAX_IONODES];
- size_t num_devs = CRAS_MAX_IODEVS, num_nodes = CRAS_MAX_IONODES;
- int rc, i, j;
-
- *num = 0;
- if (direction == CRAS_STREAM_INPUT) {
- rc = cras_client_get_input_devices(client, iodevs, ionodes,
- &num_devs, &num_nodes);
- } else {
- rc = cras_client_get_output_devices(client, iodevs, ionodes,
- &num_devs, &num_nodes);
- }
-
- if (rc < 0) {
- syslog(LOG_ERR, "Failed to get devices: %d", rc);
- return rc;
- }
-
- *nodes = (struct libcras_node_info **)calloc(
- num_nodes, sizeof(struct libcras_node_info *));
-
- for (i = 0; i < num_devs; i++) {
- for (j = 0; j < num_nodes; j++) {
- if (iodevs[i].idx != ionodes[j].iodev_idx)
- continue;
- (*nodes)[*num] = libcras_node_info_create(&iodevs[i],
- &ionodes[j]);
- if ((*nodes)[*num] == NULL) {
- rc = -errno;
- goto clean;
- }
- (*num)++;
- }
- }
- return 0;
-clean:
- for (i = 0; i < *num; i++)
- libcras_node_info_destroy((*nodes)[i]);
- free(*nodes);
- *nodes = NULL;
- *num = 0;
- return rc;
-}
-
-int get_default_output_buffer_size(struct cras_client *client, int *size)
-{
- int rc = cras_client_get_default_output_buffer_size(client);
- if (rc < 0)
- return rc;
- *size = rc;
- return 0;
-}
-
-int get_aec_group_id(struct cras_client *client, int *id)
-{
- int rc = cras_client_get_aec_group_id(client);
- if (rc < 0)
- return rc;
- *id = rc;
- return 0;
-}
-
-int get_aec_supported(struct cras_client *client, int *supported)
-{
- *supported = cras_client_get_aec_supported(client);
- return 0;
-}
-
-int get_system_muted(struct cras_client *client, int *muted)
-{
- *muted = cras_client_get_system_muted(client);
- return 0;
-}
-
-int get_loopback_dev_idx(struct cras_client *client, int *idx)
-{
- int rc = cras_client_get_first_dev_type_idx(
- client, CRAS_NODE_TYPE_POST_MIX_PRE_DSP, CRAS_STREAM_INPUT);
- if (rc < 0)
- return rc;
- *idx = rc;
- return 0;
-}
-
-struct libcras_client *libcras_client_create()
-{
- struct libcras_client *client = (struct libcras_client *)calloc(
- 1, sizeof(struct libcras_client));
- if (!client) {
- syslog(LOG_ERR, "cras_client: calloc failed");
- return NULL;
- }
- if (cras_client_create(&client->client_)) {
- libcras_client_destroy(client);
- return NULL;
- }
- client->api_version = CRAS_API_VERSION;
- client->connect = cras_client_connect;
- client->connect_timeout = cras_client_connect_timeout;
- client->connected_wait = cras_client_connected_wait;
- client->run_thread = cras_client_run_thread;
- client->stop = cras_client_stop;
- client->add_pinned_stream = cras_client_add_pinned_stream;
- client->rm_stream = cras_client_rm_stream;
- client->set_stream_volume = cras_client_set_stream_volume;
- client->get_nodes = get_nodes;
- client->get_default_output_buffer_size = get_default_output_buffer_size;
- client->get_aec_group_id = get_aec_group_id;
- client->get_aec_supported = get_aec_supported;
- client->get_system_muted = get_system_muted;
- client->set_system_mute = cras_client_set_system_mute;
- client->get_loopback_dev_idx = get_loopback_dev_idx;
- return client;
-}
-
-void libcras_client_destroy(struct libcras_client *client)
-{
- cras_client_destroy(client->client_);
- free(client);
-}
-
-int stream_params_set(struct cras_stream_params *params,
- enum CRAS_STREAM_DIRECTION direction,
- size_t buffer_frames, size_t cb_threshold,
- enum CRAS_STREAM_TYPE stream_type,
- enum CRAS_CLIENT_TYPE client_type, uint32_t flags,
- void *user_data, libcras_stream_cb_t stream_cb,
- cras_error_cb_t err_cb, size_t rate,
- snd_pcm_format_t format, size_t num_channels)
-{
- params->direction = direction;
- params->buffer_frames = buffer_frames;
- params->cb_threshold = cb_threshold;
- params->stream_type = stream_type;
- params->client_type = client_type;
- params->flags = flags;
- params->user_data = user_data;
- params->stream_cb = stream_cb;
- params->err_cb = err_cb;
- params->format.frame_rate = rate;
- params->format.format = format;
- params->format.num_channels = num_channels;
- return 0;
-}
-
-int stream_params_set_channel_layout(struct cras_stream_params *params,
- int length, const int8_t *layout)
-{
- if (length != CRAS_CH_MAX)
- return -EINVAL;
- return cras_audio_format_set_channel_layout(&params->format, layout);
-}
-
-struct libcras_stream_params *libcras_stream_params_create()
-{
- struct libcras_stream_params *params =
- (struct libcras_stream_params *)calloc(
- 1, sizeof(struct libcras_stream_params));
- if (!params) {
- syslog(LOG_ERR, "cras_client: calloc failed");
- return NULL;
- }
- params->params_ = (struct cras_stream_params *)calloc(
- 1, sizeof(struct cras_stream_params));
- if (params->params_ == NULL) {
- syslog(LOG_ERR, "cras_client: calloc failed");
- free(params->params_);
- return NULL;
- }
- params->api_version = CRAS_API_VERSION;
- params->set = stream_params_set;
- params->set_channel_layout = stream_params_set_channel_layout;
- params->enable_aec = cras_client_stream_params_enable_aec;
- return params;
-}
-
-void libcras_stream_params_destroy(struct libcras_stream_params *params)
-{
- free(params->params_);
- free(params);
-}
-
-struct cras_node_info {
- uint64_t id;
- uint32_t dev_idx;
- uint32_t node_idx;
- uint32_t max_supported_channels;
- bool plugged;
- bool active;
- char type[CRAS_NODE_TYPE_BUFFER_SIZE];
- char node_name[CRAS_NODE_NAME_BUFFER_SIZE];
- char dev_name[CRAS_IODEV_NAME_BUFFER_SIZE];
-};
-
-int cras_node_info_get_id(struct cras_node_info *node, uint64_t *id)
-{
- (*id) = node->id;
- return 0;
-}
-
-int cras_node_info_get_dev_idx(struct cras_node_info *node, uint32_t *dev_idx)
-{
- (*dev_idx) = node->dev_idx;
- return 0;
-}
-
-int cras_node_info_get_node_idx(struct cras_node_info *node, uint32_t *node_idx)
-{
- (*node_idx) = node->node_idx;
- return 0;
-}
-
-int cras_node_info_get_max_supported_channels(struct cras_node_info *node,
- uint32_t *max_supported_channels)
-{
- (*max_supported_channels) = node->max_supported_channels;
- return 0;
-}
-
-int cras_node_info_is_plugged(struct cras_node_info *node, bool *is_plugged)
-{
- (*is_plugged) = node->plugged;
- return 0;
-}
-
-int cras_node_info_is_active(struct cras_node_info *node, bool *is_active)
-{
- (*is_active) = node->active;
- return 0;
-}
-
-int cras_node_info_get_type(struct cras_node_info *node, char **type)
-{
- (*type) = node->type;
- return 0;
-}
-
-int cras_node_info_get_node_name(struct cras_node_info *node, char **node_name)
-{
- (*node_name) = node->node_name;
- return 0;
-}
-
-int cras_node_info_get_dev_name(struct cras_node_info *node, char **dev_name)
-{
- (*dev_name) = node->dev_name;
- return 0;
-}
-
-struct libcras_node_info *
-libcras_node_info_create(struct cras_iodev_info *iodev,
- struct cras_ionode_info *ionode)
-{
- struct libcras_node_info *node = (struct libcras_node_info *)calloc(
- 1, sizeof(struct libcras_node_info));
- if (!node) {
- syslog(LOG_ERR, "cras_client: calloc failed");
- return NULL;
- }
- node->node_ = (struct cras_node_info *)calloc(
- 1, sizeof(struct cras_node_info));
- if (node->node_ == NULL) {
- syslog(LOG_ERR, "cras_client: calloc failed");
- free(node);
- return NULL;
- }
- node->api_version = CRAS_API_VERSION;
- node->node_->id =
- cras_make_node_id(ionode->iodev_idx, ionode->ionode_idx);
- node->node_->dev_idx = ionode->iodev_idx;
- node->node_->node_idx = ionode->ionode_idx;
- node->node_->max_supported_channels = iodev->max_supported_channels;
- node->node_->plugged = ionode->plugged;
- node->node_->active = ionode->active;
- strncpy(node->node_->type, ionode->type, CRAS_NODE_TYPE_BUFFER_SIZE);
- node->node_->type[CRAS_NODE_TYPE_BUFFER_SIZE - 1] = '\0';
- strncpy(node->node_->node_name, ionode->name,
- CRAS_NODE_NAME_BUFFER_SIZE);
- node->node_->node_name[CRAS_NODE_NAME_BUFFER_SIZE - 1] = '\0';
- strncpy(node->node_->dev_name, iodev->name,
- CRAS_IODEV_NAME_BUFFER_SIZE);
- node->node_->dev_name[CRAS_IODEV_NAME_BUFFER_SIZE - 1] = '\0';
- node->get_id = cras_node_info_get_id;
- node->get_dev_idx = cras_node_info_get_dev_idx;
- node->get_node_idx = cras_node_info_get_node_idx;
- node->get_max_supported_channels =
- cras_node_info_get_max_supported_channels;
- node->is_plugged = cras_node_info_is_plugged;
- node->is_active = cras_node_info_is_active;
- node->get_type = cras_node_info_get_type;
- node->get_node_name = cras_node_info_get_node_name;
- node->get_dev_name = cras_node_info_get_dev_name;
- return node;
-}
-
-void libcras_node_info_destroy(struct libcras_node_info *node)
-{
- free(node->node_);
- free(node);
-}
-
-void libcras_node_info_array_destroy(struct libcras_node_info **nodes,
- size_t num)
-{
- int i;
- for (i = 0; i < num; i++)
- libcras_node_info_destroy(nodes[i]);
- free(nodes);
-}
diff --git a/cras/src/libcras/cras_client.h b/cras/src/libcras/cras_client.h
deleted file mode 100644
index f26a0814..00000000
--- a/cras/src/libcras/cras_client.h
+++ /dev/null
@@ -1,2008 +0,0 @@
-/* Copyright (c) 2012 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.
- *
- * This API creates multiple threads, one for control, and a thread per audio
- * stream. The control thread is used to receive messages and notifications
- * from the audio server, and manage the per-stream threads. API calls below
- * may send messages to the control thread, or directly to the server. It is
- * required that the control thread is running in order to support audio
- * streams and notifications from the server.
- *
- * The API has multiple initialization sequences, but some of those can block
- * while waiting for a response from the server.
- *
- * The following is the non-blocking API initialization sequence:
- * cras_client_create()
- * cras_client_set_connection_status_cb() (optional)
- * cras_client_run_thread()
- * cras_client_connect_async()
- *
- * The connection callback is executed asynchronously from the control thread
- * when the connection has been established. The connection callback should be
- * used to turn on or off interactions with any API call that communicates with
- * the audio server or starts/stops audio streams. The above is implemented by
- * cras_helper_create_connect_async().
- *
- * The following alternative (deprecated) initialization sequence can ensure
- * that the connection is established synchronously.
- *
- * Just connect to the server (no control thread):
- * cras_client_create()
- * cras_client_set_server_connection_cb() (optional)
- * one of:
- * cras_client_connect() (blocks forever)
- * or
- * cras_client_connect_timeout() (blocks for timeout)
- *
- * For API calls below that require the control thread to be running:
- * cras_client_run_thread();
- * cras_client_connected_wait(); (blocks up to 1 sec.)
- *
- * The above minus setting the connection callback is implemented within
- * cras_helper_create_connect().
- */
-
-#ifndef CRAS_CLIENT_H_
-#define CRAS_CLIENT_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <sys/select.h>
-
-#include "cras_iodev_info.h"
-#include "cras_types.h"
-#include "cras_util.h"
-
-struct cras_client;
-struct cras_hotword_handle;
-struct cras_stream_params;
-
-/* Callback for audio received or transmitted.
- * Args (All pointer will be valid - except user_arg, that's up to the user):
- * client: The client requesting service.
- * stream_id - Unique identifier for the stream needing data read/written.
- * samples - Read or write samples to/form here.
- * frames - Maximum number of frames to read or write.
- * sample_time - Playback time for the first sample read/written.
- * user_arg - Value passed to add_stream;
- * Return:
- * Returns the number of frames read or written on success, or a negative
- * number if there is a stream-fatal error. Returns EOF when the end of the
- * stream is reached.
- */
-typedef int (*cras_playback_cb_t)(struct cras_client *client,
- cras_stream_id_t stream_id, uint8_t *samples,
- size_t frames,
- const struct timespec *sample_time,
- void *user_arg);
-
-/* Callback for audio received and/or transmitted.
- * Args (All pointer will be valid - except user_arg, that's up to the user):
- * client: The client requesting service.
- * stream_id - Unique identifier for the stream needing data read/written.
- * captured_samples - Read samples form here.
- * playback_samples - Read or write samples to here.
- * frames - Maximum number of frames to read or write.
- * captured_time - Time the first sample was read.
- * playback_time - Playback time for the first sample written.
- * user_arg - Value passed to add_stream;
- * Return:
- * Returns the number of frames read or written on success, or a negative
- * number if there is a stream-fatal error. Returns EOF when the end of the
- * stream is reached.
- */
-typedef int (*cras_unified_cb_t)(struct cras_client *client,
- cras_stream_id_t stream_id,
- uint8_t *captured_samples,
- uint8_t *playback_samples, unsigned int frames,
- const struct timespec *captured_time,
- const struct timespec *playback_time,
- void *user_arg);
-
-/* Callback for handling stream errors.
- * Args:
- * client - The client created with cras_client_create().
- * stream_id - The ID for this stream.
- * error - The error code,
- * user_arg - The argument defined in cras_client_*_params_create().
- */
-typedef int (*cras_error_cb_t)(struct cras_client *client,
- cras_stream_id_t stream_id, int error,
- void *user_arg);
-
-/* Server connection status. */
-typedef enum cras_connection_status {
- CRAS_CONN_STATUS_FAILED,
- /* Resource allocation problem. Free resources, and retry the
- * connection with cras_client_connect_async(), or (blocking)
- * cras_client_connect(). Do not call cras_client_connect(),
- * cras_client_connect_timeout(), or cras_client_destroy()
- * from the callback. */
- CRAS_CONN_STATUS_DISCONNECTED,
- /* The control thread is attempting to reconnect to the
- * server in the background. Any attempt to access the
- * server will fail or block (see
- * cras_client_set_server_message_blocking(). */
- CRAS_CONN_STATUS_CONNECTED,
- /* Connection is established. All state change callbacks
- * have been re-registered, but audio streams must be
- * restarted, and node state data must be updated. */
-} cras_connection_status_t;
-
-/* Callback for handling server connection status.
- *
- * See also cras_client_set_connection_status_cb(). Do not call
- * cras_client_connect(), cras_client_connect_timeout(), or
- * cras_client_destroy() from this callback.
- *
- * Args:
- * client - The client created with cras_client_create().
- * status - The status of the connection to the server.
- * user_arg - The argument defined in
- * cras_client_set_connection_status_cb().
- */
-typedef void (*cras_connection_status_cb_t)(struct cras_client *client,
- cras_connection_status_t status,
- void *user_arg);
-
-/* Callback for setting thread priority. */
-typedef void (*cras_thread_priority_cb_t)(struct cras_client *client);
-
-/* Callback for handling get hotword models reply. */
-typedef void (*get_hotword_models_cb_t)(struct cras_client *client,
- const char *hotword_models);
-
-/* Callback to wait for a hotword trigger. */
-typedef void (*cras_hotword_trigger_cb_t)(struct cras_client *client,
- struct cras_hotword_handle *handle,
- void *user_data);
-
-/* Callback for handling hotword errors. */
-typedef int (*cras_hotword_error_cb_t)(struct cras_client *client,
- struct cras_hotword_handle *handle,
- int error, void *user_data);
-
-/*
- * Client handling.
- */
-
-/* Creates a new client.
- * Args:
- * client - Filled with a pointer to the new client.
- * Returns:
- * 0 on success (*client is filled with a valid cras_client pointer).
- * Negative error code on failure(*client will be NULL).
- */
-int cras_client_create(struct cras_client **client);
-
-/* Creates a new client with given connection type.
- * Args:
- * client - Filled with a pointer to the new client.
- * conn_type - enum CRAS_CONNECTION_TYPE
- *
- * Returns:
- * 0 on success (*client is filled with a valid cras_client pointer).
- * Negative error code on failure(*client will be NULL).
- */
-int cras_client_create_with_type(struct cras_client **client,
- enum CRAS_CONNECTION_TYPE conn_type);
-
-/* Destroys a client.
- * Args:
- * client - returned from "cras_client_create".
- */
-void cras_client_destroy(struct cras_client *client);
-
-/* Connects a client to the running server.
- * Waits forever (until interrupted or connected).
- * Args:
- * client - pointer returned from "cras_client_create".
- * Returns:
- * 0 on success, or a negative error code on failure (from errno.h).
- */
-int cras_client_connect(struct cras_client *client);
-
-/* Connects a client to the running server, retries until timeout.
- * Args:
- * client - pointer returned from "cras_client_create".
- * timeout_ms - timeout in milliseconds or negative to wait forever.
- * Returns:
- * 0 on success, or a negative error code on failure (from errno.h).
- */
-int cras_client_connect_timeout(struct cras_client *client,
- unsigned int timeout_ms);
-
-/* Begins running the client control thread.
- *
- * Required for stream operations and other operations noted below.
- *
- * Args:
- * client - the client to start (from cras_client_create).
- * Returns:
- * 0 on success or if the thread is already running, -EINVAL if the client
- * pointer is NULL, or the negative result of pthread_create().
- */
-int cras_client_run_thread(struct cras_client *client);
-
-/* Stops running a client.
- * This function is executed automatically by cras_client_destroy().
- * Args:
- * client - the client to stop (from cras_client_create).
- * Returns:
- * 0 on success or if the thread was already stopped, -EINVAL if the client
- * isn't valid.
- */
-int cras_client_stop(struct cras_client *client);
-
-/* Wait up to 1 second for the client thread to complete the server connection.
- *
- * After cras_client_run_thread() is executed, this function can be used to
- * ensure that the connection has been established with the server and ensure
- * that any information about the server is up to date. If
- * cras_client_run_thread() has not yet been executed, or cras_client_stop()
- * was executed and thread isn't running, then this function returns -EINVAL.
- *
- * Args:
- * client - pointer returned from "cras_client_create".
- * Returns:
- * 0 on success, or a negative error code on failure (from errno.h).
- */
-int cras_client_connected_wait(struct cras_client *client);
-
-/* Ask the client control thread to connect to the audio server.
- *
- * After cras_client_run_thread() is executed, this function can be used
- * to ask the control thread to connect to the audio server asynchronously.
- * The callback set with cras_client_set_connection_status_cb() will be
- * executed when the connection is established.
- *
- * Args:
- * client - The client from cras_client_create().
- * Returns:
- * 0 on success, or a negative error code on failure (from errno.h).
- * -EINVAL if the client pointer is invalid or the control thread is
- * not running.
- */
-int cras_client_connect_async(struct cras_client *client);
-
-/* Sets server connection status callback.
- *
- * See cras_connection_status_t for a description of the connection states
- * and appropriate user action.
- *
- * Args:
- * client - The client from cras_client_create.
- * connection_cb - The callback function to register.
- * user_arg - Pointer that will be passed to the callback.
- */
-void cras_client_set_connection_status_cb(
- struct cras_client *client, cras_connection_status_cb_t connection_cb,
- void *user_arg);
-
-/* Sets callback for setting thread priority.
- * Args:
- * client - The client from cras_client_create.
- * cb - The thread priority callback.
- */
-void cras_client_set_thread_priority_cb(struct cras_client *client,
- cras_thread_priority_cb_t cb);
-
-/* Returns the current list of output devices.
- *
- * Requires that the connection to the server has been established.
- *
- * Data is copied and thus can become out of date. This call must be
- * re-executed to get updates.
- *
- * Args:
- * client - The client from cras_client_create.
- * devs - Array that will be filled with device info.
- * nodes - Array that will be filled with node info.
- * *num_devs - Maximum number of devices to put in the array.
- * *num_nodes - Maximum number of nodes to put in the array.
- * Returns:
- * 0 on success, -EINVAL if the client isn't valid or isn't running.
- * *num_devs is set to the actual number of devices info filled.
- * *num_nodes is set to the actual number of nodes info filled.
- */
-int cras_client_get_output_devices(const struct cras_client *client,
- struct cras_iodev_info *devs,
- struct cras_ionode_info *nodes,
- size_t *num_devs, size_t *num_nodes);
-
-/* Returns the current list of input devices.
- *
- * Requires that the connection to the server has been established.
- *
- * Data is copied and thus can become out of date. This call must be
- * re-executed to get updates.
- *
- * Args:
- * client - The client from cras_client_create.
- * devs - Array that will be filled with device info.
- * nodes - Array that will be filled with node info.
- * *num_devs - Maximum number of devices to put in the array.
- * *num_nodes - Maximum number of nodes to put in the array.
- * Returns:
- * 0 on success, -EINVAL if the client isn't valid or isn't running.
- * *num_devs is set to the actual number of devices info filled.
- * *num_nodes is set to the actual number of nodes info filled.
- */
-int cras_client_get_input_devices(const struct cras_client *client,
- struct cras_iodev_info *devs,
- struct cras_ionode_info *nodes,
- size_t *num_devs, size_t *num_nodes);
-
-/* Returns the current list of clients attached to the server.
- *
- * Requires that the connection to the server has been established.
- *
- * Data is copied and thus can become out of date. This call must be
- * re-executed to get updates.
- *
- * Args:
- * client - This client (from cras_client_create).
- * clients - Array that will be filled with a list of attached clients.
- * max_clients - Maximum number of clients to put in the array.
- * Returns:
- * The number of attached clients. This may be more that max_clients passed
- * in, this indicates that all of the clients wouldn't fit in the provided
- * array.
- */
-int cras_client_get_attached_clients(const struct cras_client *client,
- struct cras_attached_client_info *clients,
- size_t max_clients);
-
-/* Find a node info with the matching node id.
- *
- * Requires that the connection to the server has been established.
- *
- * Data is copied and thus can become out of date. This call must be
- * re-executed to get updates.
- *
- * Args:
- * client - This client (from cras_client_create).
- * input - Non-zero for input nodes, zero for output nodes.
- * node_id - The node id to look for.
- * node_info - The information about the ionode will be returned here.
- * Returns:
- * 0 if successful, negative on error; -ENOENT if the node cannot be found.
- */
-int cras_client_get_node_by_id(const struct cras_client *client, int input,
- const cras_node_id_t node_id,
- struct cras_ionode_info *node_info);
-
-/* Checks if the output device with the given name is currently plugged in.
- *
- * For internal devices this checks that jack state, for USB devices this will
- * always be true if they are present. The name parameter can be the complete
- * name or any unique prefix of the name. If the name is not unique the first
- * matching name will be checked.
- *
- * Requires that the connection to the server has been established.
- *
- * Data is copied and thus can become out of date. This call must be
- * re-executed to get updates.
- *
- * Args:
- * client - The client from cras_client_create.
- * name - Name of the device to check.
- * Returns:
- * 1 if the device exists and is plugged, 0 otherwise.
- */
-int cras_client_output_dev_plugged(const struct cras_client *client,
- const char *name);
-
-/* Set the value of an attribute of an ionode.
- *
- * Args:
- * client - The client from cras_client_create.
- * node_id - The id of the ionode.
- * attr - the attribute we want to change.
- * value - the value we want to set.
- * Returns:
- * Returns 0 for success, negative on error (from errno.h).
- */
-int cras_client_set_node_attr(struct cras_client *client,
- cras_node_id_t node_id, enum ionode_attr attr,
- int value);
-
-/* Select the preferred node for playback/capture.
- *
- * Args:
- * client - The client from cras_client_create.
- * direction - The direction of the ionode.
- * node_id - The id of the ionode. If node_id is the special value 0, then
- * the preference is cleared and cras will choose automatically.
- */
-int cras_client_select_node(struct cras_client *client,
- enum CRAS_STREAM_DIRECTION direction,
- cras_node_id_t node_id);
-
-/* Adds an active node for playback/capture.
- *
- * Args:
- * client - The client from cras_client_create.
- * direction - The direction of the ionode.
- * node_id - The id of the ionode. If there's no node matching given
- * id, nothing will happen in CRAS.
- */
-int cras_client_add_active_node(struct cras_client *client,
- enum CRAS_STREAM_DIRECTION direction,
- cras_node_id_t node_id);
-
-/* Removes an active node for playback/capture.
- *
- * Args:
- * client - The client from cras_client_create.
- * direction - The direction of the ionode.
- * node_id - The id of the ionode. If there's no node matching given
- * id, nothing will happen in CRAS.
- */
-int cras_client_rm_active_node(struct cras_client *client,
- enum CRAS_STREAM_DIRECTION direction,
- cras_node_id_t node_id);
-
-/* Asks the server to reload dsp plugin configuration from the ini file.
- *
- * Args:
- * client - The client from cras_client_create.
- * Returns:
- * 0 on success, -EINVAL if the client isn't valid or isn't running.
- */
-int cras_client_reload_dsp(struct cras_client *client);
-
-/* Asks the server to dump current dsp information to syslog.
- *
- * Args:
- * client - The client from cras_client_create.
- * Returns:
- * 0 on success, -EINVAL if the client isn't valid or isn't running.
- */
-int cras_client_dump_dsp_info(struct cras_client *client);
-
-/* Asks the server to dump current audio thread information.
- *
- * Args:
- * client - The client from cras_client_create.
- * cb - A function to call when the data is received.
- * Returns:
- * 0 on success, -EINVAL if the client isn't valid or isn't running.
- */
-int cras_client_update_audio_debug_info(struct cras_client *client,
- void (*cb)(struct cras_client *));
-
-/* Asks the server to dump current main thread information.
- * Args:
- * client - The client from cras_client_create.
- * cb - A function to call when the data is received.
- * Returns:
- * 0 on success, -EINVAL if the client isn't valid or isn't running.
- */
-int cras_client_update_main_thread_debug_info(struct cras_client *client,
- void (*cb)(struct cras_client *));
-
-/* Asks the server to dump bluetooth debug information.
- * Args:
- * client - The client from cras_client_create.
- * cb - Function to call when debug info is ready.
- * Returns:
- * 0 on success, -EINVAL if the client isn't valid or isn't running.
- */
-int cras_client_update_bt_debug_info(struct cras_client *client,
- void (*cb)(struct cras_client *));
-
-/* Gets read-only access to audio thread log. Should be called once before
- calling cras_client_read_atlog.
- * Args:
- * client - The client from cras_client_create.
- * atlog_access_cb - Function to call after getting atlog access.
- * Returns:
- * 0 on success, -EINVAL if the client or atlog_access_cb isn't valid.
- */
-int cras_client_get_atlog_access(struct cras_client *client,
- void (*atlog_access_cb)(struct cras_client *));
-
-/* Reads continuous audio thread log into 'buf', starting from 'read_idx'-th log
- * till the latest. The number of missing logs within the range will be stored
- * in 'missing'. Requires calling cras_client_get_atlog_access() beforehand
- * to get access to audio thread log.
- * Args:
- * client - The client from cras_client_create.
- * read_idx - The log number to start reading with.
- * missing - The pointer to store the number of missing logs.
- * buf - The buffer to which continuous logs will be copied.
- * Returns:
- * The number of logs copied. < 0 if failed to read audio thread log.
- */
-int cras_client_read_atlog(struct cras_client *client, uint64_t *read_idx,
- uint64_t *missing,
- struct audio_thread_event_log *buf);
-
-/* Asks the server to dump current audio thread snapshots.
- *
- * Args:
- * client - The client from cras_client_create.
- * cb - A function to call when the data is received.
- * Returns:
- * 0 on success, -EINVAL if the client isn't valid or isn't running.
- */
-int cras_client_update_audio_thread_snapshots(struct cras_client *client,
- void (*cb)(struct cras_client *));
-
-/* Gets the max supported channel count of the output device from node_id.
- * Args:
- * client - The client from cras_client_create.
- * node_id - ID of the node.
- * max_channels - Out parameter will be filled with the max supported channel
- * count.
- * Returns:
- * 0 on success, or negative error code on failure.
- */
-int cras_client_get_max_supported_channels(const struct cras_client *client,
- cras_node_id_t node_id,
- uint32_t *max_channels);
-
-/*
- * Stream handling.
- */
-
-/* Setup stream configuration parameters.
- * Args:
- * direction - playback(CRAS_STREAM_OUTPUT) or capture(CRAS_STREAM_INPUT).
- * buffer_frames - total number of audio frames to buffer (dictates latency).
- * cb_threshold - For playback, call back for more data when the buffer
- * reaches this level. For capture, this is ignored (Audio callback will
- * be called when buffer_frames have been captured).
- * unused - No longer used.
- * stream_type - media or talk (currently only support "default").
- * flags - Currently only used for CRAS_INPUT_STREAM_FLAG.
- * user_data - Pointer that will be passed to the callback.
- * aud_cb - Called when audio is needed(playback) or ready(capture). Allowed
- * return EOF to indicate that the stream should terminate.
- * err_cb - Called when there is an error with the stream.
- * format - The format of the audio stream. Specifies bits per sample,
- * number of channels, and sample rate.
- */
-struct cras_stream_params *cras_client_stream_params_create(
- enum CRAS_STREAM_DIRECTION direction, size_t buffer_frames,
- size_t cb_threshold, size_t unused, enum CRAS_STREAM_TYPE stream_type,
- uint32_t flags, void *user_data, cras_playback_cb_t aud_cb,
- cras_error_cb_t err_cb, struct cras_audio_format *format);
-
-/* Functions to set the client type on given stream parameter.
- * Args:
- * params - Stream configuration parameters.
- * client_type - A client type.
- */
-void cras_client_stream_params_set_client_type(
- struct cras_stream_params *params, enum CRAS_CLIENT_TYPE client_type);
-
-/* Functions to enable or disable specific effect on given stream parameter.
- * Args:
- * params - Stream configuration parameters.
- */
-void cras_client_stream_params_enable_aec(struct cras_stream_params *params);
-void cras_client_stream_params_disable_aec(struct cras_stream_params *params);
-void cras_client_stream_params_enable_ns(struct cras_stream_params *params);
-void cras_client_stream_params_disable_ns(struct cras_stream_params *params);
-void cras_client_stream_params_enable_agc(struct cras_stream_params *params);
-void cras_client_stream_params_disable_agc(struct cras_stream_params *params);
-void cras_client_stream_params_enable_vad(struct cras_stream_params *params);
-void cras_client_stream_params_disable_vad(struct cras_stream_params *params);
-
-/* Setup stream configuration parameters. DEPRECATED.
- * TODO(crbug.com/972928): remove this
- * Use cras_client_stream_params_create instead.
- * Args:
- * direction - playback(CRAS_STREAM_OUTPUT) or capture(CRAS_STREAM_INPUT) or
- * loopback(CRAS_STREAM_POST_MIX_PRE_DSP).
- * block_size - The number of frames per callback(dictates latency).
- * stream_type - media or talk (currently only support "default").
- * flags - None currently used.
- * user_data - Pointer that will be passed to the callback.
- * unified_cb - Called to request audio data or to notify the client when
- * captured audio is available. Though this is a unified_cb,
- * only one direction will be used for a stream, depending
- * on the 'direction' parameter.
- * err_cb - Called when there is an error with the stream.
- * format - The format of the audio stream. Specifies bits per sample,
- * number of channels, and sample rate.
- */
-struct cras_stream_params *cras_client_unified_params_create(
- enum CRAS_STREAM_DIRECTION direction, unsigned int block_size,
- enum CRAS_STREAM_TYPE stream_type, uint32_t flags, void *user_data,
- cras_unified_cb_t unified_cb, cras_error_cb_t err_cb,
- struct cras_audio_format *format);
-
-/* Destroy stream params created with cras_client_stream_params_create. */
-void cras_client_stream_params_destroy(struct cras_stream_params *params);
-
-/* Creates a new stream and return the stream id or < 0 on error.
- *
- * Requires execution of cras_client_run_thread(), and an active connection
- * to the audio server.
- *
- * Args:
- * client - The client to add the stream to (from cras_client_create).
- * stream_id_out - On success will be filled with the new stream id.
- * Guaranteed to be set before any callbacks are made.
- * config - The cras_stream_params struct specifying the parameters for the
- * stream.
- * Returns:
- * 0 on success, negative error code on failure (from errno.h).
- */
-int cras_client_add_stream(struct cras_client *client,
- cras_stream_id_t *stream_id_out,
- struct cras_stream_params *config);
-
-/* Creates a pinned stream and return the stream id or < 0 on error.
- *
- * Requires execution of cras_client_run_thread(), and an active connection
- * to the audio server.
- *
- * Args:
- * client - The client to add the stream to (from cras_client_create).
- * dev_idx - Index of the device to attach the newly created stream.
- * stream_id_out - On success will be filled with the new stream id.
- * Guaranteed to be set before any callbacks are made.
- * config - The cras_stream_params struct specifying the parameters for the
- * stream.
- * Returns:
- * 0 on success, negative error code on failure (from errno.h).
- */
-int cras_client_add_pinned_stream(struct cras_client *client, uint32_t dev_idx,
- cras_stream_id_t *stream_id_out,
- struct cras_stream_params *config);
-
-/* Removes a currently playing/capturing stream.
- *
- * Requires execution of cras_client_run_thread().
- *
- * Args:
- * client - Client to remove the stream (returned from cras_client_create).
- * stream_id - ID returned from cras_client_add_stream to identify the stream
- to remove.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-int cras_client_rm_stream(struct cras_client *client,
- cras_stream_id_t stream_id);
-
-/* Sets the volume scaling factor for the given stream.
- *
- * Requires execution of cras_client_run_thread().
- *
- * Args:
- * client - Client owning the stream.
- * stream_id - ID returned from cras_client_add_stream.
- * volume_scaler - 0.0-1.0 the new value to scale this stream by.
- */
-int cras_client_set_stream_volume(struct cras_client *client,
- cras_stream_id_t stream_id,
- float volume_scaler);
-
-/*
- * System level functions.
- */
-
-/* Sets the volume of the system.
- *
- * Volume here ranges from 0 to 100, and will be translated to dB based on the
- * output-specific volume curve.
- *
- * Args:
- * client - The client from cras_client_create.
- * volume - 0-100 the new volume index.
- * Returns:
- * 0 for success, -EPIPE if there is an I/O error talking to the server, or
- * -EINVAL if 'client' is invalid.
- */
-int cras_client_set_system_volume(struct cras_client *client, size_t volume);
-
-/* Sets the mute state of the system.
- *
- * Args:
- * client - The client from cras_client_create.
- * mute - 0 is un-mute, 1 is muted.
- * Returns:
- * 0 for success, -EPIPE if there is an I/O error talking to the server, or
- * -EINVAL if 'client' is invalid.
- */
-int cras_client_set_system_mute(struct cras_client *client, int mute);
-
-/* Sets the user mute state of the system.
- *
- * This is used for mutes caused by user interaction. Like the mute key.
- *
- * Args:
- * client - The client from cras_client_create.
- * mute - 0 is un-mute, 1 is muted.
- * Returns:
- * 0 for success, -EPIPE if there is an I/O error talking to the server, or
- * -EINVAL if 'client' is invalid.
- */
-int cras_client_set_user_mute(struct cras_client *client, int mute);
-
-/* Sets the mute locked state of the system.
- *
- * Changing mute state is impossible when this flag is set to locked.
- *
- * Args:
- * client - The client from cras_client_create.
- * locked - 0 is un-locked, 1 is locked.
- * Returns:
- * 0 for success, -EPIPE if there is an I/O error talking to the server, or
- * -EINVAL if 'client' is invalid.
- */
-int cras_client_set_system_mute_locked(struct cras_client *client, int locked);
-
-/* Sets the capture mute state of the system.
- *
- * Recordings will be muted when this is set.
- *
- * Args:
- * client - The client from cras_client_create.
- * mute - 0 is un-mute, 1 is muted.
- * Returns:
- * 0 for success, -EPIPE if there is an I/O error talking to the server, or
- * -EINVAL if 'client' is invalid.
- */
-int cras_client_set_system_capture_mute(struct cras_client *client, int mute);
-
-/* Sets the capture mute locked state of the system.
- *
- * Changing mute state is impossible when this flag is set to locked.
- *
- * Args:
- * client - The client from cras_client_create.
- * locked - 0 is un-locked, 1 is locked.
- * Returns:
- * 0 for success, -EPIPE if there is an I/O error talking to the server, or
- * -EINVAL if 'client' is invalid.
- */
-int cras_client_set_system_capture_mute_locked(struct cras_client *client,
- int locked);
-
-/* Gets the current system volume.
- *
- * Requires that the connection to the server has been established.
- *
- * Args:
- * client - The client from cras_client_create.
- * Returns:
- * The current system volume between 0 and 100.
- */
-size_t cras_client_get_system_volume(const struct cras_client *client);
-
-/* Gets the current system mute state.
- *
- * Requires that the connection to the server has been established.
- *
- * Args:
- * client - The client from cras_client_create.
- * Returns:
- * 0 if not muted, 1 if it is.
- */
-int cras_client_get_system_muted(const struct cras_client *client);
-
-/* Gets the current user mute state.
- *
- * Requires that the connection to the server has been established.
- *
- * Args:
- * client - The client from cras_client_create.
- * Returns:
- * 0 if not muted, 1 if it is.
- */
-int cras_client_get_user_muted(const struct cras_client *client);
-
-/* Gets the current system capture mute state.
- *
- * Requires that the connection to the server has been established.
- *
- * Args:
- * client - The client from cras_client_create.
- * Returns:
- * 0 if capture is not muted, 1 if it is.
- */
-int cras_client_get_system_capture_muted(const struct cras_client *client);
-
-/* Gets the current minimum system volume.
- * Args:
- * client - The client from cras_client_create.
- * Returns:
- * The minimum value for the current output device in dBFS * 100. This is
- * the level of attenuation at volume == 1.
- */
-long cras_client_get_system_min_volume(const struct cras_client *client);
-
-/* Gets the current maximum system volume.
- * Args:
- * client - The client from cras_client_create.
- * Returns:
- * The maximum value for the current output device in dBFS * 100. This is
- * the level of attenuation at volume == 100.
- */
-long cras_client_get_system_max_volume(const struct cras_client *client);
-
-/* Gets the default output buffer size.
- * Args:
- * client - The client from cras_client_create.
- * Returns:
- * Default output buffer size in frames. A negative error on failure.
- */
-int cras_client_get_default_output_buffer_size(struct cras_client *client);
-
-/* Gets audio debug info.
- *
- * Requires that the connection to the server has been established.
- * Access to the resulting pointer is not thread-safe.
- *
- * Args:
- * client - The client from cras_client_create.
- * Returns:
- * A pointer to the debug info. This info is only updated when requested by
- * calling cras_client_update_audio_debug_info.
- */
-const struct audio_debug_info *
-cras_client_get_audio_debug_info(const struct cras_client *client);
-
-/* Gets bluetooth debug info.
- *
- * Requires that the connection to the server has been established.
- *
- * Args:
- * client - The client from cras_client_create.
- * Returns:
- * A pointer to the debug info. This info is updated and requested by
- * calling cras_client_update_bt_debug_info.
- */
-const struct cras_bt_debug_info *
-cras_client_get_bt_debug_info(const struct cras_client *client);
-
-/* Gets main thread debug info.
- * Args:
- * client - The client from cras_client_create.
- * Returns:
- * A pointer to the debug info. This info is updated and requested by
- * calling cras_client_update_main_thread_debug_info.
- */
-const struct main_thread_debug_info *
-cras_client_get_main_thread_debug_info(const struct cras_client *client);
-
-/* Gets audio thread snapshot buffer.
- *
- * Requires that the connection to the server has been established.
- * Access to the resulting pointer is not thread-safe.
- *
- * Args:
- * client - The client from cras_client_create.
- * Returns:
- * A pointer to the snapshot buffer. This info is only updated when
- * requested by calling cras_client_update_audio_thread_snapshots.
- */
-const struct cras_audio_thread_snapshot_buffer *
-cras_client_get_audio_thread_snapshot_buffer(const struct cras_client *client);
-
-/* Gets the number of streams currently attached to the server.
- *
- * This is the total number of capture and playback streams. If the ts argument
- * is not null, then it will be filled with the last time audio was played or
- * recorded. ts will be set to the current time if streams are currently
- * active.
- *
- * Requires that the connection to the server has been established.
- *
- * Args:
- * client - The client from cras_client_create.
- * ts - Filled with the timestamp of the last stream.
- * Returns:
- * The number of active streams.
- */
-unsigned cras_client_get_num_active_streams(const struct cras_client *client,
- struct timespec *ts);
-
-/*
- * Utility functions.
- */
-
-/* Returns the number of bytes in an audio frame for a stream.
- * Args:
- * format - The format of the audio stream. Specifies bits per sample,
- * number of channels, and sample rate.
- * Returns:
- * Positive number of bytes in a frame, or a negative error code if fmt is
- * NULL.
- */
-int cras_client_format_bytes_per_frame(struct cras_audio_format *fmt);
-
-/* For playback streams, calculates the latency of the next sample written.
- * Only valid when called from the audio callback function for the stream
- * (aud_cb).
- * Args:
- * sample_time - The sample time stamp passed in to aud_cb.
- * delay - Out parameter will be filled with the latency.
- * Returns:
- * 0 on success, -EINVAL if delay is NULL.
- */
-int cras_client_calc_playback_latency(const struct timespec *sample_time,
- struct timespec *delay);
-
-/* For capture returns the latency of the next frame to be read from the buffer
- * (based on when it was captured). Only valid when called from the audio
- * callback function for the stream (aud_cb).
- * Args:
- * sample_time - The sample time stamp passed in to aud_cb.
- * delay - Out parameter will be filled with the latency.
- * Returns:
- * 0 on success, -EINVAL if delay is NULL.
- */
-int cras_client_calc_capture_latency(const struct timespec *sample_time,
- struct timespec *delay);
-
-/* Set the volume of the given output node. Only for output nodes.
- *
- * Args:
- * client - The client from cras_client_create.
- * node_id - ID of the node.
- * volume - New value for node volume.
- */
-int cras_client_set_node_volume(struct cras_client *client,
- cras_node_id_t node_id, uint8_t volume);
-
-/* Swap the left and right channel of the given node.
- *
- * Args:
- * client - The client from cras_client_create.
- * node_id - ID of the node.
- * enable - 1 to enable swap mode, 0 to disable.
- */
-int cras_client_swap_node_left_right(struct cras_client *client,
- cras_node_id_t node_id, int enable);
-
-/* Set the capture gain of the given input node. Only for input nodes.
- *
- * Args:
- * client - The client from cras_client_create.
- * node_id - ID of the node.
- * gain - New capture gain for the node, in range (0, 100) which will
- * linearly maps to (-4000, 4000) 100*dBFS.
- */
-int cras_client_set_node_capture_gain(struct cras_client *client,
- cras_node_id_t node_id, long gain);
-
-/* Add a test iodev to the iodev list.
- *
- * Args:
- * client - The client from cras_client_create.
- * type - The type of test iodev, see cras_types.h
- */
-int cras_client_add_test_iodev(struct cras_client *client,
- enum TEST_IODEV_TYPE type);
-
-/* Send a test command to a test iodev.
- *
- * Args:
- * client - The client from cras_client_create.
- * iodev_idx - The index of the test iodev.
- * command - The command to send.
- * data_len - Length of command data.
- * data - Command data.
- */
-int cras_client_test_iodev_command(struct cras_client *client,
- unsigned int iodev_idx,
- enum CRAS_TEST_IODEV_CMD command,
- unsigned int data_len, const uint8_t *data);
-
-/* Finds the first node of the given type.
- *
- * This is used for finding a special hotword node.
- *
- * Requires that the connection to the server has been established.
- *
- * Args:
- * client - The client from cras_client_create.
- * type - The type of device to find.
- * direction - Search input or output devices.
- * node_id - The found node on success.
- * Returns:
- * 0 on success, a negative error on failure.
- */
-int cras_client_get_first_node_type_idx(const struct cras_client *client,
- enum CRAS_NODE_TYPE type,
- enum CRAS_STREAM_DIRECTION direction,
- cras_node_id_t *node_id);
-
-/* Finds the first device that contains a node of the given type.
- *
- * This is used for finding a special hotword device.
- *
- * Requires that the connection to the server has been established.
- *
- * Args:
- * client - The client from cras_client_create.
- * type - The type of device to find.
- * direction - Search input or output devices.
- * Returns the device index of a negative error on failure.
- */
-int cras_client_get_first_dev_type_idx(const struct cras_client *client,
- enum CRAS_NODE_TYPE type,
- enum CRAS_STREAM_DIRECTION direction);
-
-/* Sets the suspend state of audio playback and capture.
- *
- * Set this before putting the system into suspend.
- *
- * Args:
- * client - The client from cras_client_create.
- * suspend - Suspend the system if non-zero, otherwise resume.
- */
-int cras_client_set_suspend(struct cras_client *client, int suspend);
-
-/* Configures the global converter for output remixing.
- *
- * Args:
- * client - The client from cras_client_create.
- * num_channels - Number of output channels.
- * coefficient - Float array representing |num_channels| * |num_channels|
- * matrix. Channels of mixed PCM output will be remixed by
- * multiplying this matrix.
- */
-int cras_client_config_global_remix(struct cras_client *client,
- unsigned num_channels, float *coefficient);
-
-/* Gets the set of supported hotword language models on a node. The supported
- * models may differ on different nodes.
- *
- * Args:
- * client - The client from cras_client_create.
- * node_id - ID of a hotword input node (CRAS_NODE_TYPE_HOTWORD).
- * cb - The function to be called when hotword models are ready.
- * Returns:
- * 0 on success.
- */
-int cras_client_get_hotword_models(struct cras_client *client,
- cras_node_id_t node_id,
- get_hotword_models_cb_t cb);
-
-/* Sets the hotword language model on a node. If there are existing streams on
- * the hotword input node when this function is called, they need to be closed
- * then re-opend for the model change to take effect.
- * Args:
- * client - The client from cras_client_create.
- * node_id - ID of a hotword input node (CRAS_NODE_TYPE_HOTWORD).
- * model_name - Name of the model to use, e.g. "en_us".
- * Returns:
- * 0 on success.
- * -EINVAL if client or node_id is invalid.
- * -ENOENT if the specified model is not found.
- */
-int cras_client_set_hotword_model(struct cras_client *client,
- cras_node_id_t node_id,
- const char *model_name);
-
-/*
- * Creates a hotword stream and waits for the hotword to trigger.
- *
- * Args:
- * client - The client to add the stream to (from cras_client_create).
- * user_data - Pointer that will be passed to the callback.
- * trigger_cb - Called when a hotword is triggered.
- * err_cb - Called when there is an error with the stream.
- * handle_out - On success will be filled with a cras_hotword_handle.
- * Returns:
- * 0 on success, negative error code on failure (from errno.h).
- */
-int cras_client_enable_hotword_callback(
- struct cras_client *client, void *user_data,
- cras_hotword_trigger_cb_t trigger_cb, cras_hotword_error_cb_t err_cb,
- struct cras_hotword_handle **handle_out);
-
-/*
- * Closes a hotword stream that was created by cras_client_wait_for_hotword.
- *
- * Args:
- * client - Client to remove the stream (returned from cras_client_create).
- * handle - cras_hotword_handle returned from cras_client_wait_for_hotword.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-int cras_client_disable_hotword_callback(struct cras_client *client,
- struct cras_hotword_handle *handle);
-
-/* Starts or stops the aec dump task on server side.
- * Args:
- * client - The client from cras_client_create.
- * stream_id - The id of the input stream running with aec effect.
- * start - True to start APM debugging, otherwise to stop it.
- * fd - File descriptor of the file to store aec dump result.
- */
-int cras_client_set_aec_dump(struct cras_client *client,
- cras_stream_id_t stream_id, int start, int fd);
-/*
- * Reloads the aec.ini config file on server side.
- */
-int cras_client_reload_aec_config(struct cras_client *client);
-
-/*
- * Returns if AEC is supported.
- */
-int cras_client_get_aec_supported(struct cras_client *client);
-
-/*
- * Returns the AEC group ID if available.
- */
-int cras_client_get_aec_group_id(struct cras_client *client);
-
-/*
- * Sets the flag to enable bluetooth wideband speech in server.
- */
-int cras_client_set_bt_wbs_enabled(struct cras_client *client, bool enabled);
-
-/* Set the context pointer for system state change callbacks.
- * Args:
- * client - The client from cras_client_create.
- * context - The context pointer passed to all callbacks.
- */
-void cras_client_set_state_change_callback_context(struct cras_client *client,
- void *context);
-
-/* Output volume change callback.
- *
- * Args:
- * context - Context pointer set with
- * cras_client_set_state_change_callback_context().
- * volume - The system output volume, ranging from 0 to 100.
- */
-typedef void (*cras_client_output_volume_changed_callback)(void *context,
- int32_t volume);
-
-/* Output mute change callback.
- *
- * Args:
- * context - Context pointer set with
- * cras_client_set_state_change_callback_context().
- * muted - Non-zero when the audio is muted, zero otherwise.
- * user_muted - Non-zero when the audio has been muted by the
- * user, zero otherwise.
- * mute_locked - Non-zero when the mute funcion is locked,
- * zero otherwise.
- */
-typedef void (*cras_client_output_mute_changed_callback)(void *context,
- int muted,
- int user_muted,
- int mute_locked);
-
-/* Capture gain change callback.
- *
- * Args:
- * context - Context pointer set with
- * cras_client_set_state_change_callback_context().
- * gain - The system capture gain, in centi-decibels.
- */
-typedef void (*cras_client_capture_gain_changed_callback)(void *context,
- int32_t gain);
-
-/* Capture mute change callback.
- *
- * Args:
- * context - Context pointer set with
- * cras_client_set_state_change_callback_context().
- * muted - Non-zero when the audio is muted, zero otherwise.
- * mute_locked - Non-zero when the mute funcion is locked,
- * zero otherwise.
- */
-typedef void (*cras_client_capture_mute_changed_callback)(void *context,
- int muted,
- int mute_locked);
-
-/* Nodes change callback.
- *
- * Args:
- * context - Context pointer set with
- * cras_client_set_state_change_callback_context().
- */
-typedef void (*cras_client_nodes_changed_callback)(void *context);
-
-/* Active node change callback.
- *
- * Args:
- * context - Context pointer set with
- * cras_client_set_state_change_callback_context().
- * direction - Indicates the direction of the selected node.
- * node_id - The ID of the selected node. Special device ID values
- * defined by CRAS_SPECIAL_DEVICE will be used when no other
- * device or node is selected or between selections.
- */
-typedef void (*cras_client_active_node_changed_callback)(
- void *context, enum CRAS_STREAM_DIRECTION direction,
- cras_node_id_t node_id);
-
-/* Output node volume change callback.
- *
- * Args:
- * context - Context pointer set with
- * cras_client_set_state_change_callback_context().
- * node_id - The ID of the output node.
- * volume - The volume for this node with range 0 to 100.
- */
-typedef void (*cras_client_output_node_volume_changed_callback)(
- void *context, cras_node_id_t node_id, int32_t volume);
-
-/* Node left right swapped change callback.
- *
- * Args:
- * context - Context pointer set with
- * cras_client_set_state_change_callback_context().
- * node_id - The ID of the node.
- * swapped - Non-zero if the node is left-right swapped, zero otherwise.
- */
-typedef void (*cras_client_node_left_right_swapped_changed_callback)(
- void *context, cras_node_id_t node_id, int swapped);
-
-/* Input node gain change callback.
- * Args:
- * context - Context pointer set with
- * cras_client_set_state_change_callback_context().
- * node_id - The ID of the input node.
- * gain - The gain for this node in centi-decibels.
- */
-typedef void (*cras_client_input_node_gain_changed_callback)(
- void *context, cras_node_id_t node_id, int32_t gain);
-
-/* Number of active streams change callback.
- *
- * Args:
- * context - Context pointer set with
- * cras_client_set_state_change_callback_context().
- * direction - Indicates the direction of the stream's node.
- * num_active_streams - The number of active streams.
- */
-typedef void (*cras_client_num_active_streams_changed_callback)(
- void *context, enum CRAS_STREAM_DIRECTION direction,
- uint32_t num_active_streams);
-
-/* Set system state information callbacks.
- * NOTE: These callbacks are executed from the client control thread.
- * Each state change callback is given the context pointer set with
- * cras_client_set_state_change_callback_context(). The context pointer is
- * NULL by default.
- * Args:
- * client - The client from cras_client_create.
- * cb - The callback, or NULL to disable the call-back.
- * Returns:
- * 0 for success or negative errno error code on error.
- */
-int cras_client_set_output_volume_changed_callback(
- struct cras_client *client,
- cras_client_output_volume_changed_callback cb);
-int cras_client_set_output_mute_changed_callback(
- struct cras_client *client,
- cras_client_output_mute_changed_callback cb);
-int cras_client_set_capture_gain_changed_callback(
- struct cras_client *client,
- cras_client_capture_gain_changed_callback cb);
-int cras_client_set_capture_mute_changed_callback(
- struct cras_client *client,
- cras_client_capture_mute_changed_callback cb);
-int cras_client_set_nodes_changed_callback(
- struct cras_client *client, cras_client_nodes_changed_callback cb);
-int cras_client_set_active_node_changed_callback(
- struct cras_client *client,
- cras_client_active_node_changed_callback cb);
-int cras_client_set_output_node_volume_changed_callback(
- struct cras_client *client,
- cras_client_output_node_volume_changed_callback cb);
-int cras_client_set_node_left_right_swapped_changed_callback(
- struct cras_client *client,
- cras_client_node_left_right_swapped_changed_callback cb);
-int cras_client_set_input_node_gain_changed_callback(
- struct cras_client *client,
- cras_client_input_node_gain_changed_callback cb);
-int cras_client_set_num_active_streams_changed_callback(
- struct cras_client *client,
- cras_client_num_active_streams_changed_callback cb);
-
-/*
- * The functions below prefixed with libcras wrap the original CRAS library
- * They provide an interface that maps the pointers to the functions above.
- * Please add a new function instead of modifying the existing function.
- * Here are some rules about how to add a new function:
- * 1. Increase the CRAS_API_VERSION by 1.
- * 2. Write a new function in cras_client.c.
- * 3. Append the corresponding pointer to the structure. Remeber DO NOT change
- * the order of functions in the structs.
- * 4. Assign the pointer to the new function in cras_client.c.
- * 5. Create the inline function in cras_client.h, which is used by clients.
- * Remember to add DISABLE_CFI_ICALL on the inline function.
- * 6. Add CHECK_VERSION in the inline function. If the api_version is smaller
- * than the supported version, this inline function will return -ENOSYS.
- */
-
-#define CRAS_API_VERSION 1
-#define CHECK_VERSION(object, version) \
- if (object->api_version < version) { \
- return -ENOSYS; \
- }
-
-/*
- * The inline functions use the indirect function call. Therefore, they are
- * incompatible with CFI-icall.
- */
-#define DISABLE_CFI_ICALL __attribute__((no_sanitize("cfi-icall")))
-
-struct libcras_node_info {
- int api_version;
- struct cras_node_info *node_;
- int (*get_id)(struct cras_node_info *node, uint64_t *id);
- int (*get_dev_idx)(struct cras_node_info *node, uint32_t *dev_idx);
- int (*get_node_idx)(struct cras_node_info *node, uint32_t *node_idx);
- int (*get_max_supported_channels)(struct cras_node_info *node,
- uint32_t *max_supported_channels);
- int (*is_plugged)(struct cras_node_info *node, bool *plugged);
- int (*is_active)(struct cras_node_info *node, bool *active);
- int (*get_type)(struct cras_node_info *node, char **name);
- int (*get_node_name)(struct cras_node_info *node, char **name);
- int (*get_dev_name)(struct cras_node_info *node, char **name);
-};
-
-struct libcras_client {
- int api_version;
- struct cras_client *client_;
- int (*connect)(struct cras_client *client);
- int (*connect_timeout)(struct cras_client *client,
- unsigned int timeout_ms);
- int (*connected_wait)(struct cras_client *client);
- int (*run_thread)(struct cras_client *client);
- int (*stop)(struct cras_client *client);
- int (*add_pinned_stream)(struct cras_client *client, uint32_t dev_idx,
- cras_stream_id_t *stream_id_out,
- struct cras_stream_params *config);
- int (*rm_stream)(struct cras_client *client,
- cras_stream_id_t stream_id);
- int (*set_stream_volume)(struct cras_client *client,
- cras_stream_id_t stream_id,
- float volume_scaler);
- int (*get_nodes)(struct cras_client *client,
- enum CRAS_STREAM_DIRECTION direction,
- struct libcras_node_info ***nodes, size_t *num);
- int (*get_default_output_buffer_size)(struct cras_client *client,
- int *size);
- int (*get_aec_group_id)(struct cras_client *client, int *id);
- int (*get_aec_supported)(struct cras_client *client, int *supported);
- int (*get_system_muted)(struct cras_client *client, int *muted);
- int (*set_system_mute)(struct cras_client *client, int mute);
- int (*get_loopback_dev_idx)(struct cras_client *client, int *idx);
-};
-
-struct cras_stream_cb_data;
-struct libcras_stream_cb_data {
- int api_version;
- struct cras_stream_cb_data *data_;
- int (*get_stream_id)(struct cras_stream_cb_data *data,
- cras_stream_id_t *id);
- int (*get_buf)(struct cras_stream_cb_data *data, uint8_t **buf);
- int (*get_frames)(struct cras_stream_cb_data *data,
- unsigned int *frames);
- int (*get_latency)(struct cras_stream_cb_data *data,
- struct timespec *latency);
- int (*get_user_arg)(struct cras_stream_cb_data *data, void **user_arg);
-};
-typedef int (*libcras_stream_cb_t)(struct libcras_stream_cb_data *data);
-
-struct libcras_stream_params {
- int api_version;
- struct cras_stream_params *params_;
- int (*set)(struct cras_stream_params *params,
- enum CRAS_STREAM_DIRECTION direction, size_t buffer_frames,
- size_t cb_threshold, enum CRAS_STREAM_TYPE stream_type,
- enum CRAS_CLIENT_TYPE client_type, uint32_t flags,
- void *user_data, libcras_stream_cb_t stream_cb,
- cras_error_cb_t err_cb, size_t rate, snd_pcm_format_t format,
- size_t num_channels);
- int (*set_channel_layout)(struct cras_stream_params *params, int length,
- const int8_t *layout);
- void (*enable_aec)(struct cras_stream_params *params);
-};
-
-/*
- * Creates a new client.
- * Returns:
- * If success, return a valid libcras_client pointer. Otherwise, return
- * NULL.
- */
-struct libcras_client *libcras_client_create();
-
-/*
- * Destroys a client.
- * Args:
- * client - pointer returned from "libcras_client_create".
- */
-void libcras_client_destroy(struct libcras_client *client);
-
-/*
- * Connects a client to the running server.
- * Waits forever (until interrupted or connected).
- * Args:
- * client - pointer returned from "libcras_client_create".
- * Returns:
- * 0 on success, or a negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int libcras_client_connect(struct libcras_client *client)
-{
- return client->connect(client->client_);
-}
-
-/*
- * Connects a client to the running server, retries until timeout.
- * Args:
- * client - pointer returned from "libcras_client_create".
- * timeout_ms - timeout in milliseconds or negative to wait forever.
- * Returns:
- * 0 on success, or a negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int libcras_client_connect_timeout(struct libcras_client *client,
- unsigned int timeout_ms)
-{
- return client->connect_timeout(client->client_, timeout_ms);
-}
-
-/*
- * Wait up to 1 second for the client thread to complete the server connection.
- *
- * After libcras_client_run_thread() is executed, this function can be
- * used to ensure that the connection has been established with the server and
- * ensure that any information about the server is up to date. If
- * libcras_client_run_thread() has not yet been executed, or
- * libcras_client_stop() was executed and thread isn't running, then this
- * function returns -EINVAL.
- *
- * Args:
- * client - pointer returned from "libcras_client_create".
- * Returns:
- * 0 on success, or a negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int libcras_client_connected_wait(struct libcras_client *client)
-{
- return client->connected_wait(client->client_);
-}
-
-/*
- * Begins running the client control thread.
- *
- * Required for stream operations and other operations noted below.
- *
- * Args:
- * client - pointer returned from "libcras_client_create".
- * Returns:
- * 0 on success, or a negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int libcras_client_run_thread(struct libcras_client *client)
-{
- return client->run_thread(client->client_);
-}
-
-/*
- * Stops running a client.
- * This function is executed automatically by cras_client_destroy().
- * Args:
- * client - pointer returned from "libcras_client_create".
- * Returns:
- * 0 on success or if the thread was already stopped, -EINVAL if the client
- * isn't valid.
- */
-DISABLE_CFI_ICALL
-inline int libcras_client_stop(struct libcras_client *client)
-{
- return client->stop(client->client_);
-}
-
-/*
- * Creates a pinned stream and return the stream id or < 0 on error.
- *
- * Requires execution of libcras_client_run_thread(), and an active
- * connection to the audio server.
- *
- * Args:
- * client - pointer returned from "libcras_client_create".
- * dev_idx - Index of the device to attach the newly created stream.
- * stream_id_out - On success will be filled with the new stream id.
- * Guaranteed to be set before any callbacks are made.
- * params - The pointer specifying the parameters for the stream.
- * (returned from libcras_stream_params_create)
- * Returns:
- * 0 on success, negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int libcras_client_add_pinned_stream(
- struct libcras_client *client, uint32_t dev_idx,
- cras_stream_id_t *stream_id_out, struct libcras_stream_params *params)
-{
- return client->add_pinned_stream(client->client_, dev_idx,
- stream_id_out, params->params_);
-}
-
-/*
- * Removes a currently playing/capturing stream.
- *
- * Requires execution of libcras_client_run_thread().
- *
- * Args:
- * client - pointer returned from "libcras_client_create".
- * stream_id - ID returned from libcras_client_add_stream to identify
- * the stream to remove.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int libcras_client_rm_stream(struct libcras_client *client,
- cras_stream_id_t stream_id)
-{
- return client->rm_stream(client->client_, stream_id);
-}
-
-/*
- * Sets the volume scaling factor for the given stream.
- *
- * Requires execution of cras_client_run_thread().
- *
- * Args:
- * client - pointer returned from "libcras_client_create".
- * stream_id - ID returned from libcras_client_add_stream.
- * volume_scaler - 0.0-1.0 the new value to scale this stream by.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int libcras_client_set_stream_volume(struct libcras_client *client,
- cras_stream_id_t stream_id,
- float volume_scaler)
-{
- return client->set_stream_volume(client->client_, stream_id,
- volume_scaler);
-}
-
-/*
- * Gets the current list of audio nodes.
- *
- * Args:
- * client - Pointer returned from "libcras_client_create".
- * direction - Input or output.
- * nodes - Array that will be filled with libcras_node_info pointers.
- * num - Pointer to store the size of the array.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- * Remember to call libcras_node_info_array_destroy to free the array.
- */
-DISABLE_CFI_ICALL
-inline int libcras_client_get_nodes(struct libcras_client *client,
- enum CRAS_STREAM_DIRECTION direction,
- struct libcras_node_info ***nodes,
- size_t *num)
-{
- return client->get_nodes(client->client_, direction, nodes, num);
-}
-
-/*
- * Gets the default output buffer size.
- * Args:
- * client - Pointer returned from "libcras_client_create".
- * size - The pointer to save the result.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int
-libcras_client_get_default_output_buffer_size(struct libcras_client *client,
- int *size)
-{
- return client->get_default_output_buffer_size(client->client_, size);
-}
-
-/*
- * Gets the AEC group ID.
- * Args:
- * client - Pointer returned from "libcras_client_create".
- * id - The pointer to save the result.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int libcras_client_get_aec_group_id(struct libcras_client *client,
- int *id)
-{
- return client->get_aec_group_id(client->client_, id);
-}
-
-/*
- * Gets whether AEC is supported.
- * Args:
- * client - Pointer returned from "libcras_client_create".
- * supported - The pointer to save the result.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int libcras_client_get_aec_supported(struct libcras_client *client,
- int *supported)
-{
- return client->get_aec_supported(client->client_, supported);
-}
-
-/*
- * Gets whether the system is muted.
- * Args:
- * client - Pointer returned from "libcras_client_create".
- * muted - The pointer to save the result.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int libcras_client_get_system_muted(struct libcras_client *client,
- int *muted)
-{
- return client->get_aec_group_id(client->client_, muted);
-}
-
-/*
- * Mutes or unmutes the system.
- * Args:
- * client - Pointer returned from "libcras_client_create".
- * mute - 1 is to mute and 0 is to unmute.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int libcras_client_set_system_mute(struct libcras_client *client,
- int mute)
-{
- return client->set_system_mute(client->client_, mute);
-}
-
-/*
- * Gets the index of the loopback device.
- * Args:
- * client - Pointer returned from "libcras_client_create".
- * idx - The pointer to save the result.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int libcras_client_get_loopback_dev_idx(struct libcras_client *client,
- int *idx)
-{
- return client->get_loopback_dev_idx(client->client_, idx);
-}
-
-/*
- * Creates a new struct to save stream params.
- * Returns:
- * If success, return a valid libcras_stream_params pointer. Otherwise,
- * return NULL.
- */
-struct libcras_stream_params *libcras_stream_params_create();
-
-/*
- * Destroys a stream params instance.
- * Args:
- * params - The pointer returned from libcras_stream_params_create.
- */
-void libcras_stream_params_destroy(struct libcras_stream_params *params);
-
-/*
- * Setup stream configuration parameters.
- * Args:
- * params - The pointer returned from libcras_stream_params_create.
- * direction - Playback(CRAS_STREAM_OUTPUT) or capture(CRAS_STREAM_INPUT).
- * buffer_frames - total number of audio frames to buffer (dictates latency).
- * cb_threshold - For playback, call back for more data when the buffer
- * reaches this level. For capture, this is ignored (Audio callback will
- * be called when buffer_frames have been captured).
- * stream_type - Media or talk (currently only support "default").
- * client_type - The client type, like Chrome or CrOSVM.
- * flags - Currently only used for CRAS_INPUT_STREAM_FLAG.
- * user_data - Pointer that will be passed to the callback.
- * stream_cb - The audio callback. Called when audio is needed(playback) or
- * ready(capture).
- * err_cb - Called when there is an error with the stream.
- * rate - The sample rate of the audio stream.
- * format - The format of the audio stream.
- * num_channels - The number of channels of the audio stream.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int libcras_stream_params_set(
- struct libcras_stream_params *params,
- enum CRAS_STREAM_DIRECTION direction, size_t buffer_frames,
- size_t cb_threshold, enum CRAS_STREAM_TYPE stream_type,
- enum CRAS_CLIENT_TYPE client_type, uint32_t flags, void *user_data,
- libcras_stream_cb_t stream_cb, cras_error_cb_t err_cb, size_t rate,
- snd_pcm_format_t format, size_t num_channels)
-{
- return params->set(params->params_, direction, buffer_frames,
- cb_threshold, stream_type, client_type, flags,
- user_data, stream_cb, err_cb, rate, format,
- num_channels);
-}
-
-/*
- * Sets channel layout on given stream parameter.
- * Args:
- * params - The pointer returned from libcras_stream_params_create.
- * length - The length of the array.
- * layout - An integer array representing the position of each channel in
- * enum CRAS_CHANNEL.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int
-libcras_stream_params_set_channel_layout(struct libcras_stream_params *params,
- int length, const int8_t *layout)
-{
- return params->set_channel_layout(params->params_, length, layout);
-}
-
-/*
- * Enables AEC on given stream parameter.
- * Args:
- * params - The pointer returned from libcras_stream_params_create.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int
-libcras_stream_params_enable_aec(struct libcras_stream_params *params)
-{
- params->enable_aec(params->params_);
- return 0;
-}
-
-/*
- * Gets stream id from the callback data.
- * Args:
- * data - The pointer passed to the callback function.
- * id - The pointer to save the stream id.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int
-libcras_stream_cb_data_get_stream_id(struct libcras_stream_cb_data *data,
- cras_stream_id_t *id)
-{
- return data->get_stream_id(data->data_, id);
-}
-
-/*
- * Gets stream buf from the callback data.
- * Args:
- * data - The pointer passed to the callback function.
- * buf - The pointer to save the stream buffer.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int libcras_stream_cb_data_get_buf(struct libcras_stream_cb_data *data,
- uint8_t **buf)
-{
- return data->get_buf(data->data_, buf);
-}
-
-/*
- * Gets how many frames to read or play from the callback data.
- * Args:
- * data - The pointer passed to the callback function.
- * frames - The pointer to save the number of frames.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int
-libcras_stream_cb_data_get_frames(struct libcras_stream_cb_data *data,
- unsigned int *frames)
-{
- return data->get_frames(data->data_, frames);
-}
-
-/*
- * Gets the latency from the callback data.
- * Args:
- * data - The pointer passed to the callback function.
- * frames - The timespec pointer to save the latency.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int
-libcras_stream_cb_data_get_latency(struct libcras_stream_cb_data *data,
- struct timespec *latency)
-{
- return data->get_latency(data->data_, latency);
-}
-
-/*
- * Gets the user data from the callback data.
- * Args:
- * data - The pointer passed to the callback function.
- * frames - The pointer to save the user data.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int
-libcras_stream_cb_data_get_usr_arg(struct libcras_stream_cb_data *data,
- void **user_arg)
-{
- return data->get_user_arg(data->data_, user_arg);
-}
-
-/*
- * Destroys a node info instance.
- * Args:
- * node - The libcras_node_info pointer to destroy.
- */
-void libcras_node_info_destroy(struct libcras_node_info *node);
-
-/*
- * Destroys a node info array.
- * Args:
- * nodes - The libcras_node_info pointer array to destroy.
- * num - The size of the array.
- */
-void libcras_node_info_array_destroy(struct libcras_node_info **nodes,
- size_t num);
-
-/*
- * Gets ID from the node info pointer.
- * Args:
- * node - The node info pointer. (Returned from libcras_client_get_nodes)
- * id - The pointer to save ID.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int libcras_node_info_get_id(struct libcras_node_info *node,
- uint64_t *id)
-{
- return node->get_id(node->node_, id);
-}
-
-/*
- * Gets device index from the node info pointer.
- * Args:
- * node - The node info pointer. (Returned from libcras_client_get_nodes)
- * dev_idx - The pointer to the device index.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int libcras_node_info_get_dev_idx(struct libcras_node_info *node,
- uint32_t *dev_idx)
-{
- return node->get_dev_idx(node->node_, dev_idx);
-}
-
-/*
- * Gets node index from the node info pointer.
- * Args:
- * node - The node info pointer. (Returned from libcras_client_get_nodes)
- * node_idx - The pointer to save the node index.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int libcras_node_info_get_node_idx(struct libcras_node_info *node,
- uint32_t *node_idx)
-{
- return node->get_node_idx(node->node_, node_idx);
-}
-
-/*
- * Gets the max supported channels from the node info pointer.
- * Args:
- * node - The node info pointer. (Returned from libcras_client_get_nodes)
- * max_supported_channels - The pointer to save the result.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int
-libcras_node_info_get_max_supported_channels(struct libcras_node_info *node,
- uint32_t *max_supported_channels)
-{
- return node->get_max_supported_channels(node->node_,
- max_supported_channels);
-}
-
-/*
- * Gets whether the node is plugged from the node info pointer.
- * Args:
- * node - The node info pointer. (Returned from libcras_client_get_nodes)
- * plugged - The pointer to save the result.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int libcras_node_info_is_plugged(struct libcras_node_info *node,
- bool *plugged)
-{
- return node->is_plugged(node->node_, plugged);
-}
-
-/*
- * Gets whether the node is active from the node info pointer.
- * Args:
- * node - The node info pointer. (Returned from libcras_client_get_nodes)
- * active - The pointer to save the result.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int libcras_node_info_is_active(struct libcras_node_info *node,
- bool *active)
-{
- return node->is_active(node->node_, active);
-}
-
-/*
- * Gets device type from the node info pointer.
- * Args:
- * node - The node info pointer. (Returned from libcras_client_get_nodes)
- * type - The pointer to save the device type.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int libcras_node_info_get_type(struct libcras_node_info *node,
- char **type)
-{
- return node->get_type(node->node_, type);
-}
-
-/*
- * Gets device name from the node info pointer.
- * Args:
- * node - The node info pointer. (Returned from libcras_client_get_nodes)
- * name - The pointer to save the device name.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int libcras_node_info_get_node_name(struct libcras_node_info *node,
- char **name)
-{
- return node->get_node_name(node->node_, name);
-}
-
-/*
- * Gets node name from the node info pointer.
- * Args:
- * node - The node info pointer. (Returned from libcras_client_get_nodes)
- * name - The pointer to save the node name.
- * Returns:
- * 0 on success negative error code on failure (from errno.h).
- */
-DISABLE_CFI_ICALL
-inline int libcras_node_info_get_dev_name(struct libcras_node_info *node,
- char **name)
-{
- return node->get_dev_name(node->node_, name);
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* CRAS_CLIENT_H_ */
diff --git a/cras/src/libcras/cras_helpers.c b/cras/src/libcras/cras_helpers.c
deleted file mode 100644
index a2120eae..00000000
--- a/cras/src/libcras/cras_helpers.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/* Copyright 2015 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 <errno.h>
-#include <stdint.h>
-#include <sys/param.h>
-
-#include "cras_client.h"
-#include "cras_util.h"
-
-struct buffer_data {
- const uint8_t *buffer;
- unsigned int offset;
- unsigned int frame_bytes;
- unsigned int len;
-};
-
-static int
-play_buffer_callback(struct cras_client *client, cras_stream_id_t stream_id,
- uint8_t *captured_samples, uint8_t *playback_samples,
- unsigned int frames, const struct timespec *captured_time,
- const struct timespec *playback_time, void *user_arg)
-{
- struct buffer_data *data = (struct buffer_data *)user_arg;
- int to_copy = data->len - data->offset;
-
- if (to_copy <= 0) {
- free(user_arg);
- return EOF;
- }
-
- to_copy = MIN(to_copy, frames * data->frame_bytes);
-
- memcpy(playback_samples, data->buffer + data->offset, to_copy);
-
- data->offset += to_copy;
-
- return to_copy / data->frame_bytes;
-}
-
-static int play_buffer_error(struct cras_client *client,
- cras_stream_id_t stream_id, int error,
- void *user_arg)
-{
- free(user_arg);
- return 0;
-}
-
-int cras_helper_create_connect_async(struct cras_client **client,
- cras_connection_status_cb_t connection_cb,
- void *user_arg)
-{
- int rc;
-
- rc = cras_client_create(client);
- if (rc < 0)
- return rc;
-
- cras_client_set_connection_status_cb(*client, connection_cb, user_arg);
-
- rc = cras_client_run_thread(*client);
- if (rc < 0)
- goto client_start_error;
-
- rc = cras_client_connect_async(*client);
- if (rc < 0)
- goto client_start_error;
-
- return 0;
-
-client_start_error:
- cras_client_destroy(*client);
- return rc;
-}
-
-int cras_helper_create_connect(struct cras_client **client)
-{
- int rc;
-
- rc = cras_client_create(client);
- if (rc < 0)
- return rc;
-
- rc = cras_client_connect(*client);
- if (rc < 0)
- goto client_start_error;
-
- rc = cras_client_run_thread(*client);
- if (rc < 0)
- goto client_start_error;
-
- rc = cras_client_connected_wait(*client);
- if (rc < 0)
- goto client_start_error;
-
- return 0;
-
-client_start_error:
- cras_client_destroy(*client);
- return rc;
-}
-
-int cras_helper_add_stream_simple(
- struct cras_client *client, enum CRAS_STREAM_DIRECTION direction,
- void *user_data, cras_unified_cb_t unified_cb, cras_error_cb_t err_cb,
- snd_pcm_format_t format, unsigned int frame_rate,
- unsigned int num_channels, int dev_idx, cras_stream_id_t *stream_id_out)
-{
- struct cras_audio_format *aud_format;
- struct cras_stream_params *params;
- int rc;
-
- aud_format = cras_audio_format_create(format, frame_rate, num_channels);
- if (!aud_format)
- return -ENOMEM;
-
- params = cras_client_unified_params_create(CRAS_STREAM_OUTPUT, 2048,
- CRAS_STREAM_TYPE_DEFAULT, 0,
- user_data, unified_cb,
- err_cb, aud_format);
- if (!params) {
- rc = -ENOMEM;
- goto done_add_stream;
- }
-
- if (dev_idx < 0)
- dev_idx = NO_DEVICE;
- rc = cras_client_add_pinned_stream(client, dev_idx, stream_id_out,
- params);
-
-done_add_stream:
- cras_audio_format_destroy(aud_format);
- cras_client_stream_params_destroy(params);
- return rc;
-}
-
-int cras_helper_play_buffer(struct cras_client *client, const void *buffer,
- unsigned int frames, snd_pcm_format_t format,
- unsigned int frame_rate, unsigned int num_channels,
- int dev_idx)
-{
- struct buffer_data *data;
- cras_stream_id_t stream_id;
-
- data = malloc(sizeof(*data));
-
- data->buffer = buffer;
- data->frame_bytes = num_channels * PCM_FORMAT_WIDTH(format) / 8;
- data->offset = 0;
- data->len = frames * data->frame_bytes;
-
- return cras_helper_add_stream_simple(client, CRAS_STREAM_OUTPUT, data,
- play_buffer_callback,
- play_buffer_error, format,
- frame_rate, num_channels, dev_idx,
- &stream_id);
-}
diff --git a/cras/src/libcras/cras_helpers.h b/cras/src/libcras/cras_helpers.h
deleted file mode 100644
index 604b2660..00000000
--- a/cras/src/libcras/cras_helpers.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* Copyright 2015 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.
- */
-#ifndef _CRAS_HELPERS_H
-#define _CRAS_HELPERS_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Creates and connects a client to the running server asynchronously.
- *
- * When the connection has been established the connection_cb is executed
- * with the appropriate state. See cras_connection_status_cb_t for more
- * information.
- *
- * Args:
- * client - Filled with a pointer to the new client.
- * connection_cb - The connection status callback function.
- * user_arg - Argument passed to the connection status callback.
- * Returns:
- * 0 on success, or a negative error code on failure (from errno.h).
- */
-int cras_helper_create_connect_async(struct cras_client **client,
- cras_connection_status_cb_t connection_cb,
- void *user_arg);
-
-/* Creates and connects a client to the running server.
- *
- * Waits forever (or interrupt) for the server to be available.
- *
- * Args:
- * client - Filled with a pointer to the new client.
- * Returns:
- * 0 on success, or a negative error code on failure (from errno.h).
- */
-int cras_helper_create_connect(struct cras_client **client);
-
-/* Adds a stream with the given parameters, no flags and a buffer size of 2048
- * Note that the unified_cb parameter is being phased out.
- * TODO(crbug.com/972928): convert this from unified_cb.
- * Args:
- * client - The client to add the stream to (from cras_client_create).
- * direction - playback(CRAS_STREAM_OUTPUT) or capture(CRAS_STREAM_INPUT) or
- * loopback(CRAS_STREAM_POST_MIX_PRE_DSP).
- * user_data - Pointer that will be passed to the callback.
- * unified_cb - Called to request audio data or to notify the client when
- * captured audio is available. Though this is a unified_cb,
- * only one direction will be used for a stream, depending
- * on the 'direction' parameter.
- * err_cb - Called when there is an error with the stream.
- * format - The type of the samples, ex. S16_LE.
- * frame_rate - Sample rate.
- * num_channels - Number of channels in the stream, should be 1 or 2 when
- * using this API, for > 2 channel streams see cras_client.h.
- * dev_idx - Set this to a negative number to play to the default device, if
- * positive it is the index of the device to pin the stream to.
- * stream_id_out - On success will be filled with the new stream id.
- * Guaranteed to be set before any callbacks are made.
- * Returns:
- * 0 on success, negative error code on failure (from errno.h).
- */
-int cras_helper_add_stream_simple(struct cras_client *client,
- enum CRAS_STREAM_DIRECTION direction,
- void *user_data, cras_unified_cb_t unified_cb,
- cras_error_cb_t err_cb,
- snd_pcm_format_t format,
- unsigned int frame_rate,
- unsigned int num_channels, int dev_idx,
- cras_stream_id_t *stream_id_out);
-
-/* Plays the given buffer at a default latency.
- * Args:
- * client - The client to add the stream to (from cras_client_create).
- * buffer - The audio samples.
- * num_frames - The size of the buffer in number of samples.
- * format - The type of the samples, ex. S16_LE.
- * frame_rate - Sample rate.
- * num_channels - Number of channels in the stream.
- * dev_idx - Set this to a negative number to play to the default device, if
- * positive it is the index of the device to pin the stream to.
- * Returns:
- * 0 on success, negative error code on failure (from errno.h).
- */
-int cras_helper_play_buffer(struct cras_client *client, const void *buffer,
- unsigned int num_frames, snd_pcm_format_t format,
- unsigned int frame_rate, unsigned int num_channels,
- int dev_idx);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* _CRAS_HELPERS_H */