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 #include <errno.h>
7 #include <fcntl.h>
8 #include <getopt.h>
9 #include <inttypes.h>
10 #include <limits.h>
11 #include <math.h>
12 #include <pthread.h>
13 #include <stdio.h>
14 #include <stdint.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <syslog.h>
18 #include <sys/mman.h>
19 #include <sys/param.h>
20 #include <sys/select.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24
25 #include "cras_client.h"
26 #include "cras_types.h"
27 #include "cras_util.h"
28 #include "cras_version.h"
29
30 #define NOT_ASSIGNED (0)
31 #define PLAYBACK_BUFFERED_TIME_IN_US (5000)
32
33 #define BUF_SIZE 32768
34
35 static const size_t MAX_IODEVS = 10; /* Max devices to print out. */
36 static const size_t MAX_IONODES = 20; /* Max ionodes to print out. */
37 static const size_t MAX_ATTACHED_CLIENTS = 10; /* Max clients to print out. */
38
39 static int pipefd[2];
40 static struct timespec last_latency;
41 static int show_latency;
42 static float last_rms_sqr_sum;
43 static int last_rms_size;
44 static float total_rms_sqr_sum;
45 static int total_rms_size;
46 static int show_rms;
47 static int show_total_rms;
48 static int keep_looping = 1;
49 static int exit_after_done_playing = 1;
50 static size_t duration_frames;
51 static int pause_client = 0;
52 static int pause_a_reply = 0;
53 static int pause_in_playback_reply = 1000;
54
55 static char *channel_layout = NULL;
56 static int pin_device_id;
57
58 static int play_short_sound = 0;
59 static int play_short_sound_periods = 0;
60 static int play_short_sound_periods_left = 0;
61
62 static int effect_aec = 0;
63 static int effect_ns = 0;
64 static int effect_agc = 0;
65 static int effect_vad = 0;
66 static char *aecdump_file = NULL;
67 static char time_str[128];
68
69 /* Sleep interval between cras_client_read_atlog calls. */
70 static const struct timespec follow_atlog_sleep_ts = {
71 0, 50 * 1000 * 1000 /* 50 ms. */
72 };
73
74 /* Conditional so the client thread can signal that main should exit. */
75 static pthread_mutex_t done_mutex = PTHREAD_MUTEX_INITIALIZER;
76 static pthread_cond_t done_cond = PTHREAD_COND_INITIALIZER;
77
78 struct cras_audio_format *aud_format;
79 struct {
80 char *name;
81 snd_pcm_format_t format;
82 } supported_formats[] = {
83 { "S16_LE", SND_PCM_FORMAT_S16_LE },
84 { "S24_LE", SND_PCM_FORMAT_S24_LE },
85 { "S32_LE", SND_PCM_FORMAT_S32_LE },
86 { NULL, 0 },
87 };
88
terminate_stream_loop()89 static int terminate_stream_loop()
90 {
91 keep_looping = 0;
92 return write(pipefd[1], "1", 1);
93 }
94
get_block_size(uint64_t buffer_time_in_us,size_t rate)95 static size_t get_block_size(uint64_t buffer_time_in_us, size_t rate)
96 {
97 return (size_t)(buffer_time_in_us * rate / 1000000);
98 }
99
check_stream_terminate(size_t frames)100 static void check_stream_terminate(size_t frames)
101 {
102 if (duration_frames) {
103 if (duration_frames <= frames)
104 terminate_stream_loop();
105 else
106 duration_frames -= frames;
107 }
108 }
109
fill_time_offset(time_t * sec_offset,int32_t * nsec_offset)110 static void fill_time_offset(time_t *sec_offset, int32_t *nsec_offset)
111 {
112 struct timespec mono_time, real_time;
113
114 clock_gettime(CLOCK_MONOTONIC_RAW, &mono_time);
115 clock_gettime(CLOCK_REALTIME, &real_time);
116 *sec_offset = real_time.tv_sec - mono_time.tv_sec;
117 *nsec_offset = real_time.tv_nsec - mono_time.tv_nsec;
118 }
119
120 /* Compute square sum of samples (for calculation of RMS value). */
compute_sqr_sum_16(const int16_t * samples,int size)121 float compute_sqr_sum_16(const int16_t *samples, int size)
122 {
123 unsigned i;
124 float sqr_sum = 0;
125
126 for (i = 0; i < size; i++)
127 sqr_sum += samples[i] * samples[i];
128
129 return sqr_sum;
130 }
131
132 /* Update the RMS values with the given samples. */
update_rms(const uint8_t * samples,int size)133 int update_rms(const uint8_t *samples, int size)
134 {
135 switch (aud_format->format) {
136 case SND_PCM_FORMAT_S16_LE: {
137 last_rms_sqr_sum =
138 compute_sqr_sum_16((int16_t *)samples, size / 2);
139 last_rms_size = size / 2;
140 break;
141 }
142 default:
143 return -EINVAL;
144 }
145
146 total_rms_sqr_sum += last_rms_sqr_sum;
147 total_rms_size += last_rms_size;
148
149 return 0;
150 }
151
152 /* Parses a string with format <N>:<M> into a node id*/
parse_node_id(char * input,cras_node_id_t * id_out)153 static int parse_node_id(char *input, cras_node_id_t *id_out)
154 {
155 const char *s;
156 char *endptr;
157 int dev_index;
158 int node_index;
159
160 if (!id_out)
161 return -EINVAL;
162
163 s = strtok(input, ":");
164 if (!s)
165 return -EINVAL;
166 dev_index = strtol(s, &endptr, 10);
167 if (*endptr)
168 return -EINVAL;
169
170 s = strtok(NULL, ":");
171 if (!s)
172 return -EINVAL;
173 node_index = strtol(s, &endptr, 10);
174 if (*endptr)
175 return -EINVAL;
176
177 *id_out = cras_make_node_id(dev_index, node_index);
178 return 0;
179 }
180
181 /* Parses a string with format <N>:<M>:<0-100> into a node id and a value */
parse_node_id_with_value(char * input,cras_node_id_t * id_out,int * value_out)182 static int parse_node_id_with_value(char *input, cras_node_id_t *id_out,
183 int *value_out)
184 {
185 const char *s;
186 char *endptr;
187 int dev_index;
188 int node_index;
189 long int value;
190
191 if (!id_out || !value_out)
192 return -EINVAL;
193
194 s = strtok(input, ":");
195 if (!s)
196 return -EINVAL;
197 dev_index = strtol(s, &endptr, 10);
198 if (*endptr)
199 return -EINVAL;
200
201 s = strtok(NULL, ":");
202 if (!s)
203 return -EINVAL;
204 node_index = strtol(s, &endptr, 10);
205 if (*endptr)
206 return -EINVAL;
207
208 s = strtok(NULL, ":");
209 if (!s)
210 return -EINVAL;
211 value = strtol(s, &endptr, 10);
212 if (*endptr)
213 return -EINVAL;
214 if (value > INT_MAX || value < INT_MIN)
215 return -EOVERFLOW;
216
217 *id_out = cras_make_node_id(dev_index, node_index);
218 *value_out = value;
219 return 0;
220 }
221
222 /* Run from callback thread. */
got_samples(struct cras_client * client,cras_stream_id_t stream_id,uint8_t * captured_samples,uint8_t * playback_samples,unsigned int frames,const struct timespec * captured_time,const struct timespec * playback_time,void * user_arg)223 static int got_samples(struct cras_client *client, cras_stream_id_t stream_id,
224 uint8_t *captured_samples, uint8_t *playback_samples,
225 unsigned int frames,
226 const struct timespec *captured_time,
227 const struct timespec *playback_time, void *user_arg)
228 {
229 int *fd = (int *)user_arg;
230 int ret;
231 int write_size;
232 int frame_bytes;
233
234 while (pause_client)
235 usleep(10000);
236
237 cras_client_calc_capture_latency(captured_time, &last_latency);
238
239 frame_bytes = cras_client_format_bytes_per_frame(aud_format);
240 write_size = frames * frame_bytes;
241
242 /* Update RMS values with all available frames. */
243 if (keep_looping) {
244 update_rms(captured_samples,
245 MIN(write_size, duration_frames * frame_bytes));
246 }
247
248 check_stream_terminate(frames);
249
250 ret = write(*fd, captured_samples, write_size);
251 if (ret != write_size)
252 printf("Error writing file\n");
253 return frames;
254 }
255
256 /* Run from callback thread. */
put_samples(struct cras_client * client,cras_stream_id_t stream_id,uint8_t * captured_samples,uint8_t * playback_samples,unsigned int frames,const struct timespec * captured_time,const struct timespec * playback_time,void * user_arg)257 static int put_samples(struct cras_client *client, cras_stream_id_t stream_id,
258 uint8_t *captured_samples, uint8_t *playback_samples,
259 unsigned int frames,
260 const struct timespec *captured_time,
261 const struct timespec *playback_time, void *user_arg)
262 {
263 uint32_t frame_bytes = cras_client_format_bytes_per_frame(aud_format);
264 int fd = *(int *)user_arg;
265 uint8_t buff[BUF_SIZE];
266 int nread;
267
268 while (pause_client)
269 usleep(10000);
270
271 if (pause_a_reply) {
272 usleep(pause_in_playback_reply);
273 pause_a_reply = 0;
274 }
275
276 check_stream_terminate(frames);
277
278 cras_client_calc_playback_latency(playback_time, &last_latency);
279
280 if (play_short_sound) {
281 if (play_short_sound_periods_left)
282 /* Play a period from file. */
283 play_short_sound_periods_left--;
284 else {
285 /* Fill zeros to play silence. */
286 memset(playback_samples, 0,
287 MIN(frames * frame_bytes, BUF_SIZE));
288 return frames;
289 }
290 }
291
292 nread = read(fd, buff, MIN(frames * frame_bytes, BUF_SIZE));
293 if (nread <= 0) {
294 if (exit_after_done_playing)
295 terminate_stream_loop();
296 return nread;
297 }
298
299 memcpy(playback_samples, buff, nread);
300 return nread / frame_bytes;
301 }
302
303 /* Run from callback thread. */
304 static int
put_stdin_samples(struct cras_client * client,cras_stream_id_t stream_id,uint8_t * captured_samples,uint8_t * playback_samples,unsigned int frames,const struct timespec * captured_time,const struct timespec * playback_time,void * user_arg)305 put_stdin_samples(struct cras_client *client, cras_stream_id_t stream_id,
306 uint8_t *captured_samples, uint8_t *playback_samples,
307 unsigned int frames, const struct timespec *captured_time,
308 const struct timespec *playback_time, void *user_arg)
309 {
310 int rc = 0;
311 uint32_t frame_bytes = cras_client_format_bytes_per_frame(aud_format);
312
313 rc = read(0, playback_samples, frames * frame_bytes);
314 if (rc <= 0) {
315 terminate_stream_loop();
316 return -1;
317 }
318
319 return rc / frame_bytes;
320 }
321
stream_error(struct cras_client * client,cras_stream_id_t stream_id,int err,void * arg)322 static int stream_error(struct cras_client *client, cras_stream_id_t stream_id,
323 int err, void *arg)
324 {
325 printf("Stream error %d\n", err);
326 terminate_stream_loop();
327 return 0;
328 }
329
print_last_latency()330 static void print_last_latency()
331 {
332 if (last_latency.tv_sec > 0 || last_latency.tv_nsec > 0)
333 printf("%u.%09u\n", (unsigned)last_latency.tv_sec,
334 (unsigned)last_latency.tv_nsec);
335 else {
336 printf("-%lld.%09lld\n", (long long)-last_latency.tv_sec,
337 (long long)-last_latency.tv_nsec);
338 }
339 }
340
print_last_rms()341 static void print_last_rms()
342 {
343 if (last_rms_size != 0)
344 printf("%.9f\n", sqrt(last_rms_sqr_sum / last_rms_size));
345 }
346
print_total_rms()347 static void print_total_rms()
348 {
349 if (total_rms_size != 0)
350 printf("%.9f\n", sqrt(total_rms_sqr_sum / total_rms_size));
351 }
352
print_dev_info(const struct cras_iodev_info * devs,int num_devs)353 static void print_dev_info(const struct cras_iodev_info *devs, int num_devs)
354 {
355 unsigned i;
356
357 printf("\tID\tName\n");
358 for (i = 0; i < num_devs; i++)
359 printf("\t%u\t%s\n", devs[i].idx, devs[i].name);
360 }
361
print_node_info(const struct cras_ionode_info * nodes,int num_nodes,int is_input)362 static void print_node_info(const struct cras_ionode_info *nodes, int num_nodes,
363 int is_input)
364 {
365 unsigned i;
366
367 printf("\tStable Id\t ID\t%4s Plugged\tL/R swapped\t "
368 "Time Hotword\tType\t\t Name\n",
369 is_input ? "Gain" : " Vol");
370 for (i = 0; i < num_nodes; i++)
371 printf("\t(%08x)\t%u:%u\t%5g %7s\t%14s\t%10ld %-7s\t%-16s%c%s\n",
372 nodes[i].stable_id, nodes[i].iodev_idx,
373 nodes[i].ionode_idx,
374 is_input ? nodes[i].capture_gain / 100.0 :
375 (double)nodes[i].volume,
376 nodes[i].plugged ? "yes" : "no",
377 nodes[i].left_right_swapped ? "yes" : "no",
378 (long)nodes[i].plugged_time.tv_sec,
379 nodes[i].active_hotword_model, nodes[i].type,
380 nodes[i].active ? '*' : ' ', nodes[i].name);
381 }
382
print_device_lists(struct cras_client * client)383 static void print_device_lists(struct cras_client *client)
384 {
385 struct cras_iodev_info devs[MAX_IODEVS];
386 struct cras_ionode_info nodes[MAX_IONODES];
387 size_t num_devs, num_nodes;
388 int rc;
389
390 num_devs = MAX_IODEVS;
391 num_nodes = MAX_IONODES;
392 rc = cras_client_get_output_devices(client, devs, nodes, &num_devs,
393 &num_nodes);
394 if (rc < 0)
395 return;
396 printf("Output Devices:\n");
397 print_dev_info(devs, num_devs);
398 printf("Output Nodes:\n");
399 print_node_info(nodes, num_nodes, 0);
400
401 num_devs = MAX_IODEVS;
402 num_nodes = MAX_IONODES;
403 rc = cras_client_get_input_devices(client, devs, nodes, &num_devs,
404 &num_nodes);
405 printf("Input Devices:\n");
406 print_dev_info(devs, num_devs);
407 printf("Input Nodes:\n");
408 print_node_info(nodes, num_nodes, 1);
409 }
410
print_attached_client_list(struct cras_client * client)411 static void print_attached_client_list(struct cras_client *client)
412 {
413 struct cras_attached_client_info clients[MAX_ATTACHED_CLIENTS];
414 size_t i;
415 int num_clients;
416
417 num_clients = cras_client_get_attached_clients(client, clients,
418 MAX_ATTACHED_CLIENTS);
419 if (num_clients < 0)
420 return;
421 num_clients = MIN(num_clients, MAX_ATTACHED_CLIENTS);
422 printf("Attached clients:\n");
423 printf("\tID\tpid\tuid\n");
424 for (i = 0; i < num_clients; i++)
425 printf("\t%u\t%d\t%d\n", clients[i].id, clients[i].pid,
426 clients[i].gid);
427 }
428
print_active_stream_info(struct cras_client * client)429 static void print_active_stream_info(struct cras_client *client)
430 {
431 struct timespec ts;
432 unsigned num_streams;
433
434 num_streams = cras_client_get_num_active_streams(client, &ts);
435 printf("Num active streams: %u\n", num_streams);
436 printf("Last audio active time: %llu, %llu\n", (long long)ts.tv_sec,
437 (long long)ts.tv_nsec);
438 }
439
print_system_volumes(struct cras_client * client)440 static void print_system_volumes(struct cras_client *client)
441 {
442 printf("System Volume (0-100): %zu %s\n"
443 "Capture Gain (%.2f - %.2f): %.2fdB %s\n",
444 cras_client_get_system_volume(client),
445 cras_client_get_system_muted(client) ? "(Muted)" : "",
446 cras_client_get_system_min_capture_gain(client) / 100.0,
447 cras_client_get_system_max_capture_gain(client) / 100.0,
448 cras_client_get_system_capture_gain(client) / 100.0,
449 cras_client_get_system_capture_muted(client) ? "(Muted)" : "");
450 }
451
print_user_muted(struct cras_client * client)452 static void print_user_muted(struct cras_client *client)
453 {
454 printf("User muted: %s\n",
455 cras_client_get_user_muted(client) ? "Muted" : "Not muted");
456 }
457
458 /*
459 * Convert time value from one clock to the other using given offset
460 * in sec and nsec.
461 */
convert_time(unsigned int * sec,unsigned int * nsec,time_t sec_offset,int32_t nsec_offset)462 static void convert_time(unsigned int *sec, unsigned int *nsec,
463 time_t sec_offset, int32_t nsec_offset)
464 {
465 sec_offset += *sec;
466 nsec_offset += *nsec;
467 if (nsec_offset >= 1000000000L) {
468 sec_offset++;
469 nsec_offset -= 1000000000L;
470 } else if (nsec_offset < 0) {
471 sec_offset--;
472 nsec_offset += 1000000000L;
473 }
474 *sec = sec_offset;
475 *nsec = nsec_offset;
476 }
477
show_alog_tag(const struct audio_thread_event_log * log,unsigned int tag_idx,int32_t sec_offset,int32_t nsec_offset)478 static void show_alog_tag(const struct audio_thread_event_log *log,
479 unsigned int tag_idx, int32_t sec_offset,
480 int32_t nsec_offset)
481 {
482 unsigned int tag = (log->log[tag_idx].tag_sec >> 24) & 0xff;
483 unsigned int sec = log->log[tag_idx].tag_sec & 0x00ffffff;
484 unsigned int nsec = log->log[tag_idx].nsec;
485 unsigned int data1 = log->log[tag_idx].data1;
486 unsigned int data2 = log->log[tag_idx].data2;
487 unsigned int data3 = log->log[tag_idx].data3;
488 time_t lt;
489 struct tm *t;
490
491 /* Skip unused log entries. */
492 if (log->log[tag_idx].tag_sec == 0 && log->log[tag_idx].nsec == 0)
493 return;
494
495 /* Convert from monotomic raw clock to realtime clock. */
496 convert_time(&sec, &nsec, sec_offset, nsec_offset);
497 lt = sec;
498 t = localtime(<);
499 strftime(time_str, 128, "%Y-%m-%dT%H:%M:%S", t);
500
501 printf("%s.%09u cras atlog ", time_str, nsec);
502
503 /* Prepare realtime string for arguments. */
504 switch (tag) {
505 case AUDIO_THREAD_READ_AUDIO_TSTAMP:
506 case AUDIO_THREAD_FILL_AUDIO_TSTAMP:
507 case AUDIO_THREAD_STREAM_RESCHEDULE:
508 case AUDIO_THREAD_STREAM_SLEEP_TIME:
509 case AUDIO_THREAD_STREAM_SLEEP_ADJUST:
510 case AUDIO_THREAD_DEV_SLEEP_TIME:
511 sec = data2;
512 nsec = data3;
513 break;
514 }
515 convert_time(&sec, &nsec, sec_offset, nsec_offset);
516 lt = sec;
517 t = localtime(<);
518 strftime(time_str, 128, " %H:%M:%S", t);
519
520 switch (tag) {
521 case AUDIO_THREAD_WAKE:
522 printf("%-30s num_fds:%d\n", "WAKE", (int)data1);
523 break;
524 case AUDIO_THREAD_SLEEP:
525 printf("%-30s sleep:%09d.%09d\n", "SLEEP", (int)data1,
526 (int)data2);
527 break;
528 case AUDIO_THREAD_READ_AUDIO:
529 printf("%-30s dev:%u hw_level:%u read:%u\n", "READ_AUDIO",
530 data1, data2, data3);
531 break;
532 case AUDIO_THREAD_READ_AUDIO_TSTAMP:
533 printf("%-30s dev:%u tstamp:%s.%09u\n", "READ_AUDIO_TSTAMP",
534 data1, time_str, nsec);
535 break;
536 case AUDIO_THREAD_READ_AUDIO_DONE:
537 printf("%-30s read_remainder:%u\n", "READ_AUDIO_DONE", data1);
538 break;
539 case AUDIO_THREAD_READ_OVERRUN:
540 printf("%-30s dev:%u stream:%x num_overruns:%u\n",
541 "READ_AUDIO_OVERRUN", data1, data2, data3);
542 break;
543 case AUDIO_THREAD_FILL_AUDIO:
544 printf("%-30s dev:%u hw_level:%u\n", "FILL_AUDIO", data1,
545 data2);
546 break;
547 case AUDIO_THREAD_FILL_AUDIO_TSTAMP:
548 printf("%-30s dev:%u tstamp:%s.%09u\n", "FILL_AUDIO_TSTAMP",
549 data1, time_str, nsec);
550 break;
551 case AUDIO_THREAD_FILL_AUDIO_DONE:
552 printf("%-30s hw_level:%u total_written:%u min_cb_level:%u\n",
553 "FILL_AUDIO_DONE", data1, data2, data3);
554 break;
555 case AUDIO_THREAD_WRITE_STREAMS_WAIT:
556 printf("%-30s stream:%x\n", "WRITE_STREAMS_WAIT", data1);
557 break;
558 case AUDIO_THREAD_WRITE_STREAMS_WAIT_TO:
559 printf("%-30s\n", "WRITE_STREAMS_WAIT_TO");
560 break;
561 case AUDIO_THREAD_WRITE_STREAMS_MIX:
562 printf("%-30s write_limit:%u max_offset:%u\n",
563 "WRITE_STREAMS_MIX", data1, data2);
564 break;
565 case AUDIO_THREAD_WRITE_STREAMS_MIXED:
566 printf("%-30s write_limit:%u\n", "WRITE_STREAMS_MIXED", data1);
567 break;
568 case AUDIO_THREAD_WRITE_STREAMS_STREAM:
569 printf("%-30s id:%x shm_frames:%u cb_pending:%u\n",
570 "WRITE_STREAMS_STREAM", data1, data2, data3);
571 break;
572 case AUDIO_THREAD_FETCH_STREAM:
573 printf("%-30s id:%x cbth:%u delay:%u\n",
574 "WRITE_STREAMS_FETCH_STREAM", data1, data2, data3);
575 break;
576 case AUDIO_THREAD_STREAM_ADDED:
577 printf("%-30s id:%x dev:%u\n", "STREAM_ADDED", data1, data2);
578 break;
579 case AUDIO_THREAD_STREAM_REMOVED:
580 printf("%-30s id:%x\n", "STREAM_REMOVED", data1);
581 break;
582 case AUDIO_THREAD_A2DP_ENCODE:
583 printf("%-30s proc:%d queued:%u readable:%u\n", "A2DP_ENCODE",
584 data1, data2, data3);
585 break;
586 case AUDIO_THREAD_A2DP_WRITE:
587 printf("%-30s written:%d queued:%u\n", "A2DP_WRITE", data1,
588 data2);
589 break;
590 case AUDIO_THREAD_DEV_STREAM_MIX:
591 printf("%-30s written:%u read:%u\n", "DEV_STREAM_MIX", data1,
592 data2);
593 break;
594 case AUDIO_THREAD_CAPTURE_POST:
595 printf("%-30s stream:%x thresh:%u rd_buf:%u\n", "CAPTURE_POST",
596 data1, data2, data3);
597 break;
598 case AUDIO_THREAD_CAPTURE_WRITE:
599 printf("%-30s stream:%x write:%u shm_fr:%u\n", "CAPTURE_WRITE",
600 data1, data2, data3);
601 break;
602 case AUDIO_THREAD_CONV_COPY:
603 printf("%-30s wr_buf:%u shm_writable:%u offset:%u\n",
604 "CONV_COPY", data1, data2, data3);
605 break;
606 case AUDIO_THREAD_STREAM_FETCH_PENDING:
607 printf("%-30s id:%x\n", "STREAM_FETCH_PENGING", data1);
608 break;
609 case AUDIO_THREAD_STREAM_RESCHEDULE:
610 printf("%-30s id:%x next_cb_ts:%s.%09u\n", "STREAM_RESCHEDULE",
611 data1, time_str, nsec);
612 break;
613 case AUDIO_THREAD_STREAM_SLEEP_TIME:
614 printf("%-30s id:%x wake:%s.%09u\n", "STREAM_SLEEP_TIME", data1,
615 time_str, nsec);
616 break;
617 case AUDIO_THREAD_STREAM_SLEEP_ADJUST:
618 printf("%-30s id:%x from:%s.%09u\n", "STREAM_SLEEP_ADJUST",
619 data1, time_str, nsec);
620 break;
621 case AUDIO_THREAD_STREAM_SKIP_CB:
622 printf("%-30s id:%x write_offset_0:%u write_offset_1:%u\n",
623 "STREAM_SKIP_CB", data1, data2, data3);
624 break;
625 case AUDIO_THREAD_DEV_SLEEP_TIME:
626 printf("%-30s dev:%u wake:%s.%09u\n", "DEV_SLEEP_TIME", data1,
627 time_str, nsec);
628 break;
629 case AUDIO_THREAD_SET_DEV_WAKE:
630 printf("%-30s dev:%u hw_level:%u sleep:%u\n", "SET_DEV_WAKE",
631 data1, data2, data3);
632 break;
633 case AUDIO_THREAD_DEV_ADDED:
634 printf("%-30s dev:%u\n", "DEV_ADDED", data1);
635 break;
636 case AUDIO_THREAD_DEV_REMOVED:
637 printf("%-30s dev:%u\n", "DEV_REMOVED", data1);
638 break;
639 case AUDIO_THREAD_IODEV_CB:
640 printf("%-30s is_write:%u\n", "IODEV_CB", data1);
641 break;
642 case AUDIO_THREAD_PB_MSG:
643 printf("%-30s msg_id:%u\n", "PB_MSG", data1);
644 break;
645 case AUDIO_THREAD_ODEV_NO_STREAMS:
646 printf("%-30s dev:%u\n", "ODEV_NO_STREAMS", data1);
647 break;
648 case AUDIO_THREAD_ODEV_LEAVE_NO_STREAMS:
649 printf("%-30s dev:%u\n", "ODEV_LEAVE_NO_STREAMS", data1);
650 break;
651 case AUDIO_THREAD_ODEV_START:
652 printf("%-30s dev:%u min_cb_level:%u\n", "ODEV_START", data1,
653 data2);
654 break;
655 case AUDIO_THREAD_FILL_ODEV_ZEROS:
656 printf("%-30s dev:%u write:%u\n", "FILL_ODEV_ZEROS", data1,
657 data2);
658 break;
659 case AUDIO_THREAD_ODEV_DEFAULT_NO_STREAMS:
660 printf("%-30s dev:%u hw_level:%u target:%u\n",
661 "DEFAULT_NO_STREAMS", data1, data2, data3);
662 break;
663 case AUDIO_THREAD_UNDERRUN:
664 printf("%-30s dev:%u hw_level:%u total_written:%u\n",
665 "UNDERRUN", data1, data2, data3);
666 break;
667 case AUDIO_THREAD_SEVERE_UNDERRUN:
668 printf("%-30s dev:%u\n", "SEVERE_UNDERRUN", data1);
669 break;
670 case AUDIO_THREAD_CAPTURE_DROP_TIME:
671 printf("%-30s time:%09u.%09d\n", "CAPTURE_DROP_TIME", data1,
672 data2);
673 break;
674 case AUDIO_THREAD_DEV_DROP_FRAMES:
675 printf("%-30s dev:%u frames:%u\n", "DEV_DROP_FRAMES", data1,
676 data2);
677 break;
678 default:
679 printf("%-30s tag:%u\n", "UNKNOWN", tag);
680 break;
681 }
682 }
683
print_audio_debug_info(const struct audio_debug_info * info)684 static void print_audio_debug_info(const struct audio_debug_info *info)
685 {
686 time_t sec_offset;
687 int32_t nsec_offset;
688 int i, j;
689
690 printf("Audio Debug Stats:\n");
691 printf("-------------devices------------\n");
692 if (info->num_devs > MAX_DEBUG_DEVS)
693 return;
694
695 for (i = 0; i < info->num_devs; i++) {
696 printf("%s dev: %s\n",
697 (info->devs[i].direction == CRAS_STREAM_INPUT) ?
698 "Input" :
699 "Output",
700 info->devs[i].dev_name);
701 printf("buffer_size: %u\n"
702 "min_buffer_level: %u\n"
703 "min_cb_level: %u\n"
704 "max_cb_level: %u\n"
705 "frame_rate: %u\n"
706 "num_channels: %u\n"
707 "est_rate_ratio: %lf\n"
708 "num_underruns: %u\n"
709 "num_severe_underruns: %u\n"
710 "highest_hw_level: %u\n"
711 "runtime: %u.%09u\n"
712 "longest_wake: %u.%09u\n"
713 "software_gain_scaler: %lf\n",
714 (unsigned int)info->devs[i].buffer_size,
715 (unsigned int)info->devs[i].min_buffer_level,
716 (unsigned int)info->devs[i].min_cb_level,
717 (unsigned int)info->devs[i].max_cb_level,
718 (unsigned int)info->devs[i].frame_rate,
719 (unsigned int)info->devs[i].num_channels,
720 info->devs[i].est_rate_ratio,
721 (unsigned int)info->devs[i].num_underruns,
722 (unsigned int)info->devs[i].num_severe_underruns,
723 (unsigned int)info->devs[i].highest_hw_level,
724 (unsigned int)info->devs[i].runtime_sec,
725 (unsigned int)info->devs[i].runtime_nsec,
726 (unsigned int)info->devs[i].longest_wake_sec,
727 (unsigned int)info->devs[i].longest_wake_nsec,
728 info->devs[i].software_gain_scaler);
729 printf("\n");
730 }
731
732 printf("-------------stream_dump------------\n");
733 if (info->num_streams > MAX_DEBUG_STREAMS)
734 return;
735
736 for (i = 0; i < info->num_streams; i++) {
737 int channel;
738 printf("stream: %llu dev: %u\n",
739 (unsigned long long)info->streams[i].stream_id,
740 (unsigned int)info->streams[i].dev_idx);
741 printf("direction: %s\n",
742 (info->streams[i].direction == CRAS_STREAM_INPUT) ?
743 "Input" :
744 "Output");
745 printf("stream_type: %s\n",
746 cras_stream_type_str(info->streams[i].stream_type));
747 printf("client_type: %s\n",
748 cras_client_type_str(info->streams[i].client_type));
749 printf("buffer_frames: %u\n"
750 "cb_threshold: %u\n"
751 "effects: 0x%.4x\n"
752 "frame_rate: %u\n"
753 "num_channels: %u\n"
754 "longest_fetch_sec: %u.%09u\n"
755 "num_overruns: %u\n"
756 "is_pinned: %x\n"
757 "pinned_dev_idx: %x\n"
758 "num_missed_cb: %u\n"
759 "%s: %lf\n"
760 "runtime: %u.%09u\n",
761 (unsigned int)info->streams[i].buffer_frames,
762 (unsigned int)info->streams[i].cb_threshold,
763 (unsigned int)info->streams[i].effects,
764 (unsigned int)info->streams[i].frame_rate,
765 (unsigned int)info->streams[i].num_channels,
766 (unsigned int)info->streams[i].longest_fetch_sec,
767 (unsigned int)info->streams[i].longest_fetch_nsec,
768 (unsigned int)info->streams[i].num_overruns,
769 (unsigned int)info->streams[i].is_pinned,
770 (unsigned int)info->streams[i].pinned_dev_idx,
771 (unsigned int)info->streams[i].num_missed_cb,
772 (info->streams[i].direction == CRAS_STREAM_INPUT) ?
773 "gain" :
774 "volume",
775 info->streams[i].stream_volume,
776 (unsigned int)info->streams[i].runtime_sec,
777 (unsigned int)info->streams[i].runtime_nsec);
778 printf("channel map:");
779 for (channel = 0; channel < CRAS_CH_MAX; channel++)
780 printf("%d ", info->streams[i].channel_layout[channel]);
781 printf("\n\n");
782 }
783
784 printf("Audio Thread Event Log:\n");
785
786 fill_time_offset(&sec_offset, &nsec_offset);
787 j = info->log.write_pos % info->log.len;
788 i = 0;
789 printf("start at %d\n", j);
790 for (; i < info->log.len; i++) {
791 show_alog_tag(&info->log, j, sec_offset, nsec_offset);
792 j++;
793 j %= info->log.len;
794 }
795 }
796
audio_debug_info(struct cras_client * client)797 static void audio_debug_info(struct cras_client *client)
798 {
799 const struct audio_debug_info *info;
800 info = cras_client_get_audio_debug_info(client);
801 if (!info)
802 return;
803 print_audio_debug_info(info);
804
805 /* Signal main thread we are done after the last chunk. */
806 pthread_mutex_lock(&done_mutex);
807 pthread_cond_signal(&done_cond);
808 pthread_mutex_unlock(&done_mutex);
809 }
810
show_btlog_tag(const struct cras_bt_event_log * log,unsigned int tag_idx,int32_t sec_offset,int32_t nsec_offset)811 static void show_btlog_tag(const struct cras_bt_event_log *log,
812 unsigned int tag_idx, int32_t sec_offset,
813 int32_t nsec_offset)
814 {
815 unsigned int tag = (log->log[tag_idx].tag_sec >> 24) & 0xff;
816 unsigned int sec = log->log[tag_idx].tag_sec & 0x00ffffff;
817 unsigned int nsec = log->log[tag_idx].nsec;
818 unsigned int data1 = log->log[tag_idx].data1;
819 unsigned int data2 = log->log[tag_idx].data2;
820 time_t lt;
821 struct tm *t;
822
823 /* Skip unused log entries. */
824 if (log->log[tag_idx].tag_sec == 0 && log->log[tag_idx].nsec == 0)
825 return;
826
827 /* Convert from monotomic raw clock to realtime clock. */
828 convert_time(&sec, &nsec, sec_offset, nsec_offset);
829 lt = sec;
830 t = localtime(<);
831 strftime(time_str, 128, "%Y-%m-%dT%H:%M:%S", t);
832
833 printf("%s.%09u cras btlog ", time_str, nsec);
834
835 switch (tag) {
836 case BT_ADAPTER_ADDED:
837 printf("%-30s\n", "ADAPTER_ADDED");
838 break;
839 case BT_ADAPTER_REMOVED:
840 printf("%-30s\n", "ADAPTER_REMOVED");
841 break;
842 case BT_A2DP_CONFIGURED:
843 printf("%-30s connected profiles %u\n", "A2DP_CONFIGURED",
844 data1);
845 break;
846 case BT_A2DP_START:
847 printf("%-30s\n", "A2DP_START");
848 break;
849 case BT_A2DP_SUSPENDED:
850 printf("%-30s\n", "A2DP_SUSPENDED");
851 break;
852 case BT_AUDIO_GATEWAY_INIT:
853 printf("%-30s supported profiles %u\n", "AUDIO_GATEWAY_INIT",
854 data1);
855 break;
856 case BT_AUDIO_GATEWAY_START:
857 printf("%-30s \n", "AUDIO_GATEWAY_START");
858 break;
859 case BT_AVAILABLE_CODECS:
860 printf("%-30s codec #%u id %u\n", "AVAILABLE_CODECS", data1,
861 data2);
862 break;
863 case BT_CODEC_SELECTION:
864 printf("%-30s dir %u codec id %u\n", "CODEC_SELECTION", data1,
865 data2);
866 break;
867 case BT_DEV_CONNECTED_CHANGE:
868 printf("%-30s profiles %u now %u\n", "DEV_CONENCTED_CHANGE",
869 data1, data2);
870 break;
871 case BT_DEV_CONN_WATCH_CB:
872 printf("%-30s %u retries left, supported profiles %u\n",
873 "DEV_CONN_WATCH_CB", data1, data2);
874 break;
875 case BT_DEV_SUSPEND_CB:
876 printf("%-30s profiles supported %u, connected %u\n",
877 "DEV_SUSPEND_CB", data1, data2);
878 break;
879 case BT_HFP_NEW_CONNECTION:
880 printf("%-30s\n", "HFP_NEW_CONNECTION");
881 break;
882 case BT_HFP_REQUEST_DISCONNECT:
883 printf("%-30s\n", "HFP_REQUEST_DISCONNECT");
884 break;
885 case BT_HFP_SUPPORTED_FEATURES:
886 printf("%-30s role %s features %u\n", "HFP_SUPPORTED_FEATURES",
887 data1 ? "AG" : "HF", data2);
888 break;
889 case BT_HSP_NEW_CONNECTION:
890 printf("%-30s\n", "HSP_NEW_CONNECTION");
891 break;
892 case BT_HSP_REQUEST_DISCONNECT:
893 printf("%-30s\n", "HSP_REQUEST_DISCONNECT");
894 break;
895 case BT_NEW_AUDIO_PROFILE_AFTER_CONNECT:
896 printf("%-30s old %u, new %u\n",
897 "NEW_AUDIO_PROFILE_AFTER_CONNECT", data1, data2);
898 break;
899 case BT_RESET:
900 printf("%-30s\n", "RESET");
901 break;
902 case BT_SCO_CONNECT:
903 printf("%-30s %s sk %d\n", "SCO_CONNECT",
904 data1 ? "success" : "failed", (int)data2);
905 break;
906 case BT_TRANSPORT_ACQUIRE:
907 printf("%-30s %s fd %d\n", "TRANSPORT_ACQUIRE",
908 data1 ? "success" : "failed", (int)data2);
909 break;
910 case BT_TRANSPORT_RELEASE:
911 printf("%-30s\n", "TRANSPORT_RELEASE");
912 break;
913 default:
914 printf("%-30s\n", "UNKNOWN");
915 break;
916 }
917 }
918
cras_bt_debug_info(struct cras_client * client)919 static void cras_bt_debug_info(struct cras_client *client)
920 {
921 const struct cras_bt_debug_info *info;
922 time_t sec_offset;
923 int32_t nsec_offset;
924 int i, j;
925
926 info = cras_client_get_bt_debug_info(client);
927 fill_time_offset(&sec_offset, &nsec_offset);
928 j = info->bt_log.write_pos;
929 i = 0;
930 printf("BT debug log:\n");
931 for (; i < info->bt_log.len; i++) {
932 show_btlog_tag(&info->bt_log, j, sec_offset, nsec_offset);
933 j++;
934 j %= info->bt_log.len;
935 }
936
937 /* Signal main thread we are done after the last chunk. */
938 pthread_mutex_lock(&done_mutex);
939 pthread_cond_signal(&done_cond);
940 pthread_mutex_unlock(&done_mutex);
941 }
942
print_cras_audio_thread_snapshot(const struct cras_audio_thread_snapshot * snapshot)943 static void print_cras_audio_thread_snapshot(
944 const struct cras_audio_thread_snapshot *snapshot)
945 {
946 printf("-------------snapshot------------\n");
947 printf("Event time: %" PRId64 ".%ld\n",
948 (int64_t)snapshot->timestamp.tv_sec,
949 snapshot->timestamp.tv_nsec);
950
951 printf("Event type: ");
952 switch (snapshot->event_type) {
953 case AUDIO_THREAD_EVENT_BUSYLOOP:
954 printf("busyloop\n");
955 break;
956 case AUDIO_THREAD_EVENT_UNDERRUN:
957 printf("underrun\n");
958 break;
959 case AUDIO_THREAD_EVENT_SEVERE_UNDERRUN:
960 printf("severe underrun\n");
961 break;
962 case AUDIO_THREAD_EVENT_DROP_SAMPLES:
963 printf("drop samples\n");
964 break;
965 case AUDIO_THREAD_EVENT_DEBUG:
966 printf("debug\n");
967 break;
968 default:
969 printf("no such type\n");
970 }
971 print_audio_debug_info(&snapshot->audio_debug_info);
972 }
973
audio_thread_snapshots(struct cras_client * client)974 static void audio_thread_snapshots(struct cras_client *client)
975 {
976 const struct cras_audio_thread_snapshot_buffer *snapshot_buffer;
977 uint32_t i;
978 int j;
979 int count = 0;
980
981 snapshot_buffer = cras_client_get_audio_thread_snapshot_buffer(client);
982 i = snapshot_buffer->pos;
983 for (j = 0; j < CRAS_MAX_AUDIO_THREAD_SNAPSHOTS; j++) {
984 if (snapshot_buffer->snapshots[i].timestamp.tv_sec ||
985 snapshot_buffer->snapshots[i].timestamp.tv_nsec) {
986 print_cras_audio_thread_snapshot(
987 &snapshot_buffer->snapshots[i]);
988 count++;
989 }
990 i++;
991 i %= CRAS_MAX_AUDIO_THREAD_SNAPSHOTS;
992 }
993 printf("There are %d, snapshots.\n", count);
994
995 /* Signal main thread we are done after the last chunk. */
996 pthread_mutex_lock(&done_mutex);
997 pthread_cond_signal(&done_cond);
998 pthread_mutex_unlock(&done_mutex);
999 }
1000
start_stream(struct cras_client * client,cras_stream_id_t * stream_id,struct cras_stream_params * params,float stream_volume)1001 static int start_stream(struct cras_client *client, cras_stream_id_t *stream_id,
1002 struct cras_stream_params *params, float stream_volume)
1003 {
1004 int rc;
1005
1006 if (pin_device_id)
1007 rc = cras_client_add_pinned_stream(client, pin_device_id,
1008 stream_id, params);
1009 else
1010 rc = cras_client_add_stream(client, stream_id, params);
1011 if (rc < 0) {
1012 fprintf(stderr, "adding a stream %d\n", rc);
1013 return rc;
1014 }
1015 return cras_client_set_stream_volume(client, *stream_id, stream_volume);
1016 }
1017
parse_channel_layout(char * channel_layout_str,int8_t channel_layout[CRAS_CH_MAX])1018 static int parse_channel_layout(char *channel_layout_str,
1019 int8_t channel_layout[CRAS_CH_MAX])
1020 {
1021 int i = 0;
1022 char *chp;
1023
1024 chp = strtok(channel_layout_str, ",");
1025 while (chp && i < CRAS_CH_MAX) {
1026 channel_layout[i++] = atoi(chp);
1027 chp = strtok(NULL, ",");
1028 }
1029
1030 return 0;
1031 }
1032
run_aecdump(struct cras_client * client,uint64_t stream_id,int start)1033 static void run_aecdump(struct cras_client *client, uint64_t stream_id,
1034 int start)
1035 {
1036 int aecdump_fd;
1037 if (start) {
1038 aecdump_fd =
1039 open(aecdump_file, O_CREAT | O_RDWR | O_TRUNC, 0666);
1040 if (aecdump_fd == -1) {
1041 printf("Fail to open file %s", aecdump_file);
1042 return;
1043 }
1044
1045 printf("Dumping AEC info to %s, stream %" PRId64 ", fd %d\n",
1046 aecdump_file, stream_id, aecdump_fd);
1047 cras_client_set_aec_dump(client, stream_id, 1, aecdump_fd);
1048 } else {
1049 cras_client_set_aec_dump(client, stream_id, 0, -1);
1050 printf("Close AEC dump file %s\n", aecdump_file);
1051 }
1052 }
1053
run_file_io_stream(struct cras_client * client,int fd,enum CRAS_STREAM_DIRECTION direction,size_t block_size,enum CRAS_STREAM_TYPE stream_type,size_t rate,snd_pcm_format_t format,size_t num_channels,uint32_t flags,int is_loopback,int is_post_dsp)1054 static int run_file_io_stream(struct cras_client *client, int fd,
1055 enum CRAS_STREAM_DIRECTION direction,
1056 size_t block_size,
1057 enum CRAS_STREAM_TYPE stream_type, size_t rate,
1058 snd_pcm_format_t format, size_t num_channels,
1059 uint32_t flags, int is_loopback, int is_post_dsp)
1060 {
1061 int rc, tty;
1062 struct cras_stream_params *params;
1063 cras_unified_cb_t aud_cb;
1064 cras_stream_id_t stream_id = 0;
1065 int stream_playing = 0;
1066 int *pfd = malloc(sizeof(*pfd));
1067 *pfd = fd;
1068 fd_set poll_set;
1069 struct timespec sleep_ts;
1070 float volume_scaler = 1.0;
1071 size_t sys_volume = 100;
1072 long cap_gain = 0;
1073 int mute = 0;
1074 int8_t layout[CRAS_CH_MAX];
1075
1076 /* Set the sleep interval between latency/RMS prints. */
1077 sleep_ts.tv_sec = 1;
1078 sleep_ts.tv_nsec = 0;
1079
1080 /* Open the pipe file descriptor. */
1081 rc = pipe(pipefd);
1082 if (rc == -1) {
1083 perror("failed to open pipe");
1084 return -errno;
1085 }
1086
1087 /* Reset the total RMS value. */
1088 total_rms_sqr_sum = 0;
1089 total_rms_size = 0;
1090
1091 if (direction == CRAS_STREAM_INPUT)
1092 aud_cb = got_samples;
1093 else
1094 aud_cb = put_samples;
1095
1096 if (fd == 0) {
1097 if (direction != CRAS_STREAM_OUTPUT)
1098 return -EINVAL;
1099 aud_cb = put_stdin_samples;
1100 }
1101
1102 aud_format = cras_audio_format_create(format, rate, num_channels);
1103 if (aud_format == NULL)
1104 return -ENOMEM;
1105
1106 if (channel_layout) {
1107 /* Set channel layout to format */
1108 parse_channel_layout(channel_layout, layout);
1109 cras_audio_format_set_channel_layout(aud_format, layout);
1110 }
1111
1112 params = cras_client_unified_params_create(direction, block_size,
1113 stream_type, flags, pfd,
1114 aud_cb, stream_error,
1115 aud_format);
1116 if (params == NULL)
1117 return -ENOMEM;
1118
1119 cras_client_stream_params_set_client_type(params,
1120 CRAS_CLIENT_TYPE_TEST);
1121
1122 if (effect_aec)
1123 cras_client_stream_params_enable_aec(params);
1124 if (effect_ns)
1125 cras_client_stream_params_enable_ns(params);
1126 if (effect_agc)
1127 cras_client_stream_params_enable_agc(params);
1128 if (effect_vad)
1129 cras_client_stream_params_enable_vad(params);
1130
1131 cras_client_run_thread(client);
1132 if (is_loopback) {
1133 enum CRAS_NODE_TYPE type =
1134 (is_post_dsp ? CRAS_NODE_TYPE_POST_DSP :
1135 CRAS_NODE_TYPE_POST_MIX_PRE_DSP);
1136
1137 cras_client_connected_wait(client);
1138 pin_device_id = cras_client_get_first_dev_type_idx(
1139 client, type, CRAS_STREAM_INPUT);
1140 }
1141
1142 stream_playing =
1143 start_stream(client, &stream_id, params, volume_scaler) == 0;
1144
1145 tty = open("/dev/tty", O_RDONLY);
1146
1147 // There could be no terminal available when run in autotest.
1148 if (tty == -1)
1149 perror("warning: failed to open /dev/tty");
1150
1151 while (keep_looping) {
1152 char input;
1153 int nread;
1154
1155 FD_ZERO(&poll_set);
1156 if (tty >= 0)
1157 FD_SET(tty, &poll_set);
1158 FD_SET(pipefd[0], &poll_set);
1159 pselect(MAX(tty, pipefd[0]) + 1, &poll_set, NULL, NULL,
1160 show_latency || show_rms ? &sleep_ts : NULL, NULL);
1161
1162 if (stream_playing && show_latency)
1163 print_last_latency();
1164
1165 if (stream_playing && show_rms)
1166 print_last_rms();
1167
1168 if (tty < 0 || !FD_ISSET(tty, &poll_set))
1169 continue;
1170
1171 nread = read(tty, &input, 1);
1172 if (nread < 1) {
1173 fprintf(stderr, "Error reading stdin\n");
1174 return nread;
1175 }
1176 switch (input) {
1177 case 'p':
1178 pause_client = !pause_client;
1179 break;
1180 case 'i':
1181 pause_a_reply = 1;
1182 break;
1183 case 'q':
1184 terminate_stream_loop();
1185 break;
1186 case 's':
1187 if (stream_playing)
1188 break;
1189
1190 /* If started by hand keep running after it finishes. */
1191 exit_after_done_playing = 0;
1192
1193 stream_playing =
1194 start_stream(client, &stream_id, params,
1195 volume_scaler) == 0;
1196 break;
1197 case 'r':
1198 if (!stream_playing)
1199 break;
1200 cras_client_rm_stream(client, stream_id);
1201 stream_playing = 0;
1202 break;
1203 case 'u':
1204 volume_scaler = MIN(volume_scaler + 0.1, 1.0);
1205 cras_client_set_stream_volume(client, stream_id,
1206 volume_scaler);
1207 break;
1208 case 'd':
1209 volume_scaler = MAX(volume_scaler - 0.1, 0.0);
1210 cras_client_set_stream_volume(client, stream_id,
1211 volume_scaler);
1212 break;
1213 case 'k':
1214 sys_volume = MIN(sys_volume + 1, 100);
1215 cras_client_set_system_volume(client, sys_volume);
1216 break;
1217 case 'j':
1218 sys_volume = sys_volume == 0 ? 0 : sys_volume - 1;
1219 cras_client_set_system_volume(client, sys_volume);
1220 break;
1221 case 'K':
1222 cap_gain = MIN(cap_gain + 100, 5000);
1223 cras_client_set_system_capture_gain(client, cap_gain);
1224 break;
1225 case 'J':
1226 cap_gain = cap_gain == -5000 ? -5000 : cap_gain - 100;
1227 cras_client_set_system_capture_gain(client, cap_gain);
1228 break;
1229 case 'm':
1230 mute = !mute;
1231 cras_client_set_system_mute(client, mute);
1232 break;
1233 case '@':
1234 print_device_lists(client);
1235 break;
1236 case '#':
1237 print_attached_client_list(client);
1238 break;
1239 case 'v':
1240 printf("Volume: %zu%s Min dB: %ld Max dB: %ld\n"
1241 "Capture: %ld%s Min dB: %ld Max dB: %ld\n",
1242 cras_client_get_system_volume(client),
1243 cras_client_get_system_muted(client) ?
1244 "(Muted)" :
1245 "",
1246 cras_client_get_system_min_volume(client),
1247 cras_client_get_system_max_volume(client),
1248 cras_client_get_system_capture_gain(client),
1249 cras_client_get_system_capture_muted(client) ?
1250 "(Muted)" :
1251 "",
1252 cras_client_get_system_min_capture_gain(client),
1253 cras_client_get_system_max_capture_gain(client));
1254 break;
1255 case '\'':
1256 play_short_sound_periods_left =
1257 play_short_sound_periods;
1258 break;
1259 case '\n':
1260 break;
1261 default:
1262 printf("Invalid key\n");
1263 break;
1264 }
1265 }
1266
1267 if (show_total_rms)
1268 print_total_rms();
1269
1270 cras_client_stop(client);
1271
1272 cras_audio_format_destroy(aud_format);
1273 cras_client_stream_params_destroy(params);
1274 free(pfd);
1275
1276 close(pipefd[0]);
1277 close(pipefd[1]);
1278
1279 return 0;
1280 }
1281
run_capture(struct cras_client * client,const char * file,size_t block_size,enum CRAS_STREAM_TYPE stream_type,size_t rate,snd_pcm_format_t format,size_t num_channels,uint32_t flags,int is_loopback,int is_post_dsp)1282 static int run_capture(struct cras_client *client, const char *file,
1283 size_t block_size, enum CRAS_STREAM_TYPE stream_type,
1284 size_t rate, snd_pcm_format_t format,
1285 size_t num_channels, uint32_t flags, int is_loopback,
1286 int is_post_dsp)
1287 {
1288 int fd = open(file, O_CREAT | O_RDWR | O_TRUNC, 0666);
1289 if (fd == -1) {
1290 perror("failed to open file");
1291 return -errno;
1292 }
1293
1294 run_file_io_stream(client, fd, CRAS_STREAM_INPUT, block_size,
1295 stream_type, rate, format, num_channels, flags,
1296 is_loopback, is_post_dsp);
1297
1298 close(fd);
1299 return 0;
1300 }
1301
run_playback(struct cras_client * client,const char * file,size_t block_size,enum CRAS_STREAM_TYPE stream_type,size_t rate,snd_pcm_format_t format,size_t num_channels)1302 static int run_playback(struct cras_client *client, const char *file,
1303 size_t block_size, enum CRAS_STREAM_TYPE stream_type,
1304 size_t rate, snd_pcm_format_t format,
1305 size_t num_channels)
1306 {
1307 int fd;
1308
1309 fd = open(file, O_RDONLY);
1310 if (fd == -1) {
1311 perror("failed to open file");
1312 return -errno;
1313 }
1314
1315 run_file_io_stream(client, fd, CRAS_STREAM_OUTPUT, block_size,
1316 stream_type, rate, format, num_channels, 0, 0, 0);
1317
1318 close(fd);
1319 return 0;
1320 }
1321
print_server_info(struct cras_client * client)1322 static void print_server_info(struct cras_client *client)
1323 {
1324 cras_client_run_thread(client);
1325 cras_client_connected_wait(client); /* To synchronize data. */
1326 print_system_volumes(client);
1327 print_user_muted(client);
1328 print_device_lists(client);
1329 print_attached_client_list(client);
1330 print_active_stream_info(client);
1331 }
1332
show_audio_thread_snapshots(struct cras_client * client)1333 static void show_audio_thread_snapshots(struct cras_client *client)
1334 {
1335 struct timespec wait_time;
1336
1337 cras_client_run_thread(client);
1338 cras_client_connected_wait(client); /* To synchronize data. */
1339 cras_client_update_audio_thread_snapshots(client,
1340 audio_thread_snapshots);
1341
1342 clock_gettime(CLOCK_REALTIME, &wait_time);
1343 wait_time.tv_sec += 2;
1344
1345 pthread_mutex_lock(&done_mutex);
1346 pthread_cond_timedwait(&done_cond, &done_mutex, &wait_time);
1347 pthread_mutex_unlock(&done_mutex);
1348 }
1349
show_audio_debug_info(struct cras_client * client)1350 static void show_audio_debug_info(struct cras_client *client)
1351 {
1352 struct timespec wait_time;
1353
1354 cras_client_run_thread(client);
1355 cras_client_connected_wait(client); /* To synchronize data. */
1356 cras_client_update_audio_debug_info(client, audio_debug_info);
1357
1358 clock_gettime(CLOCK_REALTIME, &wait_time);
1359 wait_time.tv_sec += 2;
1360
1361 pthread_mutex_lock(&done_mutex);
1362 pthread_cond_timedwait(&done_cond, &done_mutex, &wait_time);
1363 pthread_mutex_unlock(&done_mutex);
1364 }
1365
show_cras_bt_debug_info(struct cras_client * client)1366 static void show_cras_bt_debug_info(struct cras_client *client)
1367 {
1368 struct timespec wait_time;
1369
1370 cras_client_run_thread(client);
1371 cras_client_connected_wait(client); /* To synchronize data. */
1372 cras_client_update_bt_debug_info(client, cras_bt_debug_info);
1373
1374 clock_gettime(CLOCK_REALTIME, &wait_time);
1375 wait_time.tv_sec += 2;
1376
1377 pthread_mutex_lock(&done_mutex);
1378 pthread_cond_timedwait(&done_cond, &done_mutex, &wait_time);
1379 pthread_mutex_unlock(&done_mutex);
1380 }
1381
hotword_models_cb(struct cras_client * client,const char * hotword_models)1382 static void hotword_models_cb(struct cras_client *client,
1383 const char *hotword_models)
1384 {
1385 printf("Hotword models: %s\n", hotword_models);
1386 }
1387
print_hotword_models(struct cras_client * client,cras_node_id_t id)1388 static void print_hotword_models(struct cras_client *client, cras_node_id_t id)
1389 {
1390 struct timespec wait_time;
1391
1392 cras_client_run_thread(client);
1393 cras_client_connected_wait(client);
1394 cras_client_get_hotword_models(client, id, hotword_models_cb);
1395
1396 clock_gettime(CLOCK_REALTIME, &wait_time);
1397 wait_time.tv_sec += 2;
1398
1399 pthread_mutex_lock(&done_mutex);
1400 pthread_cond_timedwait(&done_cond, &done_mutex, &wait_time);
1401 pthread_mutex_unlock(&done_mutex);
1402 }
1403
check_output_plugged(struct cras_client * client,const char * name)1404 static void check_output_plugged(struct cras_client *client, const char *name)
1405 {
1406 cras_client_run_thread(client);
1407 cras_client_connected_wait(client); /* To synchronize data. */
1408 printf("%s\n",
1409 cras_client_output_dev_plugged(client, name) ? "Yes" : "No");
1410 }
1411
1412 /* Repeatedly mute and unmute the output until there is an error. */
mute_loop_test(struct cras_client * client,int auto_reconnect)1413 static void mute_loop_test(struct cras_client *client, int auto_reconnect)
1414 {
1415 int mute = 0;
1416 int rc;
1417
1418 if (auto_reconnect)
1419 cras_client_run_thread(client);
1420 while (1) {
1421 rc = cras_client_set_user_mute(client, mute);
1422 printf("cras_client_set_user_mute(%d): %d\n", mute, rc);
1423 if (rc != 0 && !auto_reconnect)
1424 return;
1425 mute = !mute;
1426 sleep(2);
1427 }
1428 }
1429
show_atlog(time_t sec_offset,int32_t nsec_offset,struct audio_thread_event_log * log,int len,uint64_t missing)1430 static void show_atlog(time_t sec_offset, int32_t nsec_offset,
1431 struct audio_thread_event_log *log, int len,
1432 uint64_t missing)
1433 {
1434 int i;
1435 printf("Audio Thread Event Log:\n");
1436
1437 if (missing)
1438 printf("%" PRIu64 " logs are missing.\n", missing);
1439
1440 for (i = 0; i < len; ++i) {
1441 show_alog_tag(log, i, sec_offset, nsec_offset);
1442 }
1443 }
1444
unlock_main_thread(struct cras_client * client)1445 static void unlock_main_thread(struct cras_client *client)
1446 {
1447 pthread_mutex_lock(&done_mutex);
1448 pthread_cond_signal(&done_cond);
1449 pthread_mutex_unlock(&done_mutex);
1450 }
1451
cras_show_continuous_atlog(struct cras_client * client)1452 static void cras_show_continuous_atlog(struct cras_client *client)
1453 {
1454 struct audio_thread_event_log log;
1455 struct timespec wait_time;
1456 static time_t sec_offset;
1457 static int32_t nsec_offset;
1458 static uint64_t atlog_read_idx = 0, missing;
1459 int len, rc;
1460
1461 cras_client_run_thread(client);
1462 cras_client_connected_wait(client); /* To synchronize data. */
1463 cras_client_get_atlog_access(client, unlock_main_thread);
1464
1465 clock_gettime(CLOCK_REALTIME, &wait_time);
1466 wait_time.tv_sec += 2;
1467
1468 pthread_mutex_lock(&done_mutex);
1469 rc = pthread_cond_timedwait(&done_cond, &done_mutex, &wait_time);
1470 pthread_mutex_unlock(&done_mutex);
1471
1472 if (rc)
1473 goto fail;
1474
1475 fill_time_offset(&sec_offset, &nsec_offset);
1476
1477 while (1) {
1478 len = cras_client_read_atlog(client, &atlog_read_idx, &missing,
1479 &log);
1480
1481 if (len < 0)
1482 break;
1483 if (len > 0)
1484 show_atlog(sec_offset, nsec_offset, &log, len, missing);
1485 nanosleep(&follow_atlog_sleep_ts, NULL);
1486 }
1487 fail:
1488 printf("Failed to get audio thread log.\n");
1489 }
1490
1491 // clang-format off
1492 static struct option long_options[] = {
1493 {"show_latency", no_argument, &show_latency, 1},
1494 {"show_rms", no_argument, &show_rms, 1},
1495 {"show_total_rms", no_argument, &show_total_rms, 1},
1496 {"select_input", required_argument, 0, 'a'},
1497 {"block_size", required_argument, 0, 'b'},
1498 {"num_channels", required_argument, 0, 'c'},
1499 {"duration_seconds", required_argument, 0, 'd'},
1500 {"dump_events", no_argument, 0, 'e'},
1501 {"format", required_argument, 0, 'f'},
1502 {"capture_gain", required_argument, 0, 'g'},
1503 {"help", no_argument, 0, 'h'},
1504 {"dump_server_info", no_argument, 0, 'i'},
1505 {"check_output_plugged",required_argument, 0, 'j'},
1506 {"add_active_input", required_argument, 0, 'k'},
1507 {"dump_dsp", no_argument, 0, 'l'},
1508 {"dump_audio_thread", no_argument, 0, 'm'},
1509 {"syslog_mask", required_argument, 0, 'n'},
1510 {"channel_layout", required_argument, 0, 'o'},
1511 {"get_aec_group_id", no_argument, 0, 'p'},
1512 {"user_mute", required_argument, 0, 'q'},
1513 {"rate", required_argument, 0, 'r'},
1514 {"reload_dsp", no_argument, 0, 's'},
1515 {"add_active_output", required_argument, 0, 't'},
1516 {"mute", required_argument, 0, 'u'},
1517 {"volume", required_argument, 0, 'v'},
1518 {"set_node_volume", required_argument, 0, 'w'},
1519 {"plug", required_argument, 0, 'x'},
1520 {"select_output", required_argument, 0, 'y'},
1521 {"playback_delay_us", required_argument, 0, 'z'},
1522 {"capture_mute", required_argument, 0, '0'},
1523 {"rm_active_input", required_argument, 0, '1'},
1524 {"rm_active_output", required_argument, 0, '2'},
1525 {"swap_left_right", required_argument, 0, '3'},
1526 {"version", no_argument, 0, '4'},
1527 {"add_test_dev", required_argument, 0, '5'},
1528 {"test_hotword_file", required_argument, 0, '6'},
1529 {"listen_for_hotword", required_argument, 0, '7'},
1530 {"pin_device", required_argument, 0, '8'},
1531 {"suspend", required_argument, 0, '9'},
1532 {"set_node_gain", required_argument, 0, ':'},
1533 {"play_short_sound", required_argument, 0, '!'},
1534 {"config_global_remix", required_argument, 0, ';'},
1535 {"set_hotword_model", required_argument, 0, '<'},
1536 {"get_hotword_models", required_argument, 0, '>'},
1537 {"post_dsp", required_argument, 0, 'A'},
1538 {"stream_id", required_argument, 0, 'B'},
1539 {"capture_file", required_argument, 0, 'C'},
1540 {"reload_aec_config", no_argument, 0, 'D'},
1541 {"effects", required_argument, 0, 'E'},
1542 {"get_aec_supported", no_argument, 0, 'F'},
1543 {"aecdump", required_argument, 0, 'G'},
1544 {"dump_bt", no_argument, 0, 'H'},
1545 {"set_wbs_enabled", required_argument, 0, 'I'},
1546 {"follow_atlog", no_argument, 0, 'J'},
1547 {"connection_type", required_argument, 0, 'K'},
1548 {"loopback_file", required_argument, 0, 'L'},
1549 {"mute_loop_test", required_argument, 0, 'M'},
1550 {"playback_file", required_argument, 0, 'P'},
1551 {"stream_type", required_argument, 0, 'T'},
1552 {0, 0, 0, 0}
1553 };
1554 // clang-format on
1555
show_usage()1556 static void show_usage()
1557 {
1558 int i;
1559
1560 printf("--add_active_input <N>:<M> - "
1561 "Add the ionode with the given id to active input device "
1562 "list\n");
1563 printf("--add_active_output <N>:<M> - "
1564 "Add the ionode with the given id to active output device "
1565 "list\n");
1566 printf("--add_test_dev <type> - "
1567 "Add a test iodev.\n");
1568 printf("--block_size <N> - "
1569 "The number for frames per callback(dictates latency).\n");
1570 printf("--capture_file <name> - "
1571 "Name of file to record to.\n");
1572 printf("--capture_gain <dB> - "
1573 "Set system caputre gain in dB*100 (100 = 1dB).\n");
1574 printf("--capture_mute <0|1> - "
1575 "Set capture mute state.\n");
1576 printf("--channel_layout <layout_str> - "
1577 "Set multiple channel layout.\n");
1578 printf("--check_output_plugged <output name> - "
1579 "Check if the output is plugged in\n");
1580 printf("--connection_type <connection_type> - "
1581 "Set cras_client connection_type (default to 0).\n"
1582 " "
1583 "Argument: 0 - For control client.\n"
1584 " "
1585 " 1 - For playback client.\n"
1586 " "
1587 " 2 - For capture client.\n");
1588 printf("--dump_audio_thread - "
1589 "Dumps audio thread info.\n");
1590 printf("--dump_bt - "
1591 "Dumps debug info for bt audio\n");
1592 printf("--dump_dsp - "
1593 "Print status of dsp to syslog.\n");
1594 printf("--dump_server_info - "
1595 "Print status of the server.\n");
1596 printf("--duration_seconds <N> - "
1597 "Seconds to record or playback.\n");
1598 printf("--follow_atlog - "
1599 "Continuously dumps audio thread event log.\n");
1600 printf("--format <name> - "
1601 "The sample format. Either ");
1602 for (i = 0; supported_formats[i].name; ++i)
1603 printf("%s ", supported_formats[i].name);
1604 printf("(default to S16_LE).\n");
1605 printf("--get_hotword_models <N>:<M> - "
1606 "Get the supported hotword models of node\n");
1607 printf("--help - "
1608 "Print this message.\n");
1609 printf("--listen_for_hotword <name> - "
1610 "Listen and capture hotword stream if supported\n");
1611 printf("--loopback_file <name> - "
1612 "Name of file to record from loopback device.\n");
1613 printf("--mute <0|1> - "
1614 "Set system mute state.\n");
1615 printf("--mute_loop_test <0|1> - "
1616 "Continuously loop mute/umute.\n"
1617 " "
1618 "Argument: 0 - stop on error.\n"
1619 " "
1620 " 1 - automatically reconnect to CRAS.\n");
1621 printf("--num_channels <N> - "
1622 "Two for stereo.\n");
1623 printf("--pin_device <N> - "
1624 "Playback/Capture only on the given device.\n");
1625 printf("--playback_file <name> - "
1626 "Name of file to play, "
1627 "\"-\" to playback raw audio from stdin.\n");
1628 printf("--play_short_sound <N> - "
1629 "Plays the content in the file for N periods when ' "
1630 "is pressed.\n");
1631 printf("--plug <N>:<M>:<0|1> - "
1632 "Set the plug state (0 or 1) for the ionode with the given "
1633 "index M on the device with index N\n");
1634 printf("--rate <N> - "
1635 "Specifies the sample rate in Hz.\n");
1636 printf("--reload_dsp - "
1637 "Reload dsp configuration from the ini file\n");
1638 printf("--rm_active_input <N>:<M> - "
1639 "Removes the ionode with the given id from active input device "
1640 "list\n");
1641 printf("--rm_active_output <N>:<M> - "
1642 "Removes the ionode with the given id from active output device "
1643 "list\n");
1644 printf("--select_input <N>:<M> - "
1645 "Select the ionode with the given id as preferred input\n");
1646 printf("--select_output <N>:<M> - "
1647 "Select the ionode with the given id as preferred output\n");
1648 printf("--set_hotword_model <N>:<M>:<model> - "
1649 "Set the model to node\n");
1650 printf("--playback_delay_us <N> - "
1651 "Set the time in us to delay a reply for playback when i is "
1652 "pressed\n");
1653 printf("--post_dsp <0|1> - "
1654 "Use this flag with --loopback_file. The default value is 0.\n"
1655 " "
1656 "Argument: 0 - Record from post-mix, pre-DSP loopback device.\n"
1657 " "
1658 " 1 - Record from post-DSP loopback device.\n");
1659 printf("--set_node_volume <N>:<M>:<0-100> - "
1660 "Set the volume of the ionode with the given id\n");
1661 printf("--show_latency - "
1662 "Display latency while playing or recording.\n");
1663 printf("--show_rms - "
1664 "Display RMS value of loopback stream.\n");
1665 printf("--show_total_rms - "
1666 "Display total RMS value of loopback stream at the end.\n");
1667 printf("--suspend <0|1> - "
1668 "Set audio suspend state.\n");
1669 printf("--swap_left_right <N>:<M>:<0|1> - "
1670 "Swap or unswap (1 or 0) the left and right channel for the "
1671 "ionode with the given index M on the device with index N\n");
1672 printf("--stream_type <N> - "
1673 "Specify the type of the stream.\n");
1674 printf("--syslog_mask <n> - "
1675 "Set the syslog mask to the given log level.\n");
1676 printf("--test_hotword_file <N>:<filename> - "
1677 "Use filename as a hotword buffer for device N\n");
1678 printf("--user_mute <0|1> - "
1679 "Set user mute state.\n");
1680 printf("--version - "
1681 "Print the git commit ID that was used to build the client.\n");
1682 printf("--volume <0-100> - "
1683 "Set system output volume.\n");
1684 }
1685
cras_client_create_and_connect(struct cras_client ** client,enum CRAS_CONNECTION_TYPE conn_type)1686 static int cras_client_create_and_connect(struct cras_client **client,
1687 enum CRAS_CONNECTION_TYPE conn_type)
1688 {
1689 int rc;
1690
1691 rc = cras_client_create_with_type(client, conn_type);
1692 if (rc < 0) {
1693 fprintf(stderr, "Couldn't create client.\n");
1694 return rc;
1695 }
1696
1697 rc = cras_client_connect_timeout(*client, 1000);
1698 if (rc) {
1699 fprintf(stderr, "Couldn't connect to server.\n");
1700 cras_client_destroy(*client);
1701 return rc;
1702 }
1703
1704 return 0;
1705 }
1706
main(int argc,char ** argv)1707 int main(int argc, char **argv)
1708 {
1709 struct cras_client *client;
1710 int c, option_index;
1711 size_t block_size = NOT_ASSIGNED;
1712 size_t rate = 48000;
1713 size_t num_channels = 2;
1714 float duration_seconds = 0;
1715 const char *capture_file = NULL;
1716 const char *playback_file = NULL;
1717 const char *loopback_file = NULL;
1718 int post_dsp = 0;
1719 enum CRAS_STREAM_TYPE stream_type = CRAS_STREAM_TYPE_DEFAULT;
1720 int rc = 0;
1721 uint32_t stream_flags = 0;
1722 cras_stream_id_t stream_id = 0;
1723 snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
1724 enum CRAS_CONNECTION_TYPE conn_type = CRAS_CONTROL;
1725 enum CRAS_CONNECTION_TYPE new_conn_type;
1726
1727 option_index = 0;
1728 openlog("cras_test_client", LOG_PERROR, LOG_USER);
1729 setlogmask(LOG_UPTO(LOG_INFO));
1730
1731 rc = cras_client_create_and_connect(&client, conn_type);
1732 if (rc) {
1733 return rc;
1734 }
1735
1736 if (argc == 1) {
1737 /* Nothing specified, default to dump_server_info. */
1738 print_server_info(client);
1739 goto destroy_exit;
1740 }
1741
1742 while (1) {
1743 c = getopt_long(argc, argv, "o:s:P:C:r:c:f:h", long_options,
1744 &option_index);
1745 if (c == -1)
1746 break;
1747 switch (c) {
1748 case 'y':
1749 case 'a': {
1750 cras_node_id_t id;
1751 rc = parse_node_id(optarg, &id);
1752 if (rc) {
1753 show_usage();
1754 return rc;
1755 }
1756
1757 enum CRAS_STREAM_DIRECTION direction =
1758 (c == 'y') ? CRAS_STREAM_OUTPUT :
1759 CRAS_STREAM_INPUT;
1760 cras_client_select_node(client, direction, id);
1761 break;
1762 }
1763 case 'b':
1764 block_size = atoi(optarg);
1765 break;
1766 case 'c':
1767 num_channels = atoi(optarg);
1768 break;
1769 case 'd':
1770 duration_seconds = atof(optarg);
1771 break;
1772 case 'e':
1773 show_audio_thread_snapshots(client);
1774 break;
1775 case 'f': {
1776 int i;
1777
1778 for (i = 0; supported_formats[i].name; ++i) {
1779 if (strcasecmp(optarg,
1780 supported_formats[i].name) ==
1781 0) {
1782 format = supported_formats[i].format;
1783 break;
1784 }
1785 }
1786
1787 if (!supported_formats[i].name) {
1788 printf("Unsupported format: %s\n", optarg);
1789 return -EINVAL;
1790 }
1791 break;
1792 }
1793 case 'g': {
1794 long gain = atol(optarg);
1795 rc = cras_client_set_system_capture_gain(client, gain);
1796 if (rc < 0) {
1797 fprintf(stderr, "problem setting capture\n");
1798 goto destroy_exit;
1799 }
1800 break;
1801 }
1802 case 'h':
1803 show_usage();
1804 break;
1805 case 'i':
1806 print_server_info(client);
1807 break;
1808 case 'j':
1809 check_output_plugged(client, optarg);
1810 break;
1811 case 'k':
1812 case 't':
1813 case '1':
1814 case '2': {
1815 cras_node_id_t id;
1816 rc = parse_node_id(optarg, &id);
1817 if (rc) {
1818 show_usage();
1819 return rc;
1820 }
1821
1822 enum CRAS_STREAM_DIRECTION dir;
1823 if (c == 't' || c == '2')
1824 dir = CRAS_STREAM_OUTPUT;
1825 else
1826 dir = CRAS_STREAM_INPUT;
1827
1828 if (c == 'k' || c == 't')
1829 cras_client_add_active_node(client, dir, id);
1830 else
1831 cras_client_rm_active_node(client, dir, id);
1832 break;
1833 }
1834 case 'l':
1835 cras_client_dump_dsp_info(client);
1836 break;
1837 case 'm':
1838 show_audio_debug_info(client);
1839 break;
1840 case 'n': {
1841 int log_level = atoi(optarg);
1842
1843 setlogmask(LOG_UPTO(log_level));
1844 break;
1845 }
1846 case 'o':
1847 channel_layout = optarg;
1848 break;
1849 case 'p':
1850 printf("AEC group ID %d\n",
1851 cras_client_get_aec_group_id(client));
1852 break;
1853 case 'q': {
1854 int mute = atoi(optarg);
1855 rc = cras_client_set_user_mute(client, mute);
1856 if (rc < 0) {
1857 fprintf(stderr, "problem setting mute\n");
1858 goto destroy_exit;
1859 }
1860 break;
1861 }
1862 case 'r':
1863 rate = atoi(optarg);
1864 break;
1865 case 's':
1866 cras_client_reload_dsp(client);
1867 break;
1868 case 'u': {
1869 int mute = atoi(optarg);
1870 rc = cras_client_set_system_mute(client, mute);
1871 if (rc < 0) {
1872 fprintf(stderr, "problem setting mute\n");
1873 goto destroy_exit;
1874 }
1875 break;
1876 }
1877 case 'v': {
1878 int volume = atoi(optarg);
1879 volume = MIN(100, MAX(0, volume));
1880 rc = cras_client_set_system_volume(client, volume);
1881 if (rc < 0) {
1882 fprintf(stderr, "problem setting volume\n");
1883 goto destroy_exit;
1884 }
1885 break;
1886 }
1887 case ':':
1888 case 'w': {
1889 cras_node_id_t id;
1890 int value;
1891 rc = parse_node_id_with_value(optarg, &id, &value);
1892 if (rc) {
1893 show_usage();
1894 return rc;
1895 }
1896
1897 if (c == 'w')
1898 cras_client_set_node_volume(client, id, value);
1899 else
1900 cras_client_set_node_capture_gain(client, id,
1901 value);
1902 break;
1903 }
1904 case 'x': {
1905 cras_node_id_t id;
1906 int value;
1907 rc = parse_node_id_with_value(optarg, &id, &value);
1908 if (rc) {
1909 show_usage();
1910 return rc;
1911 }
1912
1913 enum ionode_attr attr = IONODE_ATTR_PLUGGED;
1914 cras_client_set_node_attr(client, id, attr, value);
1915 break;
1916 }
1917 case 'z':
1918 pause_in_playback_reply = atoi(optarg);
1919 break;
1920
1921 case '0': {
1922 int mute = atoi(optarg);
1923 rc = cras_client_set_system_capture_mute(client, mute);
1924 if (rc < 0) {
1925 fprintf(stderr, "problem setting mute\n");
1926 goto destroy_exit;
1927 }
1928 break;
1929 }
1930 case '3': {
1931 cras_node_id_t id;
1932 int value;
1933 rc = parse_node_id_with_value(optarg, &id, &value);
1934 if (rc) {
1935 show_usage();
1936 return rc;
1937 }
1938
1939 cras_client_swap_node_left_right(client, id, value);
1940 break;
1941 }
1942 case '4':
1943 printf("%s\n", VCSID);
1944 break;
1945 case '5': {
1946 cras_client_add_test_iodev(client, atoi(optarg));
1947 break;
1948 }
1949 case '6': {
1950 const char *s;
1951 int dev_index;
1952
1953 s = strtok(optarg, ":");
1954 if (!s) {
1955 show_usage();
1956 return -EINVAL;
1957 }
1958 dev_index = atoi(s);
1959
1960 const char *file_name = strtok(NULL, ":");
1961 if (!file_name) {
1962 show_usage();
1963 return -EINVAL;
1964 }
1965 cras_client_test_iodev_command(
1966 client, dev_index,
1967 TEST_IODEV_CMD_HOTWORD_TRIGGER,
1968 strlen(file_name) + 1, (uint8_t *)file_name);
1969 break;
1970 }
1971 case '7': {
1972 stream_flags = HOTWORD_STREAM;
1973 capture_file = optarg;
1974 break;
1975 }
1976 case '8':
1977 pin_device_id = atoi(optarg);
1978 break;
1979 case '9': {
1980 int suspend = atoi(optarg);
1981 cras_client_set_suspend(client, suspend);
1982 break;
1983 }
1984
1985 case '!': {
1986 play_short_sound = 1;
1987 play_short_sound_periods = atoi(optarg);
1988 break;
1989 }
1990 case ';': {
1991 char *s;
1992 int nch;
1993 int size = 0;
1994 float *coeff;
1995
1996 s = strtok(optarg, ":");
1997 nch = atoi(s);
1998 coeff = (float *)calloc(nch * nch, sizeof(*coeff));
1999 for (size = 0; size < nch * nch; size++) {
2000 s = strtok(NULL, ",");
2001 if (NULL == s)
2002 break;
2003 coeff[size] = atof(s);
2004 }
2005 cras_client_config_global_remix(client, nch, coeff);
2006 free(coeff);
2007 break;
2008 }
2009 case '<':
2010 case '>': {
2011 char *s;
2012 int dev_index;
2013 int node_index;
2014
2015 s = strtok(optarg, ":");
2016 if (!s) {
2017 show_usage();
2018 return -EINVAL;
2019 }
2020 dev_index = atoi(s);
2021
2022 s = strtok(NULL, ":");
2023 if (!s) {
2024 show_usage();
2025 return -EINVAL;
2026 }
2027 node_index = atoi(s);
2028
2029 s = strtok(NULL, ":");
2030 if (!s && c == ';') {
2031 //TODO: c never == ';'
2032 show_usage();
2033 return -EINVAL;
2034 }
2035
2036 cras_node_id_t id =
2037 cras_make_node_id(dev_index, node_index);
2038 if (c == '<')
2039 cras_client_set_hotword_model(client, id, s);
2040 else
2041 print_hotword_models(client, id);
2042 break;
2043 }
2044
2045 case 'A':
2046 post_dsp = atoi(optarg);
2047 break;
2048 case 'B':
2049 stream_id = atoi(optarg);
2050 break;
2051 case 'C':
2052 capture_file = optarg;
2053 break;
2054 case 'D':
2055 cras_client_reload_aec_config(client);
2056 break;
2057 case 'E': {
2058 char *s;
2059
2060 s = strtok(optarg, ",");
2061 while (s) {
2062 if (strcmp("aec", s) == 0)
2063 effect_aec = 1;
2064 else if (strcmp("ns", s) == 0)
2065 effect_ns = 1;
2066 else if (strcmp("agc", s) == 0)
2067 effect_agc = 1;
2068 else if (strcmp("vad", s) == 0)
2069 effect_vad = 1;
2070 else
2071 printf("Unknown effect %s\n", s);
2072 s = strtok(NULL, ",");
2073 }
2074 break;
2075 }
2076 case 'F':
2077 printf("AEC supported %d\n",
2078 !!cras_client_get_aec_supported(client));
2079 break;
2080 case 'G':
2081 aecdump_file = optarg;
2082 break;
2083 case 'H':
2084 show_cras_bt_debug_info(client);
2085 break;
2086 case 'I':
2087 cras_client_set_bt_wbs_enabled(client, atoi(optarg));
2088 break;
2089 case 'J':
2090 cras_show_continuous_atlog(client);
2091 break;
2092 case 'K':
2093 new_conn_type = atoi(optarg);
2094 if (cras_validate_connection_type(new_conn_type)) {
2095 if (new_conn_type != conn_type) {
2096 cras_client_destroy(client);
2097 client = NULL;
2098 rc = cras_client_create_and_connect(
2099 &client, new_conn_type);
2100 if (rc) {
2101 fprintf(stderr,
2102 "Couldn't connect to "
2103 "server.\n");
2104 return rc;
2105 }
2106 conn_type = new_conn_type;
2107 }
2108 } else {
2109 printf("Input connection type is not "
2110 "supported.\n");
2111 }
2112 break;
2113 case 'L':
2114 loopback_file = optarg;
2115 break;
2116 case 'M':
2117 mute_loop_test(client, atoi(optarg));
2118 break;
2119 case 'P':
2120 playback_file = optarg;
2121 break;
2122 case 'T':
2123 stream_type = atoi(optarg);
2124 break;
2125
2126 default:
2127 break;
2128 }
2129 }
2130
2131 duration_frames = duration_seconds * rate;
2132 if (block_size == NOT_ASSIGNED)
2133 block_size = get_block_size(PLAYBACK_BUFFERED_TIME_IN_US, rate);
2134
2135 if (capture_file != NULL) {
2136 if (strcmp(capture_file, "-") == 0)
2137 rc = run_file_io_stream(client, 1, CRAS_STREAM_INPUT,
2138 block_size, stream_type, rate,
2139 format, num_channels,
2140 stream_flags, 0, 0);
2141 else
2142 rc = run_capture(client, capture_file, block_size,
2143 stream_type, rate, format,
2144 num_channels, stream_flags, 0, 0);
2145 } else if (playback_file != NULL) {
2146 if (strcmp(playback_file, "-") == 0)
2147 rc = run_file_io_stream(client, 0, CRAS_STREAM_OUTPUT,
2148 block_size, stream_type, rate,
2149 format, num_channels,
2150 stream_flags, 0, 0);
2151 else
2152 rc = run_playback(client, playback_file, block_size,
2153 stream_type, rate, format,
2154 num_channels);
2155 } else if (loopback_file != NULL) {
2156 rc = run_capture(client, loopback_file, block_size, stream_type,
2157 rate, format, num_channels, stream_flags, 1,
2158 post_dsp);
2159 } else if (aecdump_file != NULL) {
2160 run_aecdump(client, stream_id, 1);
2161 sleep(duration_seconds);
2162 run_aecdump(client, stream_id, 0);
2163 }
2164
2165 destroy_exit:
2166 cras_client_destroy(client);
2167 return rc;
2168 }
2169