1 /* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6 /*
7 * Basic playback flow:
8 * cras_client_create - Create new structure and set to defaults.
9 * cras_client_connect - Connect client to server - sets up server_fd to
10 * communicate with the audio server. After the client connects, the server
11 * will send back a message containing the client id.
12 * cras_client_add_stream - Add a playback or capture stream. Creates a
13 * client_stream struct and send a file descriptor to server. That file
14 * descriptor and aud_fd are a pair created from socketpair().
15 * client_connected - The server will send a connected message to indicate that
16 * the client should start receving audio events from aud_fd. This message
17 * also specifies the shared memory region to use to share audio samples.
18 * This region will be shmat'd.
19 * running - Once the connections are established, the client will listen for
20 * requests on aud_fd and fill the shm region with the requested number of
21 * samples. This happens in the aud_cb specified in the stream parameters.
22 */
23
24 #ifndef _GNU_SOURCE
25 #define _GNU_SOURCE /* For ppoll() */
26 #endif
27
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <limits.h>
31 #include <poll.h>
32 #include <pthread.h>
33 #include <stdbool.h>
34 #include <stdint.h>
35 #include <sys/eventfd.h>
36 #include <sys/ipc.h>
37 #include <sys/mman.h>
38 #include <sys/param.h>
39 #include <sys/signal.h>
40 #include <sys/socket.h>
41 #include <sys/timerfd.h>
42 #include <sys/types.h>
43 #include <sys/un.h>
44 #include <syslog.h>
45 #include <unistd.h>
46
47 #include "cras_client.h"
48 #include "cras_config.h"
49 #include "cras_file_wait.h"
50 #include "cras_messages.h"
51 #include "cras_observer_ops.h"
52 #include "cras_shm.h"
53 #include "cras_types.h"
54 #include "cras_util.h"
55 #include "utlist.h"
56
57 static const size_t MAX_CMD_MSG_LEN = 256;
58 static const size_t SERVER_SHUTDOWN_TIMEOUT_US = 500000;
59 static const size_t SERVER_CONNECT_TIMEOUT_MS = 1000;
60
61 /* Commands sent from the user to the running client. */
62 enum {
63 CLIENT_STOP,
64 CLIENT_ADD_STREAM,
65 CLIENT_REMOVE_STREAM,
66 CLIENT_SET_STREAM_VOLUME_SCALER,
67 CLIENT_SERVER_CONNECT,
68 CLIENT_SERVER_CONNECT_ASYNC,
69 };
70
71 struct command_msg {
72 unsigned len;
73 unsigned msg_id;
74 cras_stream_id_t stream_id;
75 };
76
77 struct set_stream_volume_command_message {
78 struct command_msg header;
79 float volume_scaler;
80 };
81
82 /* Adds a stream to the client.
83 * stream - The stream to add.
84 * stream_id_out - Filled with the stream id of the new stream.
85 * dev_idx - Index of the device to attach the newly created stream.
86 * NO_DEVICE means not to pin the stream to a device.
87 */
88 struct add_stream_command_message {
89 struct command_msg header;
90 struct client_stream *stream;
91 cras_stream_id_t *stream_id_out;
92 uint32_t dev_idx;
93 };
94
95 /* Commands send from a running stream to the client. */
96 enum {
97 CLIENT_STREAM_EOF,
98 };
99
100 struct stream_msg {
101 unsigned msg_id;
102 cras_stream_id_t stream_id;
103 };
104
105 enum CRAS_THREAD_STATE {
106 CRAS_THREAD_STOP, /* Isn't (shouldn't be) running. */
107 CRAS_THREAD_WARMUP, /* Is started, but not fully functional: waiting
108 * for resources to be ready for example. */
109 CRAS_THREAD_RUNNING, /* Is running and fully functional. */
110 };
111
112 /* Manage information for a thread. */
113 struct thread_state {
114 pthread_t tid;
115 enum CRAS_THREAD_STATE state;
116 };
117
118 /* Parameters used when setting up a capture or playback stream. See comment
119 * above cras_client_create_stream_params in the header for descriptions. */
120 struct cras_stream_params {
121 enum CRAS_STREAM_DIRECTION direction;
122 size_t buffer_frames;
123 size_t cb_threshold;
124 enum CRAS_STREAM_TYPE stream_type;
125 uint32_t flags;
126 void *user_data;
127 cras_playback_cb_t aud_cb;
128 cras_unified_cb_t unified_cb;
129 cras_error_cb_t err_cb;
130 struct cras_audio_format format;
131 };
132
133 /* Represents an attached audio stream.
134 * id - Unique stream identifier.
135 * aud_fd - After server connects audio messages come in here.
136 * direction - playback, capture, both, or loopback (see CRAS_STREAM_DIRECTION).
137 * flags - Currently not used.
138 * volume_scaler - Amount to scale the stream by, 0.0 to 1.0.
139 * tid - Thread id of the audio thread spawned for this stream.
140 * running - Audio thread runs while this is non-zero.
141 * wake_fds - Pipe to wake the audio thread.
142 * client - The client this stream is attached to.
143 * config - Audio stream configuration.
144 * capture_shm - Shared memory used to exchange audio samples with the server.
145 * play_shm - Shared memory used to exchange audio samples with the server.
146 * prev, next - Form a linked list of streams attached to a client.
147 */
148 struct client_stream {
149 cras_stream_id_t id;
150 int aud_fd; /* audio messages from server come in here. */
151 enum CRAS_STREAM_DIRECTION direction;
152 uint32_t flags;
153 float volume_scaler;
154 struct thread_state thread;
155 int wake_fds[2]; /* Pipe to wake the thread */
156 struct cras_client *client;
157 struct cras_stream_params *config;
158 struct cras_audio_shm capture_shm;
159 int capture_shm_size;
160 struct cras_audio_shm play_shm;
161 int play_shm_size;
162 struct client_stream *prev, *next;
163 };
164
165 /* State of the socket. */
166 typedef enum cras_socket_state {
167 CRAS_SOCKET_STATE_DISCONNECTED,
168 /* Not connected. Also used to cleanup the current connection
169 * before restarting the connection attempt. */
170 CRAS_SOCKET_STATE_WAIT_FOR_SOCKET,
171 /* Waiting for the socket file to exist. Socket file existence
172 * is monitored using cras_file_wait. */
173 CRAS_SOCKET_STATE_WAIT_FOR_WRITABLE,
174 /* Waiting for the socket to have something at the other end. */
175 CRAS_SOCKET_STATE_FIRST_MESSAGE,
176 /* Waiting for the first messages from the server and set our
177 * client ID. */
178 CRAS_SOCKET_STATE_CONNECTED,
179 /* The socket is connected and working. */
180 CRAS_SOCKET_STATE_ERROR_DELAY,
181 /* There was an error during one of the above states. Sleep for
182 * a bit before continuing. If this state could not be initiated
183 * then we move to the DISCONNECTED state and notify via the
184 * connection callback. */
185 } cras_socket_state_t;
186
187 /* Represents a client used to communicate with the audio server.
188 * id - Unique identifier for this client, negative until connected.
189 * server_fd - Incoming messages from server.
190 * server_fd_state - State of the server's socket.
191 * server_event_fd - Eventfd to wait on until a connection is established.
192 * stream_fds - Pipe for attached streams.
193 * command_fds - Pipe for user commands to thread.
194 * command_reply_fds - Pipe for acking/nacking command messages from thread.
195 * sock_file - Server communication socket file.
196 * sock_file_wait - Structure used to monitor existence of the socket file.
197 * sock_file_exists - Set to true when the socket file exists.
198 * running - The client thread will run while this is non zero.
199 * next_stream_id - ID to give the next stream.
200 * stream_start_cond - Condition used during stream startup.
201 * stream_start_lock - Lock used during stream startup.
202 * tid - Thread ID of the client thread started by "cras_client_run_thread".
203 * last_command_result - Passes back the result of the last user command.
204 * streams - Linked list of streams attached to this client.
205 * server_state - RO shared memory region holding server state.
206 * debug_info_callback - Function to call when debug info is received.
207 * get_hotword_models_cb_t - Function to call when hotword models info is ready.
208 * server_err_cb - Function to call when failed to read messages from server.
209 * server_err_user_arg - User argument for server_err_cb.
210 * server_connection_cb - Function to called when a connection state changes.
211 * server_connection_user_arg - User argument for server_connection_cb.
212 * thread_priority_cb - Function to call for setting audio thread priority.
213 * observer_ops - Functions to call when system state changes.
214 * observer_context - Context passed to client in state change callbacks.
215 */
216 struct cras_client {
217 int id;
218 int server_fd;
219 cras_socket_state_t server_fd_state;
220 int server_event_fd;
221 int stream_fds[2];
222 int command_fds[2];
223 int command_reply_fds[2];
224 const char *sock_file;
225 struct cras_file_wait *sock_file_wait;
226 bool sock_file_exists;
227 struct thread_state thread;
228 cras_stream_id_t next_stream_id;
229 pthread_cond_t stream_start_cond;
230 pthread_mutex_t stream_start_lock;
231 int last_command_result;
232 struct client_stream *streams;
233 const struct cras_server_state *server_state;
234 void (*debug_info_callback)(struct cras_client *);
235 get_hotword_models_cb_t get_hotword_models_cb;
236 cras_server_error_cb_t server_err_cb;
237 cras_connection_status_cb_t server_connection_cb;
238 void *server_connection_user_arg;
239 cras_thread_priority_cb_t thread_priority_cb;
240 struct cras_observer_ops observer_ops;
241 void *observer_context;
242 };
243
244 /*
245 * Holds the client pointer plus internal book keeping.
246 *
247 * client - The client
248 * server_state_rwlock - lock to make the client's server_state thread-safe.
249 */
250 struct client_int {
251 struct cras_client client;
252 pthread_rwlock_t server_state_rwlock;
253 };
254
255 #define to_client_int(cptr) \
256 ((struct client_int *)((char *)cptr - offsetof(struct client_int, client)))
257
258 /*
259 * Local Helpers
260 */
261
262 static int client_thread_rm_stream(struct cras_client *client,
263 cras_stream_id_t stream_id);
264 static int handle_message_from_server(struct cras_client *client);
265 static int reregister_notifications(struct cras_client *client);
266
267 /*
268 * Unlock the server_state_rwlock if lock_rc is 0.
269 *
270 * Args:
271 * client - The CRAS client pointer.
272 * lock_rc - The result of server_state_rdlock or
273 * server_state_wrlock.
274 */
server_state_unlock(const struct cras_client * client,int lock_rc)275 static void server_state_unlock(const struct cras_client *client,
276 int lock_rc)
277 {
278 struct client_int *client_int;
279
280 if (!client)
281 return;
282 client_int = to_client_int(client);
283 if (lock_rc == 0)
284 pthread_rwlock_unlock(&client_int->server_state_rwlock);
285 }
286
287 /*
288 * Lock the server_state_rwlock for reading.
289 *
290 * Also checks that the server_state pointer is valid.
291 *
292 * Args:
293 * client - The CRAS client pointer.
294 * Returns:
295 * 0 for success, positive error code on error.
296 * Returns EINVAL if the server state pointer is NULL.
297 */
server_state_rdlock(const struct cras_client * client)298 static int server_state_rdlock(const struct cras_client *client)
299 {
300 struct client_int *client_int;
301 int lock_rc;
302
303 if (!client)
304 return EINVAL;
305 client_int = to_client_int(client);
306 lock_rc = pthread_rwlock_rdlock(&client_int->server_state_rwlock);
307 if (lock_rc != 0)
308 return lock_rc;
309 if (!client->server_state) {
310 pthread_rwlock_unlock(&client_int->server_state_rwlock);
311 return EINVAL;
312 }
313 return 0;
314 }
315
316 /*
317 * Lock the server_state_rwlock for writing.
318 *
319 * Args:
320 * client - The CRAS client pointer.
321 * Returns:
322 * 0 for success, positive error code on error.
323 */
server_state_wrlock(const struct cras_client * client)324 static int server_state_wrlock(const struct cras_client *client)
325 {
326 struct client_int *client_int;
327
328 if (!client)
329 return EINVAL;
330 client_int = to_client_int(client);
331 return pthread_rwlock_wrlock(&client_int->server_state_rwlock);
332 }
333
334 /* Get the stream pointer from a stream id. */
stream_from_id(const struct cras_client * client,unsigned int id)335 static struct client_stream *stream_from_id(const struct cras_client *client,
336 unsigned int id)
337 {
338 struct client_stream *out;
339
340 DL_SEARCH_SCALAR(client->streams, out, id, id);
341 return out;
342 }
343
344 /*
345 * Fill a pollfd structure with the current server fd and events.
346 */
server_fill_pollfd(const struct cras_client * client,struct pollfd * poll_fd)347 void server_fill_pollfd(const struct cras_client *client,
348 struct pollfd *poll_fd)
349 {
350 int events = 0;
351
352 poll_fd->fd = client->server_fd;
353 switch (client->server_fd_state) {
354 case CRAS_SOCKET_STATE_DISCONNECTED:
355 break;
356 case CRAS_SOCKET_STATE_WAIT_FOR_SOCKET:
357 case CRAS_SOCKET_STATE_FIRST_MESSAGE:
358 case CRAS_SOCKET_STATE_CONNECTED:
359 case CRAS_SOCKET_STATE_ERROR_DELAY:
360 events = POLLIN;
361 break;
362 case CRAS_SOCKET_STATE_WAIT_FOR_WRITABLE:
363 events = POLLOUT;
364 break;
365 }
366 poll_fd->events = events;
367 poll_fd->revents = 0;
368 }
369
370 /*
371 * Change the server_fd_state.
372 */
server_fd_move_to_state(struct cras_client * client,cras_socket_state_t state)373 static void server_fd_move_to_state(struct cras_client *client,
374 cras_socket_state_t state)
375 {
376 if (state == client->server_fd_state)
377 return;
378
379 client->server_fd_state = state;
380 }
381
382 /*
383 * Action to take when in state ERROR_DELAY.
384 *
385 * In this state we want to sleep for a few seconds before retrying the
386 * connection to the audio server.
387 *
388 * If server_fd is negative: create a timer and setup server_fd with the
389 * timer's fd. If server_fd is not negative and there is input, then assume
390 * that the timer has expired, and restart the connection by moving to
391 * WAIT_FOR_SOCKET state.
392 */
error_delay_next_action(struct cras_client * client,int poll_revents)393 static int error_delay_next_action(struct cras_client *client,
394 int poll_revents)
395 {
396 int rc;
397 struct itimerspec timeout;
398
399 if (client->server_fd == -1) {
400 client->server_fd = timerfd_create(
401 CLOCK_MONOTONIC,
402 TFD_NONBLOCK|TFD_CLOEXEC);
403 if (client->server_fd == -1) {
404 rc = -errno;
405 syslog(LOG_ERR,
406 "cras_client: Could not create timerfd: %s",
407 strerror(-rc));
408 return rc;
409 }
410
411 /* Setup a relative timeout of 2 seconds. */
412 memset(&timeout, 0, sizeof(timeout));
413 timeout.it_value.tv_sec = 2;
414 rc = timerfd_settime(client->server_fd, 0, &timeout, NULL);
415 if (rc != 0) {
416 rc = -errno;
417 syslog(LOG_ERR,
418 "cras_client: Could not set timeout: %s",
419 strerror(-rc));
420 return rc;
421 }
422 return 0;
423 } else if ((poll_revents & POLLIN) == 0) {
424 return 0;
425 }
426
427 /* Move to the next state: close the timer fd first. */
428 close(client->server_fd);
429 client->server_fd = -1;
430 server_fd_move_to_state(client, CRAS_SOCKET_STATE_WAIT_FOR_SOCKET);
431 return 0;
432 }
433
434 /*
435 * Action to take when in WAIT_FOR_SOCKET state.
436 *
437 * In this state we are waiting for the socket file to exist. The existence of
438 * the socket file is continually monitored using the cras_file_wait structure
439 * and a separate fd. When the sock_file_exists boolean is modified, the state
440 * machine is invoked.
441 *
442 * If the socket file exists, then we move to the WAIT_FOR_WRITABLE state.
443 */
wait_for_socket_next_action(struct cras_client * client)444 static void wait_for_socket_next_action(struct cras_client *client)
445 {
446 if (client->sock_file_exists)
447 server_fd_move_to_state(
448 client, CRAS_SOCKET_STATE_WAIT_FOR_WRITABLE);
449 }
450
451 /*
452 * Action to take when in WAIT_FOR_WRITABLE state.
453 *
454 * In this state we are initiating a connection the server and waiting for the
455 * server to ready for incoming messages.
456 *
457 * Create the socket to the server, and wait while a connect request results in
458 * -EINPROGRESS. Otherwise, we assume that the socket file will be deleted by
459 * the server and the server_fd_state will be changed in
460 * sock_file_wait_dispatch().
461 */
wait_for_writable_next_action(struct cras_client * client,int poll_revents)462 static int wait_for_writable_next_action(struct cras_client *client,
463 int poll_revents)
464 {
465 int rc;
466 struct sockaddr_un address;
467
468 if (client->server_fd == -1) {
469 client->server_fd = socket(PF_UNIX, SOCK_SEQPACKET, 0);
470 if (client->server_fd < 0) {
471 rc = -errno;
472 syslog(LOG_ERR, "cras_client: server socket failed: %s",
473 strerror(-rc));
474 return rc;
475 }
476 }
477 else if ((poll_revents & POLLOUT) == 0) {
478 return 0;
479 }
480
481 /* We make the file descriptor non-blocking when we do connect(), so we
482 * don't block indefinitely. */
483 cras_make_fd_nonblocking(client->server_fd);
484
485 memset(&address, 0, sizeof(struct sockaddr_un));
486 address.sun_family = AF_UNIX;
487 strcpy(address.sun_path, client->sock_file);
488 rc = connect(client->server_fd, (struct sockaddr *)&address,
489 sizeof(struct sockaddr_un));
490 if (rc != 0) {
491 rc = -errno;
492 /* For -EINPROGRESS, we wait for POLLOUT on the server_fd.
493 * Otherwise CRAS is not running and we assume that the socket
494 * file will be deleted and recreated. Notification of that will
495 * happen via the sock_file_wait_dispatch(). */
496 if (rc == -ECONNREFUSED) {
497 /* CRAS is not running, don't log this error and just
498 * stay in this state waiting sock_file_wait_dispatch()
499 * to move the state machine. */
500 close(client->server_fd);
501 client->server_fd = -1;
502 }
503 else if (rc != -EINPROGRESS) {
504 syslog(LOG_ERR,
505 "cras_client: server connect failed: %s",
506 strerror(-rc));
507 return rc;
508 }
509 return 0;
510 }
511
512 cras_make_fd_blocking(client->server_fd);
513 server_fd_move_to_state(client, CRAS_SOCKET_STATE_FIRST_MESSAGE);
514 return 0;
515 }
516
517 /*
518 * Action to take when transitioning to the CONNECTED state.
519 */
connect_transition_action(struct cras_client * client)520 static int connect_transition_action(struct cras_client *client)
521 {
522 eventfd_t event_value;
523 int rc;
524
525 rc = reregister_notifications(client);
526 if (rc < 0)
527 return rc;
528
529 server_fd_move_to_state(client, CRAS_SOCKET_STATE_CONNECTED);
530 /* Notify anyone waiting on this state change that we're
531 * connected. */
532 eventfd_read(client->server_event_fd, &event_value);
533 eventfd_write(client->server_event_fd, 1);
534 if (client->server_connection_cb)
535 client->server_connection_cb(
536 client, CRAS_CONN_STATUS_CONNECTED,
537 client->server_connection_user_arg);
538 return 0;
539 }
540
541 /*
542 * Action to take when in the FIRST_MESSAGE state.
543 *
544 * We are waiting for the first message from the server. When our client ID has
545 * been set, then we can move to the CONNECTED state.
546 */
first_message_next_action(struct cras_client * client,int poll_revents)547 static int first_message_next_action(struct cras_client *client,
548 int poll_revents)
549 {
550 int rc;
551
552 if (client->server_fd < 0)
553 return -EINVAL;
554
555 if ((poll_revents & POLLIN) == 0)
556 return 0;
557
558 rc = handle_message_from_server(client);
559 if (rc < 0) {
560 syslog(LOG_ERR, "handle first message: %s", strerror(-rc));
561 } else if (client->id >= 0) {
562 rc = connect_transition_action(client);
563 } else {
564 syslog(LOG_ERR, "did not get ID after first message!");
565 rc = -EINVAL;
566 }
567 return rc;
568 }
569
570 /*
571 * Play nice and shutdown the server socket.
572 */
shutdown_and_close_socket(int sockfd)573 static inline int shutdown_and_close_socket(int sockfd)
574 {
575 int rc;
576 uint8_t buffer[CRAS_CLIENT_MAX_MSG_SIZE];
577 struct timeval tv;
578
579 tv.tv_sec = 0;
580 tv.tv_usec = SERVER_SHUTDOWN_TIMEOUT_US;
581 setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv));
582
583 rc = shutdown(sockfd, SHUT_WR);
584 if (rc < 0)
585 return rc;
586 /* Wait until the socket is closed by the peer. */
587 for (;;) {
588 rc = recv(sockfd, buffer, sizeof(buffer), 0);
589 if (rc <= 0)
590 break;
591 }
592 return close(sockfd);
593 }
594
595 /*
596 * Action to take when disconnecting from the server.
597 *
598 * Clean up the server socket, and the server_state pointer. Move to the next
599 * logical state.
600 */
disconnect_transition_action(struct cras_client * client,bool force)601 static void disconnect_transition_action(struct cras_client *client, bool force)
602 {
603 eventfd_t event_value;
604 cras_socket_state_t old_state = client->server_fd_state;
605 struct client_stream *s;
606 int lock_rc;
607
608 /* Stop all playing streams.
609 * TODO(muirj): Pause and resume streams. */
610 DL_FOREACH(client->streams, s) {
611 s->config->err_cb(client, s->id, -ENOTCONN,
612 s->config->user_data);
613 client_thread_rm_stream(client, s->id);
614 }
615
616 /* Clean up the server_state pointer. */
617 lock_rc = server_state_wrlock(client);
618 if (client->server_state) {
619 munmap((void *)client->server_state,
620 sizeof(*client->server_state));
621 client->server_state = NULL;
622 }
623 server_state_unlock(client, lock_rc);
624
625 /* Our ID is unknown now. */
626 client->id = -1;
627
628 /* Clean up the server fd. */
629 if (client->server_fd >= 0) {
630 if (!force)
631 shutdown_and_close_socket(client->server_fd);
632 else
633 close(client->server_fd);
634 client->server_fd = -1;
635 }
636
637 /* Reset the server_event_fd value to 0 (and cause subsequent threads
638 * waiting on the connection to wait). */
639 eventfd_read(client->server_event_fd, &event_value);
640
641 switch (old_state) {
642 case CRAS_SOCKET_STATE_DISCONNECTED:
643 /* Do nothing: already disconnected. */
644 break;
645 case CRAS_SOCKET_STATE_ERROR_DELAY:
646 /* We're disconnected and there was a failure to setup
647 * automatic reconnection, so call the server error
648 * callback now. */
649 server_fd_move_to_state(
650 client, CRAS_SOCKET_STATE_DISCONNECTED);
651 if (client->server_connection_cb)
652 client->server_connection_cb(
653 client, CRAS_CONN_STATUS_FAILED,
654 client->server_connection_user_arg);
655 else if (client->server_err_cb)
656 client->server_err_cb(
657 client, client->server_connection_user_arg);
658 break;
659 case CRAS_SOCKET_STATE_WAIT_FOR_SOCKET:
660 case CRAS_SOCKET_STATE_WAIT_FOR_WRITABLE:
661 case CRAS_SOCKET_STATE_FIRST_MESSAGE:
662 /* We are running this state transition while a connection is
663 * in progress for an error case. When there is no error, we
664 * come into this function in the DISCONNECTED state. */
665 server_fd_move_to_state(
666 client, CRAS_SOCKET_STATE_ERROR_DELAY);
667 break;
668 case CRAS_SOCKET_STATE_CONNECTED:
669 /* Disconnected from CRAS (for an error), wait for the socket
670 * file to be (re)created. */
671 server_fd_move_to_state(
672 client, CRAS_SOCKET_STATE_WAIT_FOR_SOCKET);
673 /* Notify the caller that we aren't connected anymore. */
674 if (client->server_connection_cb)
675 client->server_connection_cb(
676 client, CRAS_CONN_STATUS_DISCONNECTED,
677 client->server_connection_user_arg);
678 break;
679 }
680 }
681
server_fd_dispatch(struct cras_client * client,int poll_revents)682 static int server_fd_dispatch(struct cras_client *client, int poll_revents)
683 {
684 int rc = 0;
685 cras_socket_state_t old_state;
686
687 if ((poll_revents & POLLHUP) != 0) {
688 /* Error or disconnect: cleanup and make a state change now. */
689 disconnect_transition_action(client, true);
690 }
691 old_state = client->server_fd_state;
692
693 switch (client->server_fd_state) {
694 case CRAS_SOCKET_STATE_DISCONNECTED:
695 /* Assume that we've taken the necessary actions. */
696 return -ENOTCONN;
697 case CRAS_SOCKET_STATE_ERROR_DELAY:
698 rc = error_delay_next_action(client, poll_revents);
699 break;
700 case CRAS_SOCKET_STATE_WAIT_FOR_SOCKET:
701 wait_for_socket_next_action(client);
702 break;
703 case CRAS_SOCKET_STATE_WAIT_FOR_WRITABLE:
704 rc = wait_for_writable_next_action(client, poll_revents);
705 break;
706 case CRAS_SOCKET_STATE_FIRST_MESSAGE:
707 rc = first_message_next_action(client, poll_revents);
708 break;
709 case CRAS_SOCKET_STATE_CONNECTED:
710 if ((poll_revents & POLLIN) != 0)
711 rc = handle_message_from_server(client);
712 break;
713 }
714
715 if (rc != 0) {
716 /* If there is an error, then start-over. */
717 rc = server_fd_dispatch(client, POLLHUP);
718 } else if (old_state != client->server_fd_state) {
719 /* There was a state change, process the new state now. */
720 rc = server_fd_dispatch(client, 0);
721 }
722 return rc;
723 }
724
725 /*
726 * Start connecting to the server if we aren't already.
727 */
server_connect(struct cras_client * client)728 static int server_connect(struct cras_client *client)
729 {
730 if (client->server_fd_state != CRAS_SOCKET_STATE_DISCONNECTED)
731 return 0;
732 /* Start waiting for the server socket to exist. */
733 server_fd_move_to_state(client, CRAS_SOCKET_STATE_WAIT_FOR_SOCKET);
734 return server_fd_dispatch(client, 0);
735 }
736
737 /*
738 * Disconnect from the server if we haven't already.
739 */
server_disconnect(struct cras_client * client)740 static void server_disconnect(struct cras_client *client)
741 {
742 if (client->server_fd_state == CRAS_SOCKET_STATE_DISCONNECTED)
743 return;
744 /* Set the disconnected state first so that the disconnect
745 * transition doesn't move the server state to ERROR_DELAY. */
746 server_fd_move_to_state(client, CRAS_SOCKET_STATE_DISCONNECTED);
747 disconnect_transition_action(client, false);
748 }
749
750 /*
751 * Called when something happens to the socket file.
752 */
sock_file_wait_callback(void * context,cras_file_wait_event_t event,const char * filename)753 static void sock_file_wait_callback(void *context, cras_file_wait_event_t event,
754 const char *filename)
755 {
756 struct cras_client *client = (struct cras_client *)context;
757 switch (event) {
758 case CRAS_FILE_WAIT_EVENT_CREATED:
759 client->sock_file_exists = 1;
760 switch (client->server_fd_state) {
761 case CRAS_SOCKET_STATE_DISCONNECTED:
762 case CRAS_SOCKET_STATE_ERROR_DELAY:
763 case CRAS_SOCKET_STATE_FIRST_MESSAGE:
764 case CRAS_SOCKET_STATE_CONNECTED:
765 break;
766 case CRAS_SOCKET_STATE_WAIT_FOR_SOCKET:
767 case CRAS_SOCKET_STATE_WAIT_FOR_WRITABLE:
768 /* The socket file exists. Tell the server state
769 * machine. */
770 server_fd_dispatch(client, 0);
771 break;
772 }
773 break;
774 case CRAS_FILE_WAIT_EVENT_DELETED:
775 client->sock_file_exists = 0;
776 switch (client->server_fd_state) {
777 case CRAS_SOCKET_STATE_DISCONNECTED:
778 break;
779 case CRAS_SOCKET_STATE_WAIT_FOR_SOCKET:
780 case CRAS_SOCKET_STATE_WAIT_FOR_WRITABLE:
781 case CRAS_SOCKET_STATE_ERROR_DELAY:
782 case CRAS_SOCKET_STATE_FIRST_MESSAGE:
783 case CRAS_SOCKET_STATE_CONNECTED:
784 /* Restart the connection process. */
785 server_disconnect(client);
786 server_connect(client);
787 break;
788 }
789 break;
790 case CRAS_FILE_WAIT_EVENT_NONE:
791 break;
792 }
793 }
794
795 /*
796 * Service the sock_file_wait's fd.
797 *
798 * If the socket file is deleted, then cause a disconnect from the server.
799 * Otherwise, start a reconnect depending on the server_fd_state.
800 */
sock_file_wait_dispatch(struct cras_client * client,int poll_revents)801 static int sock_file_wait_dispatch(struct cras_client *client,
802 int poll_revents)
803 {
804 int rc;
805
806 if ((poll_revents & POLLIN) == 0)
807 return 0;
808
809 rc = cras_file_wait_dispatch(client->sock_file_wait);
810 if (rc == -EAGAIN || rc == -EWOULDBLOCK)
811 rc = 0;
812 else if (rc != 0)
813 syslog(LOG_ERR, "cras_file_wait_dispatch: %s", strerror(-rc));
814 return rc;
815 }
816
817 /*
818 * Waits until we have heard back from the server so that we know we are
819 * connected.
820 *
821 * The connected success/failure message is always the first message the server
822 * sends. Return non zero if client is connected to the server. A return code
823 * of zero means that the client is not connected to the server.
824 */
check_server_connected_wait(struct cras_client * client,struct timespec * timeout)825 static int check_server_connected_wait(struct cras_client *client,
826 struct timespec *timeout)
827 {
828 int rc = 0;
829 struct pollfd poll_fd;
830
831 poll_fd.fd = client->server_event_fd;
832 poll_fd.events = POLLIN;
833 poll_fd.revents = 0;
834
835 /* The server_event_fd is only read and written by the functions
836 * that connect to the server. When a connection is established the
837 * eventfd has a value of 1 and cras_poll will return immediately
838 * with 1. When there is no connection to the server, then this
839 * function waits until the timeout has expired or a non-zero value
840 * is written to the server_event_fd. */
841 while (rc == 0)
842 rc = cras_poll(&poll_fd, 1, timeout, NULL);
843 return rc > 0;
844 }
845
846 /* Returns non-zero if the thread is running (not stopped). */
thread_is_running(struct thread_state * thread)847 static inline int thread_is_running(struct thread_state *thread)
848 {
849 return thread->state != CRAS_THREAD_STOP;
850 }
851
852 /*
853 * Opens the server socket and connects to it.
854 * Args:
855 * client - Client pointer created with cras_client_create().
856 * timeout - Connection timeout.
857 * Returns:
858 * 0 for success, negative error code on failure.
859 */
connect_to_server(struct cras_client * client,struct timespec * timeout,bool use_command_thread)860 static int connect_to_server(struct cras_client *client,
861 struct timespec *timeout,
862 bool use_command_thread)
863 {
864 int rc;
865 struct pollfd poll_fd[2];
866 struct timespec connected_timeout;
867
868 if (!client)
869 return -EINVAL;
870
871 if (thread_is_running(&client->thread) && use_command_thread) {
872 rc = cras_client_connect_async(client);
873 if (rc == 0) {
874 rc = check_server_connected_wait(client, timeout);
875 return rc ? 0 : -ESHUTDOWN;
876 }
877 }
878
879 connected_timeout.tv_sec = 0;
880 connected_timeout.tv_nsec = 0;
881 if (check_server_connected_wait(client, &connected_timeout))
882 return 0;
883
884 poll_fd[0].fd = cras_file_wait_get_fd(client->sock_file_wait);
885 poll_fd[0].events = POLLIN;
886
887 rc = server_connect(client);
888 while(rc == 0) {
889 // Wait until we've connected or until there is a timeout.
890 // Meanwhile handle incoming actions on our fds.
891
892 server_fill_pollfd(client, &(poll_fd[1]));
893 rc = cras_poll(poll_fd, 2, timeout, NULL);
894 if (rc <= 0)
895 continue;
896
897 if (poll_fd[0].revents) {
898 rc = sock_file_wait_dispatch(
899 client, poll_fd[0].revents);
900 continue;
901 }
902
903 if (poll_fd[1].revents) {
904 rc = server_fd_dispatch(client, poll_fd[1].revents);
905 if (rc == 0 &&
906 client->server_fd_state ==
907 CRAS_SOCKET_STATE_CONNECTED)
908 break;
909 }
910 }
911
912 if (rc != 0)
913 syslog(LOG_ERR, "cras_client: Connect server failed: %s",
914 strerror(-rc));
915
916 return rc;
917 }
918
connect_to_server_wait_retry(struct cras_client * client,int timeout_ms,bool use_command_thread)919 static int connect_to_server_wait_retry(struct cras_client *client,
920 int timeout_ms,
921 bool use_command_thread)
922 {
923 struct timespec timeout_value;
924 struct timespec *timeout;
925
926 if (timeout_ms < 0) {
927 timeout = NULL;
928 } else {
929 timeout = &timeout_value;
930 ms_to_timespec(timeout_ms, timeout);
931 }
932
933 /* If connected, wait for the first message from the server
934 * indicating it's ready. */
935 return connect_to_server(client, timeout, use_command_thread);
936 }
937
938 /*
939 * Tries to connect to the server. Waits for the initial message from the
940 * server. This will happen near instantaneously if the server is already
941 * running.
942 */
connect_to_server_wait(struct cras_client * client,bool use_command_thread)943 static int connect_to_server_wait(struct cras_client *client,
944 bool use_command_thread)
945 {
946 return connect_to_server_wait_retry(
947 client, SERVER_CONNECT_TIMEOUT_MS, use_command_thread);
948 }
949
950 /*
951 * Audio thread.
952 */
953
954 /* Sends a message from the stream to the client to indicate an error.
955 * If the running stream encounters an error, then it must tell the client
956 * to stop running it.
957 */
send_stream_message(const struct client_stream * stream,unsigned msg_id)958 static int send_stream_message(const struct client_stream *stream,
959 unsigned msg_id)
960 {
961 int res;
962 struct stream_msg msg;
963
964 msg.stream_id = stream->id;
965 msg.msg_id = msg_id;
966 res = write(stream->client->stream_fds[1], &msg, sizeof(msg));
967 if (res != sizeof(msg))
968 return -EPIPE;
969
970 return 0;
971 }
972
973 /* Blocks until there is data to be read from the read_fd or until woken by an
974 * incoming "poke" on wake_fd. Up to "len" bytes are read into "buf". */
read_with_wake_fd(int wake_fd,int read_fd,uint8_t * buf,size_t len)975 static int read_with_wake_fd(int wake_fd, int read_fd, uint8_t *buf, size_t len)
976 {
977 struct pollfd pollfds[2];
978 int nread = 0;
979 int nfds = 1;
980 int rc;
981 char tmp;
982
983 pollfds[0].fd = wake_fd;
984 pollfds[0].events = POLLIN;
985 if (read_fd >= 0) {
986 nfds++;
987 pollfds[1].fd = read_fd;
988 pollfds[1].events = POLLIN;
989 }
990
991 rc = poll(pollfds, nfds, -1);
992 if (rc < 0)
993 return rc;
994 if (read_fd >= 0 && pollfds[1].revents & POLLIN) {
995 nread = read(read_fd, buf, len);
996 if (nread != (int)len)
997 return -EIO;
998 }
999 if (pollfds[0].revents & POLLIN) {
1000 rc = read(wake_fd, &tmp, 1);
1001 if (rc < 0)
1002 return rc;
1003 }
1004
1005 return nread;
1006 }
1007 /* Check the availability and configures a capture buffer.
1008 * Args:
1009 * stream - The input stream to configure buffer for.
1010 * captured_frames - To be filled with the pointer to the beginning of
1011 * captured buffer.
1012 * num_frames - Number of captured frames.
1013 * Returns:
1014 * Number of frames available in captured_frames.
1015 */
config_capture_buf(struct client_stream * stream,uint8_t ** captured_frames,unsigned int num_frames)1016 static unsigned int config_capture_buf(struct client_stream *stream,
1017 uint8_t **captured_frames,
1018 unsigned int num_frames)
1019 {
1020 /* Always return the beginning of the read buffer because Chrome expects
1021 * so. */
1022 *captured_frames = cras_shm_get_read_buffer_base(&stream->capture_shm);
1023
1024 /* Don't ask for more frames than the client desires. */
1025 if (stream->flags & BULK_AUDIO_OK)
1026 num_frames = MIN(num_frames, stream->config->buffer_frames);
1027 else
1028 num_frames = MIN(num_frames, stream->config->cb_threshold);
1029
1030 /* If shm readable frames is less than client requests, that means
1031 * overrun has happened in server side. Don't send partial corrupted
1032 * buffer to client. */
1033 if (cras_shm_get_curr_read_frames(&stream->capture_shm) < num_frames)
1034 return 0;
1035
1036 return num_frames;
1037 }
1038
complete_capture_read_current(struct client_stream * stream,unsigned int num_frames)1039 static void complete_capture_read_current(struct client_stream *stream,
1040 unsigned int num_frames)
1041 {
1042 cras_shm_buffer_read_current(&stream->capture_shm, num_frames);
1043 }
1044
1045 /* For capture streams this handles the message signalling that data is ready to
1046 * be passed to the user of this stream. Calls the audio callback with the new
1047 * samples, and mark them as read.
1048 * Args:
1049 * stream - The stream the message was received for.
1050 * num_frames - The number of captured frames.
1051 * Returns:
1052 * 0, unless there is a fatal error or the client declares enod of file.
1053 */
handle_capture_data_ready(struct client_stream * stream,unsigned int num_frames)1054 static int handle_capture_data_ready(struct client_stream *stream,
1055 unsigned int num_frames)
1056 {
1057 int frames;
1058 struct cras_stream_params *config;
1059 uint8_t *captured_frames;
1060 struct timespec ts;
1061
1062 config = stream->config;
1063 /* If this message is for an output stream, log error and drop it. */
1064 if (!cras_stream_has_input(stream->direction)) {
1065 syslog(LOG_ERR, "cras_client: Play data to input\n");
1066 return 0;
1067 }
1068
1069 num_frames = config_capture_buf(stream, &captured_frames, num_frames);
1070 if (num_frames == 0)
1071 return 0;
1072
1073 cras_timespec_to_timespec(&ts, &stream->capture_shm.area->ts);
1074
1075 if (config->unified_cb)
1076 frames = config->unified_cb(stream->client,
1077 stream->id,
1078 captured_frames,
1079 NULL,
1080 num_frames,
1081 &ts,
1082 NULL,
1083 config->user_data);
1084 else
1085 frames = config->aud_cb(stream->client,
1086 stream->id,
1087 captured_frames,
1088 num_frames,
1089 &ts,
1090 config->user_data);
1091 if (frames == EOF) {
1092 send_stream_message(stream, CLIENT_STREAM_EOF);
1093 return EOF;
1094 }
1095 if (frames == 0)
1096 return 0;
1097
1098 complete_capture_read_current(stream, frames);
1099 return 0;
1100 }
1101
1102 /* Notifies the server that "frames" samples have been written. */
send_playback_reply(struct client_stream * stream,unsigned int frames,int error)1103 static int send_playback_reply(struct client_stream *stream,
1104 unsigned int frames,
1105 int error)
1106 {
1107 struct audio_message aud_msg;
1108 int rc;
1109
1110 if (!cras_stream_uses_output_hw(stream->direction))
1111 return 0;
1112
1113 aud_msg.id = AUDIO_MESSAGE_DATA_READY;
1114 aud_msg.frames = frames;
1115 aud_msg.error = error;
1116
1117 rc = write(stream->aud_fd, &aud_msg, sizeof(aud_msg));
1118 if (rc != sizeof(aud_msg))
1119 return -EPIPE;
1120
1121 return 0;
1122 }
1123
1124 /* For playback streams when current buffer is empty, this handles the request
1125 * for more samples by calling the audio callback for the thread, and signaling
1126 * the server that the samples have been written. */
handle_playback_request(struct client_stream * stream,unsigned int num_frames)1127 static int handle_playback_request(struct client_stream *stream,
1128 unsigned int num_frames)
1129 {
1130 uint8_t *buf;
1131 int frames;
1132 int rc = 0;
1133 struct cras_stream_params *config;
1134 struct cras_audio_shm *shm = &stream->play_shm;
1135 struct timespec ts;
1136
1137 config = stream->config;
1138
1139 /* If this message is for an input stream, log error and drop it. */
1140 if (stream->direction != CRAS_STREAM_OUTPUT) {
1141 syslog(LOG_ERR, "cras_client: Record data from output\n");
1142 return 0;
1143 }
1144
1145 buf = cras_shm_get_write_buffer_base(&stream->play_shm);
1146
1147 /* Limit the amount of frames to the configured amount. */
1148 num_frames = MIN(num_frames, config->cb_threshold);
1149
1150 cras_timespec_to_timespec(&ts, &shm->area->ts);
1151
1152 /* Get samples from the user */
1153 if (config->unified_cb)
1154 frames = config->unified_cb(stream->client,
1155 stream->id,
1156 NULL,
1157 buf,
1158 num_frames,
1159 NULL,
1160 &ts,
1161 config->user_data);
1162 else
1163 frames = config->aud_cb(stream->client,
1164 stream->id,
1165 buf,
1166 num_frames,
1167 &ts,
1168 config->user_data);
1169 if (frames < 0) {
1170 send_stream_message(stream, CLIENT_STREAM_EOF);
1171 rc = frames;
1172 goto reply_written;
1173 }
1174
1175 cras_shm_buffer_written_start(shm, frames);
1176
1177 reply_written:
1178 /* Signal server that data is ready, or that an error has occurred. */
1179 rc = send_playback_reply(stream, frames, rc);
1180 return rc;
1181 }
1182
audio_thread_set_priority(struct client_stream * stream)1183 static void audio_thread_set_priority(struct client_stream *stream)
1184 {
1185 /* Use provided callback to set priority if available. */
1186 if (stream->client->thread_priority_cb) {
1187 stream->client->thread_priority_cb(stream->client);
1188 return;
1189 }
1190
1191 /* Try to get RT scheduling, if that fails try to set the nice value. */
1192 if (cras_set_rt_scheduling(CRAS_CLIENT_RT_THREAD_PRIORITY) ||
1193 cras_set_thread_priority(CRAS_CLIENT_RT_THREAD_PRIORITY))
1194 cras_set_nice_level(CRAS_CLIENT_NICENESS_LEVEL);
1195 }
1196
1197 /* Listens to the audio socket for messages from the server indicating that
1198 * the stream needs to be serviced. One of these runs per stream. */
audio_thread(void * arg)1199 static void *audio_thread(void *arg)
1200 {
1201 struct client_stream *stream = (struct client_stream *)arg;
1202 int thread_terminated = 0;
1203 struct audio_message aud_msg;
1204 int aud_fd;
1205 int num_read;
1206
1207 if (arg == NULL)
1208 return (void *)-EIO;
1209
1210 audio_thread_set_priority(stream);
1211
1212 /* Notify the control thread that we've started. */
1213 pthread_mutex_lock(&stream->client->stream_start_lock);
1214 pthread_cond_broadcast(&stream->client->stream_start_cond);
1215 pthread_mutex_unlock(&stream->client->stream_start_lock);
1216
1217 while (thread_is_running(&stream->thread) && !thread_terminated) {
1218 /* While we are warming up, aud_fd may not be valid and some
1219 * shared memory resources may not yet be available. */
1220 aud_fd = (stream->thread.state == CRAS_THREAD_WARMUP) ?
1221 -1 : stream->aud_fd;
1222 num_read = read_with_wake_fd(stream->wake_fds[0],
1223 aud_fd,
1224 (uint8_t *)&aud_msg,
1225 sizeof(aud_msg));
1226 if (num_read < 0)
1227 return (void *)-EIO;
1228 if (num_read == 0)
1229 continue;
1230
1231 switch (aud_msg.id) {
1232 case AUDIO_MESSAGE_DATA_READY:
1233 thread_terminated = handle_capture_data_ready(
1234 stream,
1235 aud_msg.frames);
1236 break;
1237 case AUDIO_MESSAGE_REQUEST_DATA:
1238 thread_terminated = handle_playback_request(
1239 stream,
1240 aud_msg.frames);
1241 break;
1242 default:
1243 break;
1244 }
1245 }
1246
1247 return NULL;
1248 }
1249
1250 /* Pokes the audio thread so that it can notice if it has been terminated. */
wake_aud_thread(struct client_stream * stream)1251 static int wake_aud_thread(struct client_stream *stream)
1252 {
1253 int rc;
1254
1255 rc = write(stream->wake_fds[1], &rc, 1);
1256 if (rc != 1)
1257 return rc;
1258 return 0;
1259 }
1260
1261 /* Stop the audio thread for the given stream.
1262 * Args:
1263 * stream - Stream for which to stop the audio thread.
1264 * join - When non-zero, attempt to join the audio thread (wait for it to
1265 * complete).
1266 */
stop_aud_thread(struct client_stream * stream,int join)1267 static void stop_aud_thread(struct client_stream *stream, int join)
1268 {
1269 if (thread_is_running(&stream->thread)) {
1270 stream->thread.state = CRAS_THREAD_STOP;
1271 wake_aud_thread(stream);
1272 if (join)
1273 pthread_join(stream->thread.tid, NULL);
1274 }
1275
1276 if (stream->wake_fds[0] >= 0) {
1277 close(stream->wake_fds[0]);
1278 close(stream->wake_fds[1]);
1279 stream->wake_fds[0] = -1;
1280 }
1281 }
1282
1283 /* Start the audio thread for this stream.
1284 * Returns when the thread has started and is waiting.
1285 * Args:
1286 * stream - The stream that needs an audio thread.
1287 * Returns:
1288 * 0 for success, or a negative error code.
1289 */
start_aud_thread(struct client_stream * stream)1290 static int start_aud_thread(struct client_stream *stream)
1291 {
1292 int rc;
1293 struct timespec future;
1294
1295 rc = pipe(stream->wake_fds);
1296 if (rc < 0) {
1297 rc = -errno;
1298 syslog(LOG_ERR, "cras_client: pipe: %s", strerror(-rc));
1299 return rc;
1300 }
1301
1302 stream->thread.state = CRAS_THREAD_WARMUP;
1303
1304 pthread_mutex_lock(&stream->client->stream_start_lock);
1305 rc = pthread_create(&stream->thread.tid, NULL, audio_thread, stream);
1306 if (rc) {
1307 pthread_mutex_unlock(&stream->client->stream_start_lock);
1308 syslog(LOG_ERR,
1309 "cras_client: Couldn't create audio stream: %s",
1310 strerror(rc));
1311 stream->thread.state = CRAS_THREAD_STOP;
1312 stop_aud_thread(stream, 0);
1313 return -rc;
1314 }
1315
1316 clock_gettime(CLOCK_MONOTONIC, &future);
1317 future.tv_sec += 2; /* Wait up to two seconds. */
1318 rc = pthread_cond_timedwait(&stream->client->stream_start_cond,
1319 &stream->client->stream_start_lock, &future);
1320 pthread_mutex_unlock(&stream->client->stream_start_lock);
1321 if (rc != 0) {
1322 /* Something is very wrong: try to cancel the thread and don't
1323 * wait for it. */
1324 syslog(LOG_ERR, "cras_client: Client thread not responding: %s",
1325 strerror(rc));
1326 stop_aud_thread(stream, 0);
1327 return -rc;
1328 }
1329 return 0;
1330 }
1331
1332 /*
1333 * Client thread.
1334 */
1335
1336 /* Gets the update_count of the server state shm region. */
1337 static inline
begin_server_state_read(const struct cras_server_state * state)1338 unsigned begin_server_state_read(const struct cras_server_state *state)
1339 {
1340 unsigned count;
1341
1342 /* Version will be odd when the server is writing. */
1343 while ((count = *(volatile unsigned *)&state->update_count) & 1)
1344 sched_yield();
1345 __sync_synchronize();
1346 return count;
1347 }
1348
1349 /* Checks if the update count of the server state shm region has changed from
1350 * count. Returns 0 if the count still matches.
1351 */
1352 static inline
end_server_state_read(const struct cras_server_state * state,unsigned count)1353 int end_server_state_read(const struct cras_server_state *state, unsigned count)
1354 {
1355 __sync_synchronize();
1356 if (count != *(volatile unsigned *)&state->update_count)
1357 return -EAGAIN;
1358 return 0;
1359
1360 }
1361
1362 /* Gets the shared memory region used to share audio data with the server. */
config_shm(struct cras_audio_shm * shm,int shm_fd,size_t size)1363 static int config_shm(struct cras_audio_shm *shm, int shm_fd, size_t size)
1364 {
1365 shm->area = (struct cras_audio_shm_area *)mmap(
1366 NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
1367 shm_fd, 0);
1368 if (shm->area == (struct cras_audio_shm_area *)-1) {
1369 syslog(LOG_ERR,
1370 "cras_client: mmap failed to map shm for stream.");
1371 return errno;
1372 }
1373 /* Copy server shm config locally. */
1374 cras_shm_copy_shared_config(shm);
1375
1376 return 0;
1377 }
1378
1379 /* Release shm areas if references to them are held. */
free_shm(struct client_stream * stream)1380 static void free_shm(struct client_stream *stream)
1381 {
1382 if (stream->capture_shm.area) {
1383 munmap(stream->capture_shm.area, stream->capture_shm_size);
1384 }
1385 if (stream->play_shm.area) {
1386 munmap(stream->play_shm.area, stream->play_shm_size);
1387 }
1388 stream->capture_shm.area = NULL;
1389 stream->play_shm.area = NULL;
1390 }
1391
1392 /* Handles the stream connected message from the server. Check if we need a
1393 * format converter, configure the shared memory region, and start the audio
1394 * thread that will handle requests from the server. */
stream_connected(struct client_stream * stream,const struct cras_client_stream_connected * msg,const int stream_fds[2],const unsigned int num_fds)1395 static int stream_connected(struct client_stream *stream,
1396 const struct cras_client_stream_connected *msg,
1397 const int stream_fds[2], const unsigned int num_fds)
1398 {
1399 int rc;
1400 struct cras_audio_format mfmt;
1401
1402 if (msg->err || num_fds != 2) {
1403 syslog(LOG_ERR, "cras_client: Error Setting up stream %d\n",
1404 msg->err);
1405 rc = msg->err;
1406 goto err_ret;
1407 }
1408
1409 unpack_cras_audio_format(&mfmt, &msg->format);
1410
1411 if (cras_stream_has_input(stream->direction)) {
1412 rc = config_shm(&stream->capture_shm,
1413 stream_fds[0],
1414 msg->shm_max_size);
1415 if (rc < 0) {
1416 syslog(LOG_ERR,
1417 "cras_client: Error configuring capture shm");
1418 goto err_ret;
1419 }
1420 stream->capture_shm_size = msg->shm_max_size;
1421 }
1422
1423 if (cras_stream_uses_output_hw(stream->direction)) {
1424 rc = config_shm(&stream->play_shm,
1425 stream_fds[1],
1426 msg->shm_max_size);
1427 if (rc < 0) {
1428 syslog(LOG_ERR,
1429 "cras_client: Error configuring playback shm");
1430 goto err_ret;
1431 }
1432 stream->play_shm_size = msg->shm_max_size;
1433
1434 cras_shm_set_volume_scaler(&stream->play_shm,
1435 stream->volume_scaler);
1436 }
1437
1438 stream->thread.state = CRAS_THREAD_RUNNING;
1439 wake_aud_thread(stream);
1440
1441 close(stream_fds[0]);
1442 close(stream_fds[1]);
1443 return 0;
1444 err_ret:
1445 stop_aud_thread(stream, 1);
1446 close(stream_fds[0]);
1447 close(stream_fds[1]);
1448 free_shm(stream);
1449 return rc;
1450 }
1451
send_connect_message(struct cras_client * client,struct client_stream * stream,uint32_t dev_idx)1452 static int send_connect_message(struct cras_client *client,
1453 struct client_stream *stream,
1454 uint32_t dev_idx)
1455 {
1456 int rc;
1457 struct cras_connect_message serv_msg;
1458 int sock[2] = {-1, -1};
1459
1460 /* Create a socket pair for the server to notify of audio events. */
1461 rc = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
1462 if (rc != 0) {
1463 rc = -errno;
1464 syslog(LOG_ERR, "cras_client: socketpair: %s", strerror(-rc));
1465 goto fail;
1466 }
1467
1468 cras_fill_connect_message(&serv_msg,
1469 stream->config->direction,
1470 stream->id,
1471 stream->config->stream_type,
1472 stream->config->buffer_frames,
1473 stream->config->cb_threshold,
1474 stream->flags,
1475 stream->config->format,
1476 dev_idx);
1477 rc = cras_send_with_fds(client->server_fd, &serv_msg, sizeof(serv_msg),
1478 &sock[1], 1);
1479 if (rc != sizeof(serv_msg)) {
1480 rc = EIO;
1481 syslog(LOG_ERR,
1482 "cras_client: add_stream: Send server message failed.");
1483 goto fail;
1484 }
1485
1486 stream->aud_fd = sock[0];
1487 close(sock[1]);
1488 return 0;
1489
1490 fail:
1491 if (sock[0] != -1)
1492 close(sock[0]);
1493 if (sock[1] != -1)
1494 close(sock[1]);
1495 return rc;
1496 }
1497
1498 /* Adds a stream to a running client. Checks to make sure that the client is
1499 * attached, waits if it isn't. The stream is prepared on the main thread and
1500 * passed here. */
client_thread_add_stream(struct cras_client * client,struct client_stream * stream,cras_stream_id_t * stream_id_out,uint32_t dev_idx)1501 static int client_thread_add_stream(struct cras_client *client,
1502 struct client_stream *stream,
1503 cras_stream_id_t *stream_id_out,
1504 uint32_t dev_idx)
1505 {
1506 int rc;
1507 cras_stream_id_t new_id;
1508 struct client_stream *out;
1509
1510 /* Find the hotword device index. */
1511 if ((stream->flags & HOTWORD_STREAM) == HOTWORD_STREAM &&
1512 dev_idx == NO_DEVICE) {
1513 int hotword_idx;
1514 hotword_idx = cras_client_get_first_dev_type_idx(client,
1515 CRAS_NODE_TYPE_HOTWORD, CRAS_STREAM_INPUT);
1516 if (hotword_idx < 0) {
1517 syslog(LOG_ERR,
1518 "cras_client: add_stream: Finding hotword dev");
1519 return hotword_idx;
1520 }
1521 dev_idx = hotword_idx;
1522 }
1523
1524 /* Find an available stream id. */
1525 do {
1526 new_id = cras_get_stream_id(client->id, client->next_stream_id);
1527 client->next_stream_id++;
1528 DL_SEARCH_SCALAR(client->streams, out, id, new_id);
1529 } while (out != NULL);
1530
1531 stream->id = new_id;
1532 *stream_id_out = new_id;
1533 stream->client = client;
1534
1535 /* Start the audio thread. */
1536 rc = start_aud_thread(stream);
1537 if (rc != 0)
1538 return rc;
1539
1540 /* Start the thread associated with this stream. */
1541 /* send a message to the server asking that the stream be started. */
1542 rc = send_connect_message(client, stream, dev_idx);
1543 if (rc != 0) {
1544 stop_aud_thread(stream, 1);
1545 return rc;
1546 }
1547
1548 /* Add the stream to the linked list */
1549 DL_APPEND(client->streams, stream);
1550
1551 return 0;
1552 }
1553
1554 /* Removes a stream from a running client from within the running client's
1555 * context. */
client_thread_rm_stream(struct cras_client * client,cras_stream_id_t stream_id)1556 static int client_thread_rm_stream(struct cras_client *client,
1557 cras_stream_id_t stream_id)
1558 {
1559 struct cras_disconnect_stream_message msg;
1560 struct client_stream *stream =
1561 stream_from_id(client, stream_id);
1562 int rc;
1563
1564 if (stream == NULL)
1565 return 0;
1566
1567 /* Tell server to remove. */
1568 if (client->server_fd_state == CRAS_SOCKET_STATE_CONNECTED) {
1569 cras_fill_disconnect_stream_message(&msg, stream_id);
1570 rc = write(client->server_fd, &msg, sizeof(msg));
1571 if (rc < 0)
1572 syslog(LOG_ERR,
1573 "cras_client: error removing stream from server\n");
1574 }
1575
1576 /* And shut down locally. */
1577 stop_aud_thread(stream, 1);
1578
1579 free_shm(stream);
1580
1581 DL_DELETE(client->streams, stream);
1582 if (stream->aud_fd >= 0)
1583 close(stream->aud_fd);
1584
1585 free(stream->config);
1586 free(stream);
1587
1588 return 0;
1589 }
1590
1591 /* Sets the volume scaling factor for a playing stream. */
client_thread_set_stream_volume(struct cras_client * client,cras_stream_id_t stream_id,float volume_scaler)1592 static int client_thread_set_stream_volume(struct cras_client *client,
1593 cras_stream_id_t stream_id,
1594 float volume_scaler)
1595 {
1596 struct client_stream *stream;
1597
1598 stream = stream_from_id(client, stream_id);
1599 if (stream == NULL || volume_scaler > 1.0 || volume_scaler < 0.0)
1600 return -EINVAL;
1601
1602 stream->volume_scaler = volume_scaler;
1603 if (stream->play_shm.area != NULL)
1604 cras_shm_set_volume_scaler(&stream->play_shm, volume_scaler);
1605
1606 return 0;
1607 }
1608
1609 /* Attach to the shm region containing the server state. */
client_attach_shm(struct cras_client * client,int shm_fd)1610 static int client_attach_shm(struct cras_client *client, int shm_fd)
1611 {
1612 int lock_rc;
1613 int rc;
1614
1615 lock_rc = server_state_wrlock(client);
1616 if (client->server_state) {
1617 rc = -EBUSY;
1618 goto error;
1619 }
1620
1621 client->server_state = (struct cras_server_state *)mmap(
1622 NULL, sizeof(*client->server_state),
1623 PROT_READ, MAP_SHARED, shm_fd, 0);
1624 rc = -errno;
1625 close(shm_fd);
1626 if (client->server_state == (struct cras_server_state *)-1) {
1627 syslog(LOG_ERR,
1628 "cras_client: mmap failed to map shm for client: %s",
1629 strerror(-rc));
1630 goto error;
1631 }
1632
1633 if (client->server_state->state_version != CRAS_SERVER_STATE_VERSION) {
1634 munmap((void *)client->server_state,
1635 sizeof(*client->server_state));
1636 client->server_state = NULL;
1637 rc = -EINVAL;
1638 syslog(LOG_ERR, "cras_client: Unknown server_state version.");
1639 } else {
1640 rc = 0;
1641 }
1642
1643 error:
1644 server_state_unlock(client, lock_rc);
1645 return rc;
1646 }
1647
cras_client_get_hotword_models_ready(struct cras_client * client,const char * hotword_models)1648 static void cras_client_get_hotword_models_ready(
1649 struct cras_client *client,
1650 const char *hotword_models)
1651 {
1652 if (!client->get_hotword_models_cb)
1653 return;
1654 client->get_hotword_models_cb(client, hotword_models);
1655 client->get_hotword_models_cb = NULL;
1656 }
1657
1658 /* Handles messages from the cras server. */
handle_message_from_server(struct cras_client * client)1659 static int handle_message_from_server(struct cras_client *client)
1660 {
1661 uint8_t buf[CRAS_CLIENT_MAX_MSG_SIZE];
1662 struct cras_client_message *msg;
1663 int rc = 0;
1664 int nread;
1665 int server_fds[2];
1666 unsigned int num_fds = 2;
1667
1668 msg = (struct cras_client_message *)buf;
1669 nread = cras_recv_with_fds(client->server_fd, buf, sizeof(buf),
1670 server_fds, &num_fds);
1671 if (nread < (int)sizeof(msg->length) || (int)msg->length != nread)
1672 return -EIO;
1673
1674 switch (msg->id) {
1675 case CRAS_CLIENT_CONNECTED: {
1676 struct cras_client_connected *cmsg =
1677 (struct cras_client_connected *)msg;
1678 if (num_fds != 1)
1679 return -EINVAL;
1680 rc = client_attach_shm(client, server_fds[0]);
1681 if (rc)
1682 return rc;
1683 client->id = cmsg->client_id;
1684
1685 break;
1686 }
1687 case CRAS_CLIENT_STREAM_CONNECTED: {
1688 struct cras_client_stream_connected *cmsg =
1689 (struct cras_client_stream_connected *)msg;
1690 struct client_stream *stream =
1691 stream_from_id(client, cmsg->stream_id);
1692 if (stream == NULL)
1693 break;
1694 rc = stream_connected(stream, cmsg, server_fds, num_fds);
1695 if (rc < 0)
1696 stream->config->err_cb(stream->client,
1697 stream->id,
1698 rc,
1699 stream->config->user_data);
1700 break;
1701 }
1702 case CRAS_CLIENT_AUDIO_DEBUG_INFO_READY:
1703 if (client->debug_info_callback)
1704 client->debug_info_callback(client);
1705 break;
1706 case CRAS_CLIENT_GET_HOTWORD_MODELS_READY: {
1707 struct cras_client_get_hotword_models_ready *cmsg =
1708 (struct cras_client_get_hotword_models_ready *)msg;
1709 cras_client_get_hotword_models_ready(client,
1710 (const char *)cmsg->hotword_models);
1711 break;
1712 }
1713 case CRAS_CLIENT_OUTPUT_VOLUME_CHANGED: {
1714 struct cras_client_volume_changed *cmsg =
1715 (struct cras_client_volume_changed *)msg;
1716 if (client->observer_ops.output_volume_changed)
1717 client->observer_ops.output_volume_changed(
1718 client->observer_context,
1719 cmsg->volume);
1720 break;
1721 }
1722 case CRAS_CLIENT_OUTPUT_MUTE_CHANGED: {
1723 struct cras_client_mute_changed *cmsg =
1724 (struct cras_client_mute_changed *)msg;
1725 if (client->observer_ops.output_mute_changed)
1726 client->observer_ops.output_mute_changed(
1727 client->observer_context,
1728 cmsg->muted,
1729 cmsg->user_muted,
1730 cmsg->mute_locked);
1731 break;
1732 }
1733 case CRAS_CLIENT_CAPTURE_GAIN_CHANGED: {
1734 struct cras_client_volume_changed *cmsg =
1735 (struct cras_client_volume_changed *)msg;
1736 if (client->observer_ops.capture_gain_changed)
1737 client->observer_ops.capture_gain_changed(
1738 client->observer_context,
1739 cmsg->volume);
1740 break;
1741 }
1742 case CRAS_CLIENT_CAPTURE_MUTE_CHANGED: {
1743 struct cras_client_mute_changed *cmsg =
1744 (struct cras_client_mute_changed *)msg;
1745 if (client->observer_ops.capture_mute_changed)
1746 client->observer_ops.capture_mute_changed(
1747 client->observer_context,
1748 cmsg->muted,
1749 cmsg->mute_locked);
1750 break;
1751 }
1752 case CRAS_CLIENT_NODES_CHANGED: {
1753 if (client->observer_ops.nodes_changed)
1754 client->observer_ops.nodes_changed(
1755 client->observer_context);
1756 break;
1757 }
1758 case CRAS_CLIENT_ACTIVE_NODE_CHANGED: {
1759 struct cras_client_active_node_changed *cmsg =
1760 (struct cras_client_active_node_changed *)msg;
1761 enum CRAS_STREAM_DIRECTION direction =
1762 (enum CRAS_STREAM_DIRECTION)cmsg->direction;
1763 if (client->observer_ops.active_node_changed)
1764 client->observer_ops.active_node_changed(
1765 client->observer_context,
1766 direction, cmsg->node_id);
1767 break;
1768 }
1769 case CRAS_CLIENT_OUTPUT_NODE_VOLUME_CHANGED: {
1770 struct cras_client_node_value_changed *cmsg =
1771 (struct cras_client_node_value_changed *)msg;
1772 if (client->observer_ops.output_node_volume_changed)
1773 client->observer_ops.output_node_volume_changed(
1774 client->observer_context,
1775 cmsg->node_id,
1776 cmsg->value);
1777 break;
1778 }
1779 case CRAS_CLIENT_NODE_LEFT_RIGHT_SWAPPED_CHANGED: {
1780 struct cras_client_node_value_changed *cmsg =
1781 (struct cras_client_node_value_changed *)msg;
1782 if (client->observer_ops.node_left_right_swapped_changed)
1783 client->observer_ops.node_left_right_swapped_changed(
1784 client->observer_context,
1785 cmsg->node_id,
1786 cmsg->value);
1787 break;
1788 }
1789 case CRAS_CLIENT_INPUT_NODE_GAIN_CHANGED: {
1790 struct cras_client_node_value_changed *cmsg =
1791 (struct cras_client_node_value_changed *)msg;
1792 if (client->observer_ops.input_node_gain_changed)
1793 client->observer_ops.input_node_gain_changed(
1794 client->observer_context,
1795 cmsg->node_id,
1796 cmsg->value);
1797 break;
1798 }
1799 case CRAS_CLIENT_NUM_ACTIVE_STREAMS_CHANGED: {
1800 struct cras_client_num_active_streams_changed *cmsg =
1801 (struct cras_client_num_active_streams_changed *)msg;
1802 enum CRAS_STREAM_DIRECTION direction =
1803 (enum CRAS_STREAM_DIRECTION)cmsg->direction;
1804 if (client->observer_ops.num_active_streams_changed)
1805 client->observer_ops.num_active_streams_changed(
1806 client->observer_context,
1807 direction, cmsg->num_active_streams);
1808 break;
1809 }
1810 default:
1811 break;
1812 }
1813
1814 return 0;
1815 }
1816
1817 /* Handles messages from streams to this client. */
handle_stream_message(struct cras_client * client,int poll_revents)1818 static int handle_stream_message(struct cras_client *client,
1819 int poll_revents)
1820 {
1821 struct stream_msg msg;
1822 int rc;
1823
1824 if ((poll_revents & POLLIN) == 0)
1825 return 0;
1826
1827 rc = read(client->stream_fds[0], &msg, sizeof(msg));
1828 if (rc < 0)
1829 syslog(LOG_ERR, "cras_client: Stream read failed %d\n", errno);
1830 /* The only reason a stream sends a message is if it needs to be
1831 * removed. An error on read would mean the same thing so regardless of
1832 * what gets us here, just remove the stream */
1833 client_thread_rm_stream(client, msg.stream_id);
1834 return 0;
1835 }
1836
1837 /* Handles messages from users to this client. */
handle_command_message(struct cras_client * client,int poll_revents)1838 static int handle_command_message(struct cras_client *client,
1839 int poll_revents)
1840 {
1841 uint8_t buf[MAX_CMD_MSG_LEN];
1842 struct command_msg *msg = (struct command_msg *)buf;
1843 int rc, to_read;
1844
1845 if ((poll_revents & POLLIN) == 0)
1846 return 0;
1847
1848 rc = read(client->command_fds[0], buf, sizeof(msg->len));
1849 if (rc != sizeof(msg->len) || msg->len > MAX_CMD_MSG_LEN) {
1850 rc = -EIO;
1851 goto cmd_msg_complete;
1852 }
1853 to_read = msg->len - rc;
1854 rc = read(client->command_fds[0], &buf[0] + rc, to_read);
1855 if (rc != to_read) {
1856 rc = -EIO;
1857 goto cmd_msg_complete;
1858 }
1859
1860 switch (msg->msg_id) {
1861 case CLIENT_STOP: {
1862 struct client_stream *s;
1863
1864 /* Stop all playing streams */
1865 DL_FOREACH(client->streams, s)
1866 client_thread_rm_stream(client, s->id);
1867
1868 /* And stop this client */
1869 client->thread.state = CRAS_THREAD_STOP;
1870 rc = 0;
1871 break;
1872 }
1873 case CLIENT_ADD_STREAM: {
1874 struct add_stream_command_message *add_msg =
1875 (struct add_stream_command_message *)msg;
1876 rc = client_thread_add_stream(client,
1877 add_msg->stream,
1878 add_msg->stream_id_out,
1879 add_msg->dev_idx);
1880 break;
1881 }
1882 case CLIENT_REMOVE_STREAM:
1883 rc = client_thread_rm_stream(client, msg->stream_id);
1884 break;
1885 case CLIENT_SET_STREAM_VOLUME_SCALER: {
1886 struct set_stream_volume_command_message *vol_msg =
1887 (struct set_stream_volume_command_message *)msg;
1888 rc = client_thread_set_stream_volume(client,
1889 vol_msg->header.stream_id,
1890 vol_msg->volume_scaler);
1891 break;
1892 }
1893 case CLIENT_SERVER_CONNECT:
1894 rc = connect_to_server_wait(client, false);
1895 break;
1896 case CLIENT_SERVER_CONNECT_ASYNC:
1897 rc = server_connect(client);
1898 break;
1899 default:
1900 assert(0);
1901 break;
1902 }
1903
1904 cmd_msg_complete:
1905 /* Wake the waiting main thread with the result of the command. */
1906 if (write(client->command_reply_fds[1], &rc, sizeof(rc)) != sizeof(rc))
1907 return -EIO;
1908 return rc;
1909 }
1910
1911 /* This thread handles non audio sample communication with the audio server.
1912 * The client program will call fucntions below to send messages to this thread
1913 * to add or remove streams or change parameters.
1914 */
client_thread(void * arg)1915 static void *client_thread(void *arg)
1916 {
1917 struct cras_client *client = (struct cras_client *)arg;
1918 struct pollfd pollfds[4];
1919 int (*cbs[4])(struct cras_client *client, int poll_revents);
1920 unsigned int num_pollfds, i;
1921 int rc;
1922
1923 if (arg == NULL)
1924 return (void *)-EINVAL;
1925
1926 while (thread_is_running(&client->thread)) {
1927 num_pollfds = 0;
1928
1929 rc = cras_file_wait_get_fd(client->sock_file_wait);
1930 if (rc >= 0) {
1931 cbs[num_pollfds] = sock_file_wait_dispatch;
1932 pollfds[num_pollfds].fd = rc;
1933 pollfds[num_pollfds].events = POLLIN;
1934 pollfds[num_pollfds].revents = 0;
1935 num_pollfds++;
1936 }
1937 else
1938 syslog(LOG_ERR, "file wait fd: %d", rc);
1939 if (client->server_fd >= 0) {
1940 cbs[num_pollfds] = server_fd_dispatch;
1941 server_fill_pollfd(client, &(pollfds[num_pollfds]));
1942 num_pollfds++;
1943 }
1944 if (client->command_fds[0] >= 0) {
1945 cbs[num_pollfds] = handle_command_message;
1946 pollfds[num_pollfds].fd = client->command_fds[0];
1947 pollfds[num_pollfds].events = POLLIN;
1948 pollfds[num_pollfds].revents = 0;
1949 num_pollfds++;
1950 }
1951 if (client->stream_fds[0] >= 0) {
1952 cbs[num_pollfds] = handle_stream_message;
1953 pollfds[num_pollfds].fd = client->stream_fds[0];
1954 pollfds[num_pollfds].events = POLLIN;
1955 pollfds[num_pollfds].revents = 0;
1956 num_pollfds++;
1957 }
1958
1959 rc = poll(pollfds, num_pollfds, -1);
1960 if (rc <= 0)
1961 continue;
1962
1963 for (i = 0; i < num_pollfds; i++) {
1964 /* Only do one at a time, since some messages may
1965 * result in change to other fds. */
1966 if (pollfds[i].revents) {
1967 cbs[i](client, pollfds[i].revents);
1968 break;
1969 }
1970 }
1971 }
1972
1973 /* close the command reply pipe. */
1974 close(client->command_reply_fds[1]);
1975 client->command_reply_fds[1] = -1;
1976
1977 return NULL;
1978 }
1979
1980 /* Sends a message to the client thread to complete an action requested by the
1981 * user. Then waits for the action to complete and returns the result. */
send_command_message(struct cras_client * client,struct command_msg * msg)1982 static int send_command_message(struct cras_client *client,
1983 struct command_msg *msg)
1984 {
1985 int rc, cmd_res;
1986 if (client == NULL || !thread_is_running(&client->thread))
1987 return -EINVAL;
1988
1989 rc = write(client->command_fds[1], msg, msg->len);
1990 if (rc != (int)msg->len)
1991 return -EPIPE;
1992
1993 /* Wait for command to complete. */
1994 rc = read(client->command_reply_fds[0], &cmd_res, sizeof(cmd_res));
1995 if (rc != sizeof(cmd_res))
1996 return -EPIPE;
1997 return cmd_res;
1998 }
1999
2000 /* Send a simple message to the client thread that holds no data. */
send_simple_cmd_msg(struct cras_client * client,cras_stream_id_t stream_id,unsigned msg_id)2001 static int send_simple_cmd_msg(struct cras_client *client,
2002 cras_stream_id_t stream_id,
2003 unsigned msg_id)
2004 {
2005 struct command_msg msg;
2006
2007 msg.len = sizeof(msg);
2008 msg.stream_id = stream_id;
2009 msg.msg_id = msg_id;
2010
2011 return send_command_message(client, &msg);
2012 }
2013
2014 /* Sends the set volume message to the client thread. */
send_stream_volume_command_msg(struct cras_client * client,cras_stream_id_t stream_id,float volume_scaler)2015 static int send_stream_volume_command_msg(struct cras_client *client,
2016 cras_stream_id_t stream_id,
2017 float volume_scaler)
2018 {
2019 struct set_stream_volume_command_message msg;
2020
2021 msg.header.len = sizeof(msg);
2022 msg.header.stream_id = stream_id;
2023 msg.header.msg_id = CLIENT_SET_STREAM_VOLUME_SCALER;
2024 msg.volume_scaler = volume_scaler;
2025
2026 return send_command_message(client, &msg.header);
2027 }
2028
2029 /* Sends a message back to the client and returns the error code. */
write_message_to_server(struct cras_client * client,const struct cras_server_message * msg)2030 static int write_message_to_server(struct cras_client *client,
2031 const struct cras_server_message *msg)
2032 {
2033 ssize_t write_rc = -EPIPE;
2034
2035 if (client->server_fd_state == CRAS_SOCKET_STATE_CONNECTED ||
2036 client->server_fd_state == CRAS_SOCKET_STATE_FIRST_MESSAGE) {
2037 write_rc = write(client->server_fd, msg, msg->length);
2038 if (write_rc < 0)
2039 write_rc = -errno;
2040 }
2041
2042 if (write_rc != (ssize_t)msg->length &&
2043 client->server_fd_state != CRAS_SOCKET_STATE_FIRST_MESSAGE)
2044 return -EPIPE;
2045
2046 if (write_rc < 0)
2047 return write_rc;
2048 else if (write_rc != (ssize_t)msg->length)
2049 return -EIO;
2050 else
2051 return 0;
2052 }
2053
2054 /*
2055 * Exported Client Interface
2056 */
2057
cras_client_create(struct cras_client ** client)2058 int cras_client_create(struct cras_client **client)
2059 {
2060 const char *sock_dir;
2061 size_t sock_file_size;
2062 int rc;
2063 struct client_int *client_int;
2064 pthread_condattr_t cond_attr;
2065
2066 /* Ignore SIGPIPE while using this API. */
2067 signal(SIGPIPE, SIG_IGN);
2068
2069 sock_dir = cras_config_get_system_socket_file_dir();
2070 if (!sock_dir)
2071 return -ENOMEM;
2072
2073 client_int = (struct client_int *)calloc(1, sizeof(*client_int));
2074 if (!client_int)
2075 return -ENOMEM;
2076 *client = &client_int->client;
2077 (*client)->server_fd = -1;
2078 (*client)->id = -1;
2079
2080 rc = pthread_rwlock_init(&client_int->server_state_rwlock, NULL);
2081 if (rc != 0) {
2082 syslog(LOG_ERR, "cras_client: Could not init state rwlock.");
2083 rc = -rc;
2084 goto free_client;
2085 }
2086
2087 rc = pthread_mutex_init(&(*client)->stream_start_lock, NULL);
2088 if (rc != 0) {
2089 syslog(LOG_ERR, "cras_client: Could not init start lock.");
2090 rc = -rc;
2091 goto free_rwlock;
2092 }
2093
2094 pthread_condattr_init(&cond_attr);
2095 pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
2096 rc = pthread_cond_init(&(*client)->stream_start_cond, &cond_attr);
2097 pthread_condattr_destroy(&cond_attr);
2098 if (rc != 0) {
2099 syslog(LOG_ERR, "cras_client: Could not init start cond.");
2100 rc = -rc;
2101 goto free_lock;
2102 }
2103
2104 (*client)->server_event_fd = eventfd(0, EFD_CLOEXEC|EFD_NONBLOCK);
2105 if ((*client)->server_event_fd < 0) {
2106 syslog(LOG_ERR, "cras_client: Could not setup server eventfd.");
2107 rc = -errno;
2108 goto free_cond;
2109 }
2110
2111 sock_file_size = strlen(sock_dir) + strlen(CRAS_SOCKET_FILE) + 2;
2112 (*client)->sock_file = (const char *)malloc(sock_file_size);
2113 if (!(*client)->sock_file) {
2114 rc = -ENOMEM;
2115 goto free_error;
2116 }
2117 snprintf((char *)(*client)->sock_file, sock_file_size, "%s/%s", sock_dir,
2118 CRAS_SOCKET_FILE);
2119
2120 rc = cras_file_wait_create((*client)->sock_file,
2121 CRAS_FILE_WAIT_FLAG_NONE,
2122 sock_file_wait_callback, *client,
2123 &(*client)->sock_file_wait);
2124 if (rc != 0 && rc != -ENOENT) {
2125 syslog(LOG_ERR, "cras_client: Could not setup watch for '%s'.",
2126 (*client)->sock_file);
2127 goto free_error;
2128 }
2129 (*client)->sock_file_exists = (rc == 0);
2130
2131 /* Pipes used by the main thread and the client thread to send commands
2132 * and replies. */
2133 rc = pipe((*client)->command_fds);
2134 if (rc < 0)
2135 goto free_error;
2136 /* Pipe used to communicate between the client thread and the audio
2137 * thread. */
2138 rc = pipe((*client)->stream_fds);
2139 if (rc < 0) {
2140 close((*client)->command_fds[0]);
2141 close((*client)->command_fds[1]);
2142 goto free_error;
2143 }
2144 (*client)->command_reply_fds[0] = -1;
2145 (*client)->command_reply_fds[1] = -1;
2146
2147 return 0;
2148 free_error:
2149 if ((*client)->server_event_fd >= 0)
2150 close((*client)->server_event_fd);
2151 cras_file_wait_destroy((*client)->sock_file_wait);
2152 free((void *)(*client)->sock_file);
2153 free_cond:
2154 pthread_cond_destroy(&(*client)->stream_start_cond);
2155 free_lock:
2156 pthread_mutex_destroy(&(*client)->stream_start_lock);
2157 free_rwlock:
2158 pthread_rwlock_destroy(&client_int->server_state_rwlock);
2159 free_client:
2160 *client = NULL;
2161 free(client_int);
2162 return rc;
2163 }
2164
cras_client_destroy(struct cras_client * client)2165 void cras_client_destroy(struct cras_client *client)
2166 {
2167 struct client_int *client_int;
2168 if (client == NULL)
2169 return;
2170 client_int = to_client_int(client);
2171 client->server_connection_cb = NULL;
2172 client->server_err_cb = NULL;
2173 cras_client_stop(client);
2174 server_disconnect(client);
2175 close(client->command_fds[0]);
2176 close(client->command_fds[1]);
2177 close(client->stream_fds[0]);
2178 close(client->stream_fds[1]);
2179 cras_file_wait_destroy(client->sock_file_wait);
2180 pthread_rwlock_destroy(&client_int->server_state_rwlock);
2181 free((void *)client->sock_file);
2182 free(client_int);
2183 }
2184
cras_client_connect(struct cras_client * client)2185 int cras_client_connect(struct cras_client *client)
2186 {
2187 return connect_to_server(client, NULL, true);
2188 }
2189
cras_client_connect_timeout(struct cras_client * client,unsigned int timeout_ms)2190 int cras_client_connect_timeout(struct cras_client *client,
2191 unsigned int timeout_ms)
2192 {
2193 return connect_to_server_wait_retry(client, timeout_ms, true);
2194 }
2195
cras_client_connected_wait(struct cras_client * client)2196 int cras_client_connected_wait(struct cras_client *client)
2197 {
2198 return send_simple_cmd_msg(client, 0, CLIENT_SERVER_CONNECT);
2199 }
2200
cras_client_connect_async(struct cras_client * client)2201 int cras_client_connect_async(struct cras_client *client)
2202 {
2203 return send_simple_cmd_msg(client, 0, CLIENT_SERVER_CONNECT_ASYNC);
2204 }
2205
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)2206 struct cras_stream_params *cras_client_stream_params_create(
2207 enum CRAS_STREAM_DIRECTION direction,
2208 size_t buffer_frames,
2209 size_t cb_threshold,
2210 size_t unused,
2211 enum CRAS_STREAM_TYPE stream_type,
2212 uint32_t flags,
2213 void *user_data,
2214 cras_playback_cb_t aud_cb,
2215 cras_error_cb_t err_cb,
2216 struct cras_audio_format *format)
2217 {
2218 struct cras_stream_params *params;
2219
2220 params = (struct cras_stream_params *)malloc(sizeof(*params));
2221 if (params == NULL)
2222 return NULL;
2223
2224 params->direction = direction;
2225 params->buffer_frames = buffer_frames;
2226 params->cb_threshold = cb_threshold;
2227
2228 params->stream_type = stream_type;
2229 params->flags = flags;
2230 params->user_data = user_data;
2231 params->aud_cb = aud_cb;
2232 params->unified_cb = 0;
2233 params->err_cb = err_cb;
2234 memcpy(&(params->format), format, sizeof(*format));
2235 return params;
2236 }
2237
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)2238 struct cras_stream_params *cras_client_unified_params_create(
2239 enum CRAS_STREAM_DIRECTION direction,
2240 unsigned int block_size,
2241 enum CRAS_STREAM_TYPE stream_type,
2242 uint32_t flags,
2243 void *user_data,
2244 cras_unified_cb_t unified_cb,
2245 cras_error_cb_t err_cb,
2246 struct cras_audio_format *format)
2247 {
2248 struct cras_stream_params *params;
2249
2250 params = (struct cras_stream_params *)malloc(sizeof(*params));
2251 if (params == NULL)
2252 return NULL;
2253
2254 params->direction = direction;
2255 params->buffer_frames = block_size * 2;
2256 params->cb_threshold = block_size;
2257 params->stream_type = stream_type;
2258 params->flags = flags;
2259 params->user_data = user_data;
2260 params->aud_cb = 0;
2261 params->unified_cb = unified_cb;
2262 params->err_cb = err_cb;
2263 memcpy(&(params->format), format, sizeof(*format));
2264
2265 return params;
2266 }
2267
cras_client_stream_params_destroy(struct cras_stream_params * params)2268 void cras_client_stream_params_destroy(struct cras_stream_params *params)
2269 {
2270 free(params);
2271 }
2272
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)2273 static inline int cras_client_send_add_stream_command_message(
2274 struct cras_client *client,
2275 uint32_t dev_idx,
2276 cras_stream_id_t *stream_id_out,
2277 struct cras_stream_params *config)
2278 {
2279 struct add_stream_command_message cmd_msg;
2280 struct client_stream *stream;
2281 int rc = 0;
2282
2283 if (client == NULL || config == NULL || stream_id_out == NULL)
2284 return -EINVAL;
2285
2286 if (config->aud_cb == NULL && config->unified_cb == NULL)
2287 return -EINVAL;
2288
2289 if (config->err_cb == NULL)
2290 return -EINVAL;
2291
2292 stream = (struct client_stream *)calloc(1, sizeof(*stream));
2293 if (stream == NULL) {
2294 rc = -ENOMEM;
2295 goto add_failed;
2296 }
2297 stream->config = (struct cras_stream_params *)
2298 malloc(sizeof(*(stream->config)));
2299 if (stream->config == NULL) {
2300 rc = -ENOMEM;
2301 goto add_failed;
2302 }
2303 memcpy(stream->config, config, sizeof(*config));
2304 stream->aud_fd = -1;
2305 stream->wake_fds[0] = -1;
2306 stream->wake_fds[1] = -1;
2307 stream->direction = config->direction;
2308 stream->volume_scaler = 1.0;
2309 stream->flags = config->flags;
2310
2311 cmd_msg.header.len = sizeof(cmd_msg);
2312 cmd_msg.header.msg_id = CLIENT_ADD_STREAM;
2313 cmd_msg.header.stream_id = stream->id;
2314 cmd_msg.stream = stream;
2315 cmd_msg.stream_id_out = stream_id_out;
2316 cmd_msg.dev_idx = dev_idx;
2317 rc = send_command_message(client, &cmd_msg.header);
2318 if (rc < 0) {
2319 syslog(LOG_ERR,
2320 "cras_client: adding stream failed in thread %d", rc);
2321 goto add_failed;
2322 }
2323
2324 return 0;
2325
2326 add_failed:
2327 if (stream) {
2328 if (stream->config)
2329 free(stream->config);
2330 free(stream);
2331 }
2332 return rc;
2333 }
2334
cras_client_add_stream(struct cras_client * client,cras_stream_id_t * stream_id_out,struct cras_stream_params * config)2335 int cras_client_add_stream(struct cras_client *client,
2336 cras_stream_id_t *stream_id_out,
2337 struct cras_stream_params *config)
2338 {
2339 return cras_client_send_add_stream_command_message(
2340 client,
2341 NO_DEVICE,
2342 stream_id_out,
2343 config);
2344 }
2345
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)2346 int cras_client_add_pinned_stream(struct cras_client *client,
2347 uint32_t dev_idx,
2348 cras_stream_id_t *stream_id_out,
2349 struct cras_stream_params *config)
2350 {
2351 return cras_client_send_add_stream_command_message(
2352 client,
2353 dev_idx,
2354 stream_id_out,
2355 config);
2356 }
2357
cras_client_rm_stream(struct cras_client * client,cras_stream_id_t stream_id)2358 int cras_client_rm_stream(struct cras_client *client,
2359 cras_stream_id_t stream_id)
2360 {
2361 if (client == NULL)
2362 return -EINVAL;
2363
2364 return send_simple_cmd_msg(client, stream_id, CLIENT_REMOVE_STREAM);
2365 }
2366
cras_client_set_stream_volume(struct cras_client * client,cras_stream_id_t stream_id,float volume_scaler)2367 int cras_client_set_stream_volume(struct cras_client *client,
2368 cras_stream_id_t stream_id,
2369 float volume_scaler)
2370 {
2371 if (client == NULL)
2372 return -EINVAL;
2373
2374 return send_stream_volume_command_msg(client, stream_id, volume_scaler);
2375 }
2376
cras_client_set_system_volume(struct cras_client * client,size_t volume)2377 int cras_client_set_system_volume(struct cras_client *client, size_t volume)
2378 {
2379 struct cras_set_system_volume msg;
2380
2381 if (client == NULL)
2382 return -EINVAL;
2383
2384 cras_fill_set_system_volume(&msg, volume);
2385 return write_message_to_server(client, &msg.header);
2386 }
2387
cras_client_set_system_capture_gain(struct cras_client * client,long gain)2388 int cras_client_set_system_capture_gain(struct cras_client *client, long gain)
2389 {
2390 struct cras_set_system_capture_gain msg;
2391
2392 if (client == NULL)
2393 return -EINVAL;
2394
2395 cras_fill_set_system_capture_gain(&msg, gain);
2396 return write_message_to_server(client, &msg.header);
2397 }
2398
cras_client_set_system_mute(struct cras_client * client,int mute)2399 int cras_client_set_system_mute(struct cras_client *client, int mute)
2400 {
2401 struct cras_set_system_mute msg;
2402
2403 if (client == NULL)
2404 return -EINVAL;
2405
2406 cras_fill_set_system_mute(&msg, mute);
2407 return write_message_to_server(client, &msg.header);
2408 }
2409
cras_client_set_user_mute(struct cras_client * client,int mute)2410 int cras_client_set_user_mute(struct cras_client *client, int mute)
2411 {
2412 struct cras_set_system_mute msg;
2413
2414 if (client == NULL)
2415 return -EINVAL;
2416
2417 cras_fill_set_user_mute(&msg, mute);
2418 return write_message_to_server(client, &msg.header);
2419 }
2420
cras_client_set_system_mute_locked(struct cras_client * client,int locked)2421 int cras_client_set_system_mute_locked(struct cras_client *client, int locked)
2422 {
2423 struct cras_set_system_mute msg;
2424
2425 if (client == NULL)
2426 return -EINVAL;
2427
2428 cras_fill_set_system_mute_locked(&msg, locked);
2429 return write_message_to_server(client, &msg.header);
2430 }
2431
cras_client_set_system_capture_mute(struct cras_client * client,int mute)2432 int cras_client_set_system_capture_mute(struct cras_client *client, int mute)
2433 {
2434 struct cras_set_system_mute msg;
2435
2436 if (client == NULL)
2437 return -EINVAL;
2438
2439 cras_fill_set_system_capture_mute(&msg, mute);
2440 return write_message_to_server(client, &msg.header);
2441 }
2442
cras_client_set_system_capture_mute_locked(struct cras_client * client,int locked)2443 int cras_client_set_system_capture_mute_locked(struct cras_client *client,
2444 int locked)
2445 {
2446 struct cras_set_system_mute msg;
2447
2448 if (client == NULL)
2449 return -EINVAL;
2450
2451 cras_fill_set_system_capture_mute_locked(&msg, locked);
2452 return write_message_to_server(client, &msg.header);
2453 }
2454
cras_client_get_system_volume(const struct cras_client * client)2455 size_t cras_client_get_system_volume(const struct cras_client *client)
2456 {
2457 size_t volume;
2458 int lock_rc;
2459
2460 lock_rc = server_state_rdlock(client);
2461 if (lock_rc)
2462 return 0;
2463
2464 volume = client->server_state->volume;
2465 server_state_unlock(client, lock_rc);
2466 return volume;
2467 }
2468
cras_client_get_system_capture_gain(const struct cras_client * client)2469 long cras_client_get_system_capture_gain(const struct cras_client *client)
2470 {
2471 long gain;
2472 int lock_rc;
2473
2474 lock_rc = server_state_rdlock(client);
2475 if (lock_rc)
2476 return 0;
2477
2478 gain = client->server_state->capture_gain;
2479 server_state_unlock(client, lock_rc);
2480 return gain;
2481 }
2482
cras_client_get_system_muted(const struct cras_client * client)2483 int cras_client_get_system_muted(const struct cras_client *client)
2484 {
2485 int muted;
2486 int lock_rc;
2487
2488 lock_rc = server_state_rdlock(client);
2489 if (lock_rc)
2490 return 0;
2491
2492 muted = client->server_state->mute;
2493 server_state_unlock(client, lock_rc);
2494 return muted;
2495 }
2496
cras_client_get_user_muted(const struct cras_client * client)2497 int cras_client_get_user_muted(const struct cras_client *client)
2498 {
2499 int muted;
2500 int lock_rc;
2501
2502 lock_rc = server_state_rdlock(client);
2503 if (lock_rc)
2504 return 0;
2505
2506 muted = client->server_state->user_mute;
2507 server_state_unlock(client, lock_rc);
2508 return muted;
2509 }
2510
cras_client_get_system_capture_muted(const struct cras_client * client)2511 int cras_client_get_system_capture_muted(const struct cras_client *client)
2512 {
2513 int muted;
2514 int lock_rc;
2515
2516 lock_rc = server_state_rdlock(client);
2517 if (lock_rc)
2518 return 0;
2519
2520 muted = client->server_state->capture_mute;
2521 server_state_unlock(client, lock_rc);
2522 return muted;
2523 }
2524
cras_client_get_system_min_volume(const struct cras_client * client)2525 long cras_client_get_system_min_volume(const struct cras_client *client)
2526 {
2527 long min_volume;
2528 int lock_rc;
2529
2530 lock_rc = server_state_rdlock(client);
2531 if (lock_rc)
2532 return 0;
2533
2534 min_volume = client->server_state->min_volume_dBFS;
2535 server_state_unlock(client, lock_rc);
2536 return min_volume;
2537 }
2538
cras_client_get_system_max_volume(const struct cras_client * client)2539 long cras_client_get_system_max_volume(const struct cras_client *client)
2540 {
2541 long max_volume;
2542 int lock_rc;
2543
2544 lock_rc = server_state_rdlock(client);
2545 if (lock_rc)
2546 return 0;
2547
2548 max_volume = client->server_state->max_volume_dBFS;
2549 server_state_unlock(client, lock_rc);
2550 return max_volume;
2551 }
2552
cras_client_get_system_min_capture_gain(const struct cras_client * client)2553 long cras_client_get_system_min_capture_gain(const struct cras_client *client)
2554 {
2555 long min_gain;
2556 int lock_rc;
2557
2558 lock_rc = server_state_rdlock(client);
2559 if (lock_rc)
2560 return 0;
2561
2562 min_gain = client->server_state->min_capture_gain;
2563 server_state_unlock(client, lock_rc);
2564 return min_gain;
2565 }
2566
cras_client_get_system_max_capture_gain(const struct cras_client * client)2567 long cras_client_get_system_max_capture_gain(const struct cras_client *client)
2568 {
2569 long max_gain;
2570 int lock_rc;
2571
2572 lock_rc = server_state_rdlock(client);
2573 if (lock_rc)
2574 return 0;
2575
2576 max_gain = client->server_state->max_capture_gain;
2577 server_state_unlock(client, lock_rc);
2578 return max_gain;
2579 }
2580
cras_client_get_audio_debug_info(const struct cras_client * client)2581 const struct audio_debug_info *cras_client_get_audio_debug_info(
2582 const struct cras_client *client)
2583 {
2584 const struct audio_debug_info *debug_info;
2585 int lock_rc;
2586
2587 lock_rc = server_state_rdlock(client);
2588 if (lock_rc)
2589 return 0;
2590
2591 debug_info = &client->server_state->audio_debug_info;
2592 server_state_unlock(client, lock_rc);
2593 return debug_info;
2594 }
2595
cras_client_get_num_active_streams(const struct cras_client * client,struct timespec * ts)2596 unsigned cras_client_get_num_active_streams(const struct cras_client *client,
2597 struct timespec *ts)
2598 {
2599 unsigned num_streams, version, i;
2600 int lock_rc;
2601
2602 lock_rc = server_state_rdlock(client);
2603 if (lock_rc)
2604 return 0;
2605
2606 read_active_streams_again:
2607 version = begin_server_state_read(client->server_state);
2608 num_streams = 0;
2609 for (i = 0; i < CRAS_NUM_DIRECTIONS; i++)
2610 num_streams += client->server_state->num_active_streams[i];
2611 if (ts) {
2612 if (num_streams)
2613 clock_gettime(CLOCK_MONOTONIC_RAW, ts);
2614 else
2615 cras_timespec_to_timespec(ts,
2616 &client->server_state->last_active_stream_time);
2617 }
2618 if (end_server_state_read(client->server_state, version))
2619 goto read_active_streams_again;
2620
2621 server_state_unlock(client, lock_rc);
2622 return num_streams;
2623 }
2624
cras_client_run_thread(struct cras_client * client)2625 int cras_client_run_thread(struct cras_client *client)
2626 {
2627 int rc;
2628
2629 if (client == NULL)
2630 return -EINVAL;
2631 if (thread_is_running(&client->thread))
2632 return 0;
2633
2634 assert(client->command_reply_fds[0] == -1 &&
2635 client->command_reply_fds[1] == -1);
2636
2637 if (pipe(client->command_reply_fds) < 0)
2638 return -EIO;
2639 client->thread.state = CRAS_THREAD_RUNNING;
2640 rc = pthread_create(&client->thread.tid, NULL, client_thread, client);
2641 if (rc) {
2642 client->thread.state = CRAS_THREAD_STOP;
2643 return -rc;
2644 }
2645
2646 return 0;
2647 }
2648
cras_client_stop(struct cras_client * client)2649 int cras_client_stop(struct cras_client *client)
2650 {
2651 if (client == NULL)
2652 return -EINVAL;
2653 if (!thread_is_running(&client->thread))
2654 return 0;
2655
2656 send_simple_cmd_msg(client, 0, CLIENT_STOP);
2657 pthread_join(client->thread.tid, NULL);
2658
2659 /* The other end of the reply pipe is closed by the client thread, just
2660 * clost the read end here. */
2661 close(client->command_reply_fds[0]);
2662 client->command_reply_fds[0] = -1;
2663
2664 return 0;
2665 }
2666
cras_client_set_server_error_cb(struct cras_client * client,cras_server_error_cb_t err_cb,void * user_arg)2667 void cras_client_set_server_error_cb(struct cras_client *client,
2668 cras_server_error_cb_t err_cb,
2669 void *user_arg)
2670 {
2671 client->server_err_cb = err_cb;
2672 client->server_connection_user_arg = user_arg;
2673 }
2674
cras_client_set_connection_status_cb(struct cras_client * client,cras_connection_status_cb_t connection_cb,void * user_arg)2675 void cras_client_set_connection_status_cb(
2676 struct cras_client *client,
2677 cras_connection_status_cb_t connection_cb,
2678 void *user_arg)
2679 {
2680 client->server_connection_cb = connection_cb;
2681 client->server_connection_user_arg = user_arg;
2682 }
2683
cras_client_set_thread_priority_cb(struct cras_client * client,cras_thread_priority_cb_t cb)2684 void cras_client_set_thread_priority_cb(struct cras_client *client,
2685 cras_thread_priority_cb_t cb)
2686 {
2687 client->thread_priority_cb = cb;
2688 }
2689
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)2690 int cras_client_get_output_devices(const struct cras_client *client,
2691 struct cras_iodev_info *devs,
2692 struct cras_ionode_info *nodes,
2693 size_t *num_devs, size_t *num_nodes)
2694 {
2695 const struct cras_server_state *state;
2696 unsigned avail_devs, avail_nodes, version;
2697 int lock_rc;
2698
2699 lock_rc = server_state_rdlock(client);
2700 if (lock_rc)
2701 return -EINVAL;
2702 state = client->server_state;
2703
2704 read_outputs_again:
2705 version = begin_server_state_read(state);
2706 avail_devs = MIN(*num_devs, state->num_output_devs);
2707 memcpy(devs, state->output_devs, avail_devs * sizeof(*devs));
2708 avail_nodes = MIN(*num_nodes, state->num_output_nodes);
2709 memcpy(nodes, state->output_nodes, avail_nodes * sizeof(*nodes));
2710 if (end_server_state_read(state, version))
2711 goto read_outputs_again;
2712 server_state_unlock(client, lock_rc);
2713
2714 *num_devs = avail_devs;
2715 *num_nodes = avail_nodes;
2716
2717 return 0;
2718 }
2719
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)2720 int cras_client_get_input_devices(const struct cras_client *client,
2721 struct cras_iodev_info *devs,
2722 struct cras_ionode_info *nodes,
2723 size_t *num_devs, size_t *num_nodes)
2724 {
2725 const struct cras_server_state *state;
2726 unsigned avail_devs, avail_nodes, version;
2727 int lock_rc;
2728
2729 lock_rc = server_state_rdlock(client);
2730 if (!client)
2731 return -EINVAL;
2732 state = client->server_state;
2733
2734 read_inputs_again:
2735 version = begin_server_state_read(state);
2736 avail_devs = MIN(*num_devs, state->num_input_devs);
2737 memcpy(devs, state->input_devs, avail_devs * sizeof(*devs));
2738 avail_nodes = MIN(*num_nodes, state->num_input_nodes);
2739 memcpy(nodes, state->input_nodes, avail_nodes * sizeof(*nodes));
2740 if (end_server_state_read(state, version))
2741 goto read_inputs_again;
2742 server_state_unlock(client, lock_rc);
2743
2744 *num_devs = avail_devs;
2745 *num_nodes = avail_nodes;
2746
2747 return 0;
2748 }
2749
cras_client_get_attached_clients(const struct cras_client * client,struct cras_attached_client_info * clients,size_t max_clients)2750 int cras_client_get_attached_clients(const struct cras_client *client,
2751 struct cras_attached_client_info *clients,
2752 size_t max_clients)
2753 {
2754 const struct cras_server_state *state;
2755 unsigned num, version;
2756 int lock_rc;
2757
2758 lock_rc = server_state_rdlock(client);
2759 if (lock_rc)
2760 return -EINVAL;
2761 state = client->server_state;
2762
2763 read_clients_again:
2764 version = begin_server_state_read(state);
2765 num = MIN(max_clients, state->num_attached_clients);
2766 memcpy(clients, state->client_info, num * sizeof(*clients));
2767 if (end_server_state_read(state, version))
2768 goto read_clients_again;
2769 server_state_unlock(client, lock_rc);
2770
2771 return num;
2772 }
2773
2774 /* Find an output ionode on an iodev with the matching name.
2775 *
2776 * Args:
2777 * dev_name - The prefix of the iodev name.
2778 * node_name - The prefix of the ionode name.
2779 * dev_info - The information about the iodev will be returned here.
2780 * node_info - The information about the ionode will be returned here.
2781 * Returns:
2782 * 0 if successful, -1 if the node cannot be found.
2783 */
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)2784 static int cras_client_find_output_node(const struct cras_client *client,
2785 const char *dev_name,
2786 const char *node_name,
2787 struct cras_iodev_info *dev_info,
2788 struct cras_ionode_info *node_info)
2789 {
2790 size_t ndevs, nnodes;
2791 struct cras_iodev_info *devs = NULL;
2792 struct cras_ionode_info *nodes = NULL;
2793 int rc = -1;
2794 unsigned i, j;
2795
2796 if (!client || !dev_name || !node_name)
2797 goto quit;
2798
2799 devs = (struct cras_iodev_info *)
2800 malloc(CRAS_MAX_IODEVS * sizeof(*devs));
2801 if (!devs)
2802 goto quit;
2803
2804 nodes = (struct cras_ionode_info *)
2805 malloc(CRAS_MAX_IONODES * sizeof(*nodes));
2806 if (!nodes)
2807 goto quit;
2808
2809 ndevs = CRAS_MAX_IODEVS;
2810 nnodes = CRAS_MAX_IONODES;
2811 rc = cras_client_get_output_devices(client, devs, nodes, &ndevs,
2812 &nnodes);
2813 if (rc < 0)
2814 goto quit;
2815
2816 for (i = 0; i < ndevs; i++)
2817 if (!strncmp(dev_name, devs[i].name, strlen(dev_name)))
2818 goto found_dev;
2819 rc = -1;
2820 goto quit;
2821
2822 found_dev:
2823 for (j = 0; j < nnodes; j++)
2824 if (nodes[j].iodev_idx == devs[i].idx &&
2825 !strncmp(node_name, nodes[j].name, strlen(node_name)))
2826 goto found_node;
2827 rc = -1;
2828 goto quit;
2829
2830 found_node:
2831 *dev_info = devs[i];
2832 *node_info = nodes[j];
2833 rc = 0;
2834
2835 quit:
2836 free(devs);
2837 free(nodes);
2838 return rc;
2839 }
2840
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)2841 int cras_client_get_node_by_id(const struct cras_client *client,
2842 int input,
2843 const cras_node_id_t node_id,
2844 struct cras_ionode_info* node_info)
2845 {
2846 size_t ndevs, nnodes;
2847 struct cras_iodev_info *devs = NULL;
2848 struct cras_ionode_info *nodes = NULL;
2849 int rc = -EINVAL;
2850 unsigned i;
2851
2852 if (!client || !node_info) {
2853 rc = -EINVAL;
2854 goto quit;
2855 }
2856
2857 devs = (struct cras_iodev_info *)
2858 malloc(CRAS_MAX_IODEVS * sizeof(*devs));
2859 if (!devs) {
2860 rc = -ENOMEM;
2861 goto quit;
2862 }
2863
2864 nodes = (struct cras_ionode_info *)
2865 malloc(CRAS_MAX_IONODES * sizeof(*nodes));
2866 if (!nodes) {
2867 rc = -ENOMEM;
2868 goto quit;
2869 }
2870
2871 ndevs = CRAS_MAX_IODEVS;
2872 nnodes = CRAS_MAX_IONODES;
2873 if (input)
2874 rc = cras_client_get_input_devices(client, devs, nodes,
2875 &ndevs, &nnodes);
2876 else
2877 rc = cras_client_get_output_devices(client, devs, nodes,
2878 &ndevs, &nnodes);
2879 if (rc < 0)
2880 goto quit;
2881
2882 rc = -ENOENT;
2883 for (i = 0; i < nnodes; i++) {
2884 if (node_id == cras_make_node_id(nodes[i].iodev_idx,
2885 nodes[i].ionode_idx)) {
2886 memcpy(node_info, &nodes[i], sizeof(*node_info));
2887 rc = 0;
2888 break;
2889 }
2890 }
2891
2892 quit:
2893 free(devs);
2894 free(nodes);
2895 return rc;
2896 }
2897
cras_client_output_dev_plugged(const struct cras_client * client,const char * name)2898 int cras_client_output_dev_plugged(const struct cras_client *client,
2899 const char *name)
2900 {
2901 struct cras_iodev_info dev_info;
2902 struct cras_ionode_info node_info = { 0 };
2903
2904 if (cras_client_find_output_node(client, name, "Front Headphone Jack",
2905 &dev_info, &node_info) < 0)
2906 return 0;
2907
2908 return node_info.plugged;
2909 }
2910
cras_client_set_node_attr(struct cras_client * client,cras_node_id_t node_id,enum ionode_attr attr,int value)2911 int cras_client_set_node_attr(struct cras_client *client,
2912 cras_node_id_t node_id,
2913 enum ionode_attr attr, int value)
2914 {
2915 struct cras_set_node_attr msg;
2916
2917 if (client == NULL)
2918 return -EINVAL;
2919
2920 cras_fill_set_node_attr(&msg, node_id, attr, value);
2921 return write_message_to_server(client, &msg.header);
2922 }
2923
cras_client_select_node(struct cras_client * client,enum CRAS_STREAM_DIRECTION direction,cras_node_id_t node_id)2924 int cras_client_select_node(struct cras_client *client,
2925 enum CRAS_STREAM_DIRECTION direction,
2926 cras_node_id_t node_id)
2927 {
2928 struct cras_select_node msg;
2929
2930 if (client == NULL)
2931 return -EINVAL;
2932
2933 cras_fill_select_node(&msg, direction, node_id);
2934 return write_message_to_server(client, &msg.header);
2935 }
2936
cras_client_add_active_node(struct cras_client * client,enum CRAS_STREAM_DIRECTION direction,cras_node_id_t node_id)2937 int cras_client_add_active_node(struct cras_client *client,
2938 enum CRAS_STREAM_DIRECTION direction,
2939 cras_node_id_t node_id)
2940 {
2941 struct cras_add_active_node msg;
2942
2943 if (client == NULL)
2944 return -EINVAL;
2945
2946 cras_fill_add_active_node(&msg, direction, node_id);
2947 return write_message_to_server(client, &msg.header);
2948 }
2949
cras_client_rm_active_node(struct cras_client * client,enum CRAS_STREAM_DIRECTION direction,cras_node_id_t node_id)2950 int cras_client_rm_active_node(struct cras_client *client,
2951 enum CRAS_STREAM_DIRECTION direction,
2952 cras_node_id_t node_id)
2953 {
2954 struct cras_rm_active_node msg;
2955
2956 if (client == NULL)
2957 return -EINVAL;
2958
2959 cras_fill_rm_active_node(&msg, direction, node_id);
2960 return write_message_to_server(client, &msg.header);
2961 }
2962
cras_client_format_bytes_per_frame(struct cras_audio_format * fmt)2963 int cras_client_format_bytes_per_frame(struct cras_audio_format *fmt)
2964 {
2965 if (fmt == NULL)
2966 return -EINVAL;
2967
2968 return cras_get_format_bytes(fmt);
2969 }
2970
cras_client_calc_playback_latency(const struct timespec * sample_time,struct timespec * delay)2971 int cras_client_calc_playback_latency(const struct timespec *sample_time,
2972 struct timespec *delay)
2973 {
2974 struct timespec now;
2975
2976 if (delay == NULL)
2977 return -EINVAL;
2978
2979 clock_gettime(CLOCK_MONOTONIC_RAW, &now);
2980
2981 /* for output return time until sample is played (t - now) */
2982 subtract_timespecs(sample_time, &now, delay);
2983 return 0;
2984 }
2985
cras_client_calc_capture_latency(const struct timespec * sample_time,struct timespec * delay)2986 int cras_client_calc_capture_latency(const struct timespec *sample_time,
2987 struct timespec *delay)
2988 {
2989 struct timespec now;
2990
2991 if (delay == NULL)
2992 return -EINVAL;
2993
2994 clock_gettime(CLOCK_MONOTONIC_RAW, &now);
2995
2996 /* For input want time since sample read (now - t) */
2997 subtract_timespecs(&now, sample_time, delay);
2998 return 0;
2999 }
3000
cras_client_reload_dsp(struct cras_client * client)3001 int cras_client_reload_dsp(struct cras_client *client)
3002 {
3003 struct cras_reload_dsp msg;
3004
3005 if (client == NULL)
3006 return -EINVAL;
3007
3008 cras_fill_reload_dsp(&msg);
3009 return write_message_to_server(client, &msg.header);
3010 }
3011
cras_client_dump_dsp_info(struct cras_client * client)3012 int cras_client_dump_dsp_info(struct cras_client *client)
3013 {
3014 struct cras_dump_dsp_info msg;
3015
3016 if (client == NULL)
3017 return -EINVAL;
3018
3019 cras_fill_dump_dsp_info(&msg);
3020 return write_message_to_server(client, &msg.header);
3021 }
3022
cras_client_update_audio_debug_info(struct cras_client * client,void (* debug_info_cb)(struct cras_client *))3023 int cras_client_update_audio_debug_info(
3024 struct cras_client *client,
3025 void (*debug_info_cb)(struct cras_client *))
3026 {
3027 struct cras_dump_audio_thread msg;
3028
3029 if (client == NULL)
3030 return -EINVAL;
3031
3032 client->debug_info_callback = debug_info_cb;
3033
3034 cras_fill_dump_audio_thread(&msg);
3035 return write_message_to_server(client, &msg.header);
3036 }
3037
cras_client_set_node_volume(struct cras_client * client,cras_node_id_t node_id,uint8_t volume)3038 int cras_client_set_node_volume(struct cras_client *client,
3039 cras_node_id_t node_id,
3040 uint8_t volume)
3041 {
3042 struct cras_set_node_attr msg;
3043
3044 if (client == NULL)
3045 return -EINVAL;
3046
3047 cras_fill_set_node_attr(&msg, node_id, IONODE_ATTR_VOLUME, volume);
3048 return write_message_to_server(client, &msg.header);
3049 }
3050
cras_client_swap_node_left_right(struct cras_client * client,cras_node_id_t node_id,int enable)3051 int cras_client_swap_node_left_right(struct cras_client *client,
3052 cras_node_id_t node_id, int enable)
3053 {
3054 struct cras_set_node_attr msg;
3055
3056 if (client == NULL)
3057 return -EINVAL;
3058
3059 cras_fill_set_node_attr(&msg, node_id, IONODE_ATTR_SWAP_LEFT_RIGHT,
3060 enable);
3061 return write_message_to_server(client, &msg.header);
3062 }
3063
cras_client_set_node_capture_gain(struct cras_client * client,cras_node_id_t node_id,long gain)3064 int cras_client_set_node_capture_gain(struct cras_client *client,
3065 cras_node_id_t node_id,
3066 long gain)
3067 {
3068 struct cras_set_node_attr msg;
3069
3070 if (client == NULL)
3071 return -EINVAL;
3072 if (gain > INT_MAX || gain < INT_MIN)
3073 return -EINVAL;
3074
3075 cras_fill_set_node_attr(&msg, node_id, IONODE_ATTR_CAPTURE_GAIN, gain);
3076 return write_message_to_server(client, &msg.header);
3077 }
3078
cras_client_add_test_iodev(struct cras_client * client,enum TEST_IODEV_TYPE type)3079 int cras_client_add_test_iodev(struct cras_client *client,
3080 enum TEST_IODEV_TYPE type)
3081 {
3082 struct cras_add_test_dev msg;
3083
3084 cras_fill_add_test_dev(&msg, type);
3085 return write_message_to_server(client, &msg.header);
3086 }
3087
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)3088 int cras_client_test_iodev_command(struct cras_client *client,
3089 unsigned int iodev_idx,
3090 enum CRAS_TEST_IODEV_CMD command,
3091 unsigned int data_len,
3092 const uint8_t *data)
3093 {
3094 struct cras_test_dev_command *msg;
3095 int rc;
3096
3097 msg = (struct cras_test_dev_command *)malloc(sizeof(*msg) + data_len);
3098 cras_fill_test_dev_command(msg, iodev_idx, command, data_len, data);
3099 rc = write_message_to_server(client, &msg->header);
3100 free(msg);
3101 return rc;
3102 }
3103
cras_client_config_global_remix(struct cras_client * client,unsigned num_channels,float * coefficient)3104 int cras_client_config_global_remix(struct cras_client *client,
3105 unsigned num_channels,
3106 float *coefficient)
3107 {
3108 struct cras_config_global_remix *msg;
3109 int rc;
3110
3111 msg = (struct cras_config_global_remix *)malloc(sizeof(*msg) +
3112 num_channels * num_channels * sizeof(*coefficient));
3113 cras_fill_config_global_remix_command(msg, num_channels,
3114 coefficient,
3115 num_channels * num_channels);
3116 rc = write_message_to_server(client, &msg->header);
3117 free(msg);
3118 return rc;
3119 }
3120
3121 /* Return the index of the device used for listening to hotwords. */
cras_client_get_first_dev_type_idx(const struct cras_client * client,enum CRAS_NODE_TYPE type,enum CRAS_STREAM_DIRECTION direction)3122 int cras_client_get_first_dev_type_idx(const struct cras_client *client,
3123 enum CRAS_NODE_TYPE type,
3124 enum CRAS_STREAM_DIRECTION direction)
3125 {
3126 const struct cras_server_state *state;
3127 unsigned int version;
3128 unsigned int i;
3129 const struct cras_ionode_info *node_list;
3130 unsigned int num_nodes;
3131 int lock_rc;
3132
3133 lock_rc = server_state_rdlock(client);
3134 if (lock_rc)
3135 return -EINVAL;
3136 state = client->server_state;
3137
3138 read_nodes_again:
3139 version = begin_server_state_read(state);
3140 if (direction == CRAS_STREAM_OUTPUT) {
3141 node_list = state->output_nodes;
3142 num_nodes = state->num_output_nodes;
3143 } else {
3144 node_list = state->input_nodes;
3145 num_nodes = state->num_input_nodes;
3146 }
3147 for (i = 0; i < num_nodes; i++) {
3148 if ((enum CRAS_NODE_TYPE)node_list[i].type_enum == type) {
3149 int ret_idx = node_list[i].iodev_idx;
3150 server_state_unlock(client, lock_rc);
3151 return ret_idx;
3152 }
3153 }
3154 if (end_server_state_read(state, version))
3155 goto read_nodes_again;
3156 server_state_unlock(client, lock_rc);
3157
3158 return -ENODEV;
3159 }
3160
cras_client_set_suspend(struct cras_client * client,int suspend)3161 int cras_client_set_suspend(struct cras_client *client, int suspend)
3162 {
3163 struct cras_server_message msg;
3164
3165 cras_fill_suspend_message(&msg, suspend);
3166 return write_message_to_server(client, &msg);
3167 }
3168
cras_client_get_hotword_models(struct cras_client * client,cras_node_id_t node_id,get_hotword_models_cb_t cb)3169 int cras_client_get_hotword_models(struct cras_client *client,
3170 cras_node_id_t node_id,
3171 get_hotword_models_cb_t cb)
3172 {
3173 struct cras_get_hotword_models msg;
3174
3175 if (!client)
3176 return -EINVAL;
3177 client->get_hotword_models_cb = cb;
3178
3179 cras_fill_get_hotword_models_message(&msg, node_id);
3180 return write_message_to_server(client, &msg.header);
3181 }
3182
cras_client_set_hotword_model(struct cras_client * client,cras_node_id_t node_id,const char * model_name)3183 int cras_client_set_hotword_model(struct cras_client *client,
3184 cras_node_id_t node_id,
3185 const char *model_name)
3186 {
3187 struct cras_set_hotword_model msg;
3188
3189 cras_fill_set_hotword_model_message(&msg, node_id, model_name);
3190 return write_message_to_server(client, &msg.header);
3191 }
3192
cras_client_set_state_change_callback_context(struct cras_client * client,void * context)3193 void cras_client_set_state_change_callback_context(
3194 struct cras_client *client, void *context)
3195 {
3196 if (!client)
3197 return;
3198 client->observer_context = context;
3199 }
3200
cras_send_register_notification(struct cras_client * client,enum CRAS_CLIENT_MESSAGE_ID msg_id,int do_register)3201 static int cras_send_register_notification(struct cras_client *client,
3202 enum CRAS_CLIENT_MESSAGE_ID msg_id,
3203 int do_register)
3204 {
3205 struct cras_register_notification msg;
3206 int rc;
3207
3208 /* This library automatically re-registers notifications when
3209 * reconnecting, so we can ignore message send failure due to no
3210 * connection. */
3211 cras_fill_register_notification_message(&msg, msg_id, do_register);
3212 rc = write_message_to_server(client, &msg.header);
3213 if (rc == -EPIPE)
3214 rc = 0;
3215 return rc;
3216 }
3217
cras_client_set_output_volume_changed_callback(struct cras_client * client,cras_client_output_volume_changed_callback cb)3218 int cras_client_set_output_volume_changed_callback(
3219 struct cras_client *client,
3220 cras_client_output_volume_changed_callback cb)
3221 {
3222 if (!client)
3223 return -EINVAL;
3224 client->observer_ops.output_volume_changed = cb;
3225 return cras_send_register_notification(
3226 client, CRAS_CLIENT_OUTPUT_VOLUME_CHANGED, cb != NULL);
3227 }
3228
cras_client_set_output_mute_changed_callback(struct cras_client * client,cras_client_output_mute_changed_callback cb)3229 int cras_client_set_output_mute_changed_callback(
3230 struct cras_client *client,
3231 cras_client_output_mute_changed_callback cb)
3232 {
3233 if (!client)
3234 return -EINVAL;
3235 client->observer_ops.output_mute_changed = cb;
3236 return cras_send_register_notification(
3237 client, CRAS_CLIENT_OUTPUT_MUTE_CHANGED, cb != NULL);
3238 }
3239
cras_client_set_capture_gain_changed_callback(struct cras_client * client,cras_client_capture_gain_changed_callback cb)3240 int cras_client_set_capture_gain_changed_callback(
3241 struct cras_client *client,
3242 cras_client_capture_gain_changed_callback cb)
3243 {
3244 if (!client)
3245 return -EINVAL;
3246 client->observer_ops.capture_gain_changed = cb;
3247 return cras_send_register_notification(
3248 client, CRAS_CLIENT_CAPTURE_GAIN_CHANGED, cb != NULL);
3249 }
3250
cras_client_set_capture_mute_changed_callback(struct cras_client * client,cras_client_capture_mute_changed_callback cb)3251 int cras_client_set_capture_mute_changed_callback(
3252 struct cras_client *client,
3253 cras_client_capture_mute_changed_callback cb)
3254 {
3255 if (!client)
3256 return -EINVAL;
3257 client->observer_ops.capture_mute_changed = cb;
3258 return cras_send_register_notification(
3259 client, CRAS_CLIENT_CAPTURE_MUTE_CHANGED, cb != NULL);
3260 }
3261
cras_client_set_nodes_changed_callback(struct cras_client * client,cras_client_nodes_changed_callback cb)3262 int cras_client_set_nodes_changed_callback(
3263 struct cras_client *client,
3264 cras_client_nodes_changed_callback cb)
3265 {
3266 if (!client)
3267 return -EINVAL;
3268 client->observer_ops.nodes_changed = cb;
3269 return cras_send_register_notification(
3270 client, CRAS_CLIENT_NODES_CHANGED, cb != NULL);
3271 }
3272
cras_client_set_active_node_changed_callback(struct cras_client * client,cras_client_active_node_changed_callback cb)3273 int cras_client_set_active_node_changed_callback(
3274 struct cras_client *client,
3275 cras_client_active_node_changed_callback cb)
3276 {
3277 if (!client)
3278 return -EINVAL;
3279 client->observer_ops.active_node_changed = cb;
3280 return cras_send_register_notification(
3281 client, CRAS_CLIENT_ACTIVE_NODE_CHANGED, cb != NULL);
3282 }
3283
cras_client_set_output_node_volume_changed_callback(struct cras_client * client,cras_client_output_node_volume_changed_callback cb)3284 int cras_client_set_output_node_volume_changed_callback(
3285 struct cras_client *client,
3286 cras_client_output_node_volume_changed_callback cb)
3287 {
3288 if (!client)
3289 return -EINVAL;
3290 client->observer_ops.output_node_volume_changed = cb;
3291 return cras_send_register_notification(
3292 client, CRAS_CLIENT_OUTPUT_NODE_VOLUME_CHANGED, cb != NULL);
3293 }
3294
cras_client_set_node_left_right_swapped_changed_callback(struct cras_client * client,cras_client_node_left_right_swapped_changed_callback cb)3295 int cras_client_set_node_left_right_swapped_changed_callback(
3296 struct cras_client *client,
3297 cras_client_node_left_right_swapped_changed_callback cb)
3298 {
3299 if (!client)
3300 return -EINVAL;
3301 client->observer_ops.node_left_right_swapped_changed = cb;
3302 return cras_send_register_notification(
3303 client, CRAS_CLIENT_NODE_LEFT_RIGHT_SWAPPED_CHANGED, cb != NULL);
3304 }
3305
cras_client_set_input_node_gain_changed_callback(struct cras_client * client,cras_client_input_node_gain_changed_callback cb)3306 int cras_client_set_input_node_gain_changed_callback(
3307 struct cras_client *client,
3308 cras_client_input_node_gain_changed_callback cb)
3309 {
3310 if (!client)
3311 return -EINVAL;
3312 client->observer_ops.input_node_gain_changed = cb;
3313 return cras_send_register_notification(
3314 client, CRAS_CLIENT_INPUT_NODE_GAIN_CHANGED, cb != NULL);
3315 }
3316
cras_client_set_num_active_streams_changed_callback(struct cras_client * client,cras_client_num_active_streams_changed_callback cb)3317 int cras_client_set_num_active_streams_changed_callback(
3318 struct cras_client *client,
3319 cras_client_num_active_streams_changed_callback cb)
3320 {
3321 if (!client)
3322 return -EINVAL;
3323 client->observer_ops.num_active_streams_changed = cb;
3324 return cras_send_register_notification(
3325 client, CRAS_CLIENT_NUM_ACTIVE_STREAMS_CHANGED, cb != NULL);
3326 }
3327
reregister_notifications(struct cras_client * client)3328 static int reregister_notifications(struct cras_client *client)
3329 {
3330 int rc;
3331
3332 if (client->observer_ops.output_volume_changed) {
3333 rc = cras_client_set_output_volume_changed_callback(
3334 client,
3335 client->observer_ops.output_volume_changed);
3336 if (rc != 0)
3337 return rc;
3338 }
3339 if (client->observer_ops.output_mute_changed) {
3340 rc = cras_client_set_output_mute_changed_callback(
3341 client,
3342 client->observer_ops.output_mute_changed);
3343 if (rc != 0)
3344 return rc;
3345 }
3346 if (client->observer_ops.capture_gain_changed) {
3347 rc = cras_client_set_capture_gain_changed_callback(
3348 client,
3349 client->observer_ops.capture_gain_changed);
3350 if (rc != 0)
3351 return rc;
3352 }
3353 if (client->observer_ops.capture_mute_changed) {
3354 rc = cras_client_set_capture_mute_changed_callback(
3355 client,
3356 client->observer_ops.capture_mute_changed);
3357 if (rc != 0)
3358 return rc;
3359 }
3360 if (client->observer_ops.nodes_changed) {
3361 rc = cras_client_set_nodes_changed_callback(
3362 client, client->observer_ops.nodes_changed);
3363 if (rc != 0)
3364 return rc;
3365 }
3366 if (client->observer_ops.active_node_changed) {
3367 rc = cras_client_set_active_node_changed_callback(
3368 client,
3369 client->observer_ops.active_node_changed);
3370 if (rc != 0)
3371 return rc;
3372 }
3373 if (client->observer_ops.output_node_volume_changed) {
3374 rc = cras_client_set_output_node_volume_changed_callback(
3375 client,
3376 client->observer_ops.output_node_volume_changed);
3377 if (rc != 0)
3378 return rc;
3379 }
3380 if (client->observer_ops.node_left_right_swapped_changed) {
3381 rc = cras_client_set_node_left_right_swapped_changed_callback(
3382 client,
3383 client->observer_ops.node_left_right_swapped_changed);
3384 if (rc != 0)
3385 return rc;
3386 }
3387 if (client->observer_ops.input_node_gain_changed) {
3388 rc = cras_client_set_input_node_gain_changed_callback(
3389 client,
3390 client->observer_ops.input_node_gain_changed);
3391 if (rc != 0)
3392 return rc;
3393 }
3394 if (client->observer_ops.num_active_streams_changed) {
3395 rc = cras_client_set_num_active_streams_changed_callback(
3396 client,
3397 client->observer_ops.num_active_streams_changed);
3398 if (rc != 0)
3399 return rc;
3400 }
3401 return 0;
3402 }
3403