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 <math.h>
11 #include <pthread.h>
12 #include <stdio.h>
13 #include <stdint.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <syslog.h>
17 #include <sys/param.h>
18 #include <sys/select.h>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22
23 #include "cras_client.h"
24 #include "cras_types.h"
25 #include "cras_util.h"
26 #include "cras_version.h"
27
28 #define NOT_ASSIGNED (0)
29 #define PLAYBACK_BUFFERED_TIME_IN_US (5000)
30
31 #define BUF_SIZE 32768
32
33 static const size_t MAX_IODEVS = 10; /* Max devices to print out. */
34 static const size_t MAX_IONODES = 20; /* Max ionodes to print out. */
35 static const size_t MAX_ATTACHED_CLIENTS = 10; /* Max clients to print out. */
36
37 static int pipefd[2];
38 static struct timespec last_latency;
39 static int show_latency;
40 static float last_rms_sqr_sum;
41 static int last_rms_size;
42 static float total_rms_sqr_sum;
43 static int total_rms_size;
44 static int show_rms;
45 static int show_total_rms;
46 static int keep_looping = 1;
47 static int exit_after_done_playing = 1;
48 static size_t duration_frames;
49 static int pause_client = 0;
50 static int pause_a_reply = 0;
51 static int pause_in_playback_reply = 1000;
52
53 static char *channel_layout = NULL;
54 static int pin_device_id;
55
56 static int play_short_sound = 0;
57 static int play_short_sound_periods = 0;
58 static int play_short_sound_periods_left = 0;
59
60 static int effect_aec = 0;
61 static int effect_ns = 0;
62 static int effect_agc = 0;
63 static int effect_vad = 0;
64 static char *aecdump_file = NULL;
65
66 /* Conditional so the client thread can signal that main should exit. */
67 static pthread_mutex_t done_mutex = PTHREAD_MUTEX_INITIALIZER;
68 static pthread_cond_t done_cond = PTHREAD_COND_INITIALIZER;
69
70 struct cras_audio_format *aud_format;
71
terminate_stream_loop()72 static int terminate_stream_loop()
73 {
74 keep_looping = 0;
75 return write(pipefd[1], "1", 1);
76 }
77
get_block_size(uint64_t buffer_time_in_us,size_t rate)78 static size_t get_block_size(uint64_t buffer_time_in_us, size_t rate)
79 {
80 return (size_t)(buffer_time_in_us * rate / 1000000);
81 }
82
check_stream_terminate(size_t frames)83 static void check_stream_terminate(size_t frames)
84 {
85 if (duration_frames) {
86 if (duration_frames <= frames)
87 terminate_stream_loop();
88 else
89 duration_frames -= frames;
90 }
91 }
92
93 /* Compute square sum of samples (for calculation of RMS value). */
compute_sqr_sum_16(const int16_t * samples,int size)94 float compute_sqr_sum_16(const int16_t *samples, int size)
95 {
96 unsigned i;
97 float sqr_sum = 0;
98
99 for (i = 0; i < size; i++)
100 sqr_sum += samples[i] * samples[i];
101
102 return sqr_sum;
103 }
104
105 /* Update the RMS values with the given samples. */
update_rms(const uint8_t * samples,int size)106 int update_rms(const uint8_t *samples, int size)
107 {
108 switch (aud_format->format) {
109 case SND_PCM_FORMAT_S16_LE: {
110 last_rms_sqr_sum = compute_sqr_sum_16((int16_t *)samples, size / 2);
111 last_rms_size = size / 2;
112 break;
113 }
114 default:
115 return -EINVAL;
116 }
117
118 total_rms_sqr_sum += last_rms_sqr_sum;
119 total_rms_size += last_rms_size;
120
121 return 0;
122 }
123
124 /* 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)125 static int got_samples(struct cras_client *client,
126 cras_stream_id_t stream_id,
127 uint8_t *captured_samples,
128 uint8_t *playback_samples,
129 unsigned int frames,
130 const struct timespec *captured_time,
131 const struct timespec *playback_time,
132 void *user_arg)
133 {
134 int *fd = (int *)user_arg;
135 int ret;
136 int write_size;
137 int frame_bytes;
138
139 while (pause_client)
140 usleep(10000);
141
142 cras_client_calc_capture_latency(captured_time, &last_latency);
143
144 frame_bytes = cras_client_format_bytes_per_frame(aud_format);
145 write_size = frames * frame_bytes;
146
147 /* Update RMS values with all available frames. */
148 if (keep_looping) {
149 update_rms(captured_samples,
150 MIN(write_size, duration_frames * frame_bytes));
151 }
152
153 check_stream_terminate(frames);
154
155 ret = write(*fd, captured_samples, write_size);
156 if (ret != write_size)
157 printf("Error writing file\n");
158 return frames;
159 }
160
161 /* 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)162 static int put_samples(struct cras_client *client,
163 cras_stream_id_t stream_id,
164 uint8_t *captured_samples,
165 uint8_t *playback_samples,
166 unsigned int frames,
167 const struct timespec *captured_time,
168 const struct timespec *playback_time,
169 void *user_arg)
170 {
171 uint32_t frame_bytes = cras_client_format_bytes_per_frame(aud_format);
172 int fd = *(int *)user_arg;
173 uint8_t buff[BUF_SIZE];
174 int nread;
175
176 while (pause_client)
177 usleep(10000);
178
179 if (pause_a_reply) {
180 usleep(pause_in_playback_reply);
181 pause_a_reply = 0;
182 }
183
184 check_stream_terminate(frames);
185
186 cras_client_calc_playback_latency(playback_time, &last_latency);
187
188 if (play_short_sound) {
189 if (play_short_sound_periods_left)
190 /* Play a period from file. */
191 play_short_sound_periods_left--;
192 else {
193 /* Fill zeros to play silence. */
194 memset(playback_samples, 0,
195 MIN(frames * frame_bytes, BUF_SIZE));
196 return frames;
197 }
198 }
199
200 nread = read(fd, buff, MIN(frames * frame_bytes, BUF_SIZE));
201 if (nread <= 0) {
202 if (exit_after_done_playing)
203 terminate_stream_loop();
204 return nread;
205 }
206
207 memcpy(playback_samples, buff, nread);
208 return nread / frame_bytes;
209 }
210
211 /* Run from callback thread. */
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)212 static int put_stdin_samples(struct cras_client *client,
213 cras_stream_id_t stream_id,
214 uint8_t *captured_samples,
215 uint8_t *playback_samples,
216 unsigned int frames,
217 const struct timespec *captured_time,
218 const struct timespec *playback_time,
219 void *user_arg)
220 {
221 int rc = 0;
222 uint32_t frame_bytes = cras_client_format_bytes_per_frame(aud_format);
223
224 rc = read(0, playback_samples, frames * frame_bytes);
225 if (rc <= 0) {
226 terminate_stream_loop();
227 return -1;
228 }
229
230 return rc / frame_bytes;
231 }
232
stream_error(struct cras_client * client,cras_stream_id_t stream_id,int err,void * arg)233 static int stream_error(struct cras_client *client,
234 cras_stream_id_t stream_id,
235 int err,
236 void *arg)
237 {
238 printf("Stream error %d\n", err);
239 terminate_stream_loop();
240 return 0;
241 }
242
print_last_latency()243 static void print_last_latency()
244 {
245 if (last_latency.tv_sec > 0 || last_latency.tv_nsec > 0)
246 printf("%u.%09u\n", (unsigned)last_latency.tv_sec,
247 (unsigned)last_latency.tv_nsec);
248 else {
249 printf("-%lld.%09lld\n", (long long)-last_latency.tv_sec,
250 (long long)-last_latency.tv_nsec);
251 }
252 }
253
print_last_rms()254 static void print_last_rms()
255 {
256 if (last_rms_size != 0)
257 printf("%.9f\n", sqrt(last_rms_sqr_sum / last_rms_size));
258 }
259
print_total_rms()260 static void print_total_rms()
261 {
262 if (total_rms_size != 0)
263 printf("%.9f\n", sqrt(total_rms_sqr_sum / total_rms_size));
264 }
265
print_dev_info(const struct cras_iodev_info * devs,int num_devs)266 static void print_dev_info(const struct cras_iodev_info *devs, int num_devs)
267 {
268 unsigned i;
269
270 printf("\tID\tName\n");
271 for (i = 0; i < num_devs; i++)
272 printf("\t%u\t%s\n", devs[i].idx, devs[i].name);
273 }
274
print_node_info(const struct cras_ionode_info * nodes,int num_nodes,int is_input)275 static void print_node_info(const struct cras_ionode_info *nodes, int num_nodes,
276 int is_input)
277 {
278 unsigned i;
279
280 printf("\tStable Id\t ID\t%4s Plugged\tL/R swapped\t "
281 "Time Hotword\tType\t\t Name\n", is_input ? "Gain" : " Vol");
282 for (i = 0; i < num_nodes; i++)
283 printf("\t(%08x)\t%u:%u\t%5g %7s\t%14s\t%10ld %-7s\t%-16s%c%s\n",
284 nodes[i].stable_id,
285 nodes[i].iodev_idx,
286 nodes[i].ionode_idx,
287 is_input ? nodes[i].capture_gain / 100.0
288 : (double) nodes[i].volume,
289 nodes[i].plugged ? "yes" : "no",
290 nodes[i].left_right_swapped ? "yes" : "no",
291 (long) nodes[i].plugged_time.tv_sec,
292 nodes[i].active_hotword_model,
293 nodes[i].type,
294 nodes[i].active ? '*' : ' ',
295 nodes[i].name);
296 }
297
print_device_lists(struct cras_client * client)298 static void print_device_lists(struct cras_client *client)
299 {
300 struct cras_iodev_info devs[MAX_IODEVS];
301 struct cras_ionode_info nodes[MAX_IONODES];
302 size_t num_devs, num_nodes;
303 int rc;
304
305 num_devs = MAX_IODEVS;
306 num_nodes = MAX_IONODES;
307 rc = cras_client_get_output_devices(client, devs, nodes, &num_devs,
308 &num_nodes);
309 if (rc < 0)
310 return;
311 printf("Output Devices:\n");
312 print_dev_info(devs, num_devs);
313 printf("Output Nodes:\n");
314 print_node_info(nodes, num_nodes, 0);
315
316 num_devs = MAX_IODEVS;
317 num_nodes = MAX_IONODES;
318 rc = cras_client_get_input_devices(client, devs, nodes, &num_devs,
319 &num_nodes);
320 printf("Input Devices:\n");
321 print_dev_info(devs, num_devs);
322 printf("Input Nodes:\n");
323 print_node_info(nodes, num_nodes, 1);
324 }
325
print_attached_client_list(struct cras_client * client)326 static void print_attached_client_list(struct cras_client *client)
327 {
328 struct cras_attached_client_info clients[MAX_ATTACHED_CLIENTS];
329 size_t i;
330 int num_clients;
331
332 num_clients = cras_client_get_attached_clients(client,
333 clients,
334 MAX_ATTACHED_CLIENTS);
335 if (num_clients < 0)
336 return;
337 num_clients = MIN(num_clients, MAX_ATTACHED_CLIENTS);
338 printf("Attached clients:\n");
339 printf("\tID\tpid\tuid\n");
340 for (i = 0; i < num_clients; i++)
341 printf("\t%u\t%d\t%d\n",
342 clients[i].id,
343 clients[i].pid,
344 clients[i].gid);
345 }
346
print_active_stream_info(struct cras_client * client)347 static void print_active_stream_info(struct cras_client *client)
348 {
349 struct timespec ts;
350 unsigned num_streams;
351
352 num_streams = cras_client_get_num_active_streams(client, &ts);
353 printf("Num active streams: %u\n", num_streams);
354 printf("Last audio active time: %llu, %llu\n",
355 (long long)ts.tv_sec, (long long)ts.tv_nsec);
356 }
357
print_system_volumes(struct cras_client * client)358 static void print_system_volumes(struct cras_client *client)
359 {
360 printf("System Volume (0-100): %zu %s\n"
361 "Capture Gain (%.2f - %.2f): %.2fdB %s\n",
362 cras_client_get_system_volume(client),
363 cras_client_get_system_muted(client) ? "(Muted)" : "",
364 cras_client_get_system_min_capture_gain(client) / 100.0,
365 cras_client_get_system_max_capture_gain(client) / 100.0,
366 cras_client_get_system_capture_gain(client) / 100.0,
367 cras_client_get_system_capture_muted(client) ? "(Muted)" : "");
368 }
369
print_user_muted(struct cras_client * client)370 static void print_user_muted(struct cras_client *client)
371 {
372 printf("User muted: %s\n",
373 cras_client_get_user_muted(client) ? "Muted" : "Not muted");
374 }
375
show_alog_tag(const struct audio_thread_event_log * log,unsigned int tag_idx)376 static void show_alog_tag(const struct audio_thread_event_log *log,
377 unsigned int tag_idx)
378 {
379 unsigned int tag = (log->log[tag_idx].tag_sec >> 24) & 0xff;
380 unsigned int sec = log->log[tag_idx].tag_sec & 0x00ffffff;
381 unsigned int nsec = log->log[tag_idx].nsec;
382 unsigned int data1 = log->log[tag_idx].data1;
383 unsigned int data2 = log->log[tag_idx].data2;
384 unsigned int data3 = log->log[tag_idx].data3;
385
386 /* Skip unused log entries. */
387 if (log->log[tag_idx].tag_sec == 0 && log->log[tag_idx].nsec == 0)
388 return;
389
390 printf("%10u.%09u ", sec, nsec);
391
392 switch (tag) {
393 case AUDIO_THREAD_WAKE:
394 printf("%-30s num_fds:%d\n", "WAKE", (int)data1);
395 break;
396 case AUDIO_THREAD_SLEEP:
397 printf("%-30s sleep:%09d.%09d longest_wake:%09d\n",
398 "SLEEP", (int)data1, (int)data2, (int)data3);
399 break;
400 case AUDIO_THREAD_READ_AUDIO:
401 printf("%-30s dev:%u hw_level:%u read:%u\n",
402 "READ_AUDIO", data1, data2, data3);
403 break;
404 case AUDIO_THREAD_READ_AUDIO_TSTAMP:
405 printf("%-30s dev:%u tstamp:%09d.%09d\n",
406 "READ_AUDIO_TSTAMP", data1, (int)data2, (int)data3);
407 break;
408 case AUDIO_THREAD_READ_AUDIO_DONE:
409 printf("%-30s read_remainder:%u\n", "READ_AUDIO_DONE", data1);
410 break;
411 case AUDIO_THREAD_READ_OVERRUN:
412 printf("%-30s dev:%u stream:%x num_overruns:%u\n",
413 "READ_AUDIO_OVERRUN", data1, data2, data3);
414 break;
415 case AUDIO_THREAD_FILL_AUDIO:
416 printf("%-30s dev:%u hw_level:%u\n",
417 "FILL_AUDIO", data1, data2);
418 break;
419 case AUDIO_THREAD_FILL_AUDIO_TSTAMP:
420 printf("%-30s dev:%u tstamp:%09d.%09d\n",
421 "FILL_AUDIO_TSTAMP", data1, (int)data2, (int)data3);
422 break;
423 case AUDIO_THREAD_FILL_AUDIO_DONE:
424 printf("%-30s hw_level:%u total_written:%u min_cb_level:%u\n",
425 "FILL_AUDIO_DONE", data1, data2, data3);
426 break;
427 case AUDIO_THREAD_WRITE_STREAMS_WAIT:
428 printf("%-30s stream:%x\n", "WRITE_STREAMS_WAIT", data1);
429 break;
430 case AUDIO_THREAD_WRITE_STREAMS_WAIT_TO:
431 printf("%-30s\n", "WRITE_STREAMS_WAIT_TO");
432 break;
433 case AUDIO_THREAD_WRITE_STREAMS_MIX:
434 printf("%-30s write_limit:%u max_offset:%u\n",
435 "WRITE_STREAMS_MIX", data1, data2);
436 break;
437 case AUDIO_THREAD_WRITE_STREAMS_MIXED:
438 printf("%-30s write_limit:%u\n", "WRITE_STREAMS_MIXED", data1);
439 break;
440 case AUDIO_THREAD_WRITE_STREAMS_STREAM:
441 printf("%-30s id:%x shm_frames:%u cb_pending:%u\n",
442 "WRITE_STREAMS_STREAM", data1, data2, data3);
443 break;
444 case AUDIO_THREAD_FETCH_STREAM:
445 printf("%-30s id:%x cbth:%u delay:%u\n",
446 "WRITE_STREAMS_FETCH_STREAM", data1, data2, data3);
447 break;
448 case AUDIO_THREAD_STREAM_ADDED:
449 printf("%-30s id:%x dev:%u\n",
450 "STREAM_ADDED", data1, data2);
451 break;
452 case AUDIO_THREAD_STREAM_REMOVED:
453 printf("%-30s id:%x\n", "STREAM_REMOVED", data1);
454 break;
455 case AUDIO_THREAD_A2DP_ENCODE:
456 printf("%-30s proc:%d queued:%u readable:%u\n",
457 "A2DP_ENCODE", data1, data2, data3);
458 break;
459 case AUDIO_THREAD_A2DP_WRITE:
460 printf("%-30s written:%d queued:%u\n",
461 "A2DP_WRITE", data1, data2);
462 break;
463 case AUDIO_THREAD_DEV_STREAM_MIX:
464 printf("%-30s written:%u read:%u\n",
465 "DEV_STREAM_MIX", data1, data2);
466 break;
467 case AUDIO_THREAD_CAPTURE_POST:
468 printf("%-30s stream:%x thresh:%u rd_buf:%u\n",
469 "CAPTURE_POST", data1, data2, data3);
470 break;
471 case AUDIO_THREAD_CAPTURE_WRITE:
472 printf("%-30s stream:%x write:%u shm_fr:%u\n",
473 "CAPTURE_WRITE", data1, data2, data3);
474 break;
475 case AUDIO_THREAD_CONV_COPY:
476 printf("%-30s wr_buf:%u shm_writable:%u offset:%u\n",
477 "CONV_COPY", data1, data2, data3);
478 break;
479 case AUDIO_THREAD_STREAM_SLEEP_TIME:
480 printf("%-30s id:%x wake:%09u.%09d\n",
481 "STREAM_SLEEP_TIME", data1, (int)data2, (int)data3);
482 break;
483 case AUDIO_THREAD_STREAM_SLEEP_ADJUST:
484 printf("%-30s id:%x from:%09u.%09d\n",
485 "STREAM_SLEEP_ADJUST", data1, data2, data3);
486 break;
487 case AUDIO_THREAD_STREAM_SKIP_CB:
488 printf("%-30s id:%x write_offset_0:%u write_offset_1:%u\n",
489 "STREAM_SKIP_CB", data1, data2, data3);
490 break;
491 case AUDIO_THREAD_DEV_SLEEP_TIME:
492 printf("%-30s dev:%u wake:%09u.%09d\n",
493 "DEV_SLEEP_TIME", data1, data2, data3);
494 break;
495 case AUDIO_THREAD_SET_DEV_WAKE:
496 printf("%-30s dev:%u hw_level:%u sleep:%u\n",
497 "SET_DEV_WAKE", data1, data2, data3);
498 break;
499 case AUDIO_THREAD_DEV_ADDED:
500 printf("%-30s dev:%u\n", "DEV_ADDED", data1);
501 break;
502 case AUDIO_THREAD_DEV_REMOVED:
503 printf("%-30s dev:%u\n", "DEV_REMOVED", data1);
504 break;
505 case AUDIO_THREAD_IODEV_CB:
506 printf("%-30s is_write:%u\n", "IODEV_CB", data1);
507 break;
508 case AUDIO_THREAD_PB_MSG:
509 printf("%-30s msg_id:%u\n", "PB_MSG", data1);
510 break;
511 case AUDIO_THREAD_ODEV_NO_STREAMS:
512 printf("%-30s dev:%u\n",
513 "ODEV_NO_STREAMS", data1);
514 break;
515 case AUDIO_THREAD_ODEV_LEAVE_NO_STREAMS:
516 printf("%-30s dev:%u\n",
517 "ODEV_LEAVE_NO_STREAMS", data1);
518 break;
519 case AUDIO_THREAD_ODEV_START:
520 printf("%-30s dev:%u min_cb_level:%u\n",
521 "ODEV_START", data1, data2);
522 break;
523 case AUDIO_THREAD_FILL_ODEV_ZEROS:
524 printf("%-30s dev:%u write:%u\n",
525 "FILL_ODEV_ZEROS", data1, data2);
526 break;
527 case AUDIO_THREAD_ODEV_DEFAULT_NO_STREAMS:
528 printf("%-30s dev:%u hw_level:%u target:%u\n",
529 "DEFAULT_NO_STREAMS", data1, data2, data3);
530 break;
531 case AUDIO_THREAD_UNDERRUN:
532 printf("%-30s dev:%u hw_level:%u total_written:%u\n",
533 "UNDERRUN", data1, data2, data3);
534 break;
535 case AUDIO_THREAD_SEVERE_UNDERRUN:
536 printf("%-30s dev:%u\n", "SEVERE_UNDERRUN", data1);
537 break;
538 default:
539 printf("%-30s tag:%u\n","UNKNOWN", tag);
540 break;
541 }
542 }
543
print_audio_debug_info(const struct audio_debug_info * info)544 static void print_audio_debug_info(const struct audio_debug_info *info)
545 {
546 int i, j;
547 printf("Audio Debug Stats:\n");
548 printf("-------------devices------------\n");
549 if (info->num_devs > MAX_DEBUG_DEVS)
550 return;
551
552 for (i = 0; i < info->num_devs; i++) {
553 printf("%s dev: %s\n",
554 (info->devs[i].direction == CRAS_STREAM_INPUT)
555 ? "Input" : "Output",
556 info->devs[i].dev_name);
557 printf("buffer_size: %u\n"
558 "min_buffer_level: %u\n"
559 "min_cb_level: %u\n"
560 "max_cb_level: %u\n"
561 "frame_rate: %u\n"
562 "num_channels: %u\n"
563 "est_rate_ratio: %lf\n"
564 "num_underruns: %u\n"
565 "num_severe_underruns: %u\n"
566 "highest_hw_level: %u\n",
567 (unsigned int)info->devs[i].buffer_size,
568 (unsigned int)info->devs[i].min_buffer_level,
569 (unsigned int)info->devs[i].min_cb_level,
570 (unsigned int)info->devs[i].max_cb_level,
571 (unsigned int)info->devs[i].frame_rate,
572 (unsigned int)info->devs[i].num_channels,
573 info->devs[i].est_rate_ratio,
574 (unsigned int)info->devs[i].num_underruns,
575 (unsigned int)info->devs[i].num_severe_underruns,
576 (unsigned int)info->devs[i].highest_hw_level);
577 printf("\n");
578 }
579
580 printf("-------------stream_dump------------\n");
581 if (info->num_streams > MAX_DEBUG_STREAMS)
582 return;
583
584 for (i = 0; i < info->num_streams; i++) {
585 int channel;
586 printf("stream: %llu dev: %u\n",
587 (unsigned long long)info->streams[i].stream_id,
588 (unsigned int)info->streams[i].dev_idx);
589 printf("direction: %s\n",
590 (info->streams[i].direction == CRAS_STREAM_INPUT)
591 ? "Input" : "Output");
592 printf("stream_type: %s\n",
593 cras_stream_type_str(info->streams[i].stream_type));
594 printf("buffer_frames: %u\n"
595 "cb_threshold: %u\n"
596 "effects: 0x%.4x\n"
597 "frame_rate: %u\n"
598 "num_channels: %u\n"
599 "longest_fetch_sec: %u.%09u\n"
600 "num_overruns: %u\n",
601 (unsigned int)info->streams[i].buffer_frames,
602 (unsigned int)info->streams[i].cb_threshold,
603 (unsigned int)info->streams[i].effects,
604 (unsigned int)info->streams[i].frame_rate,
605 (unsigned int)info->streams[i].num_channels,
606 (unsigned int)info->streams[i].longest_fetch_sec,
607 (unsigned int)info->streams[i].longest_fetch_nsec,
608 (unsigned int)info->streams[i].num_overruns);
609 printf("channel map:");
610 for (channel = 0; channel < CRAS_CH_MAX; channel++)
611 printf("%d ", info->streams[i].channel_layout[channel]);
612 printf("\n\n");
613 }
614
615 printf("Audio Thread Event Log:\n");
616
617 j = info->log.write_pos;
618 i = 0;
619 printf("start at %d\n", j);
620 for (; i < info->log.len; i++) {
621 show_alog_tag(&info->log, j);
622 j++;
623 j %= info->log.len;
624 }
625 }
626
audio_debug_info(struct cras_client * client)627 static void audio_debug_info(struct cras_client *client)
628 {
629 const struct audio_debug_info *info;
630 info = cras_client_get_audio_debug_info(client);
631 if (!info)
632 return;
633 print_audio_debug_info(info);
634
635 /* Signal main thread we are done after the last chunk. */
636 pthread_mutex_lock(&done_mutex);
637 pthread_cond_signal(&done_cond);
638 pthread_mutex_unlock(&done_mutex);
639 }
640
print_cras_audio_thread_snapshot(const struct cras_audio_thread_snapshot * snapshot)641 static void print_cras_audio_thread_snapshot(
642 const struct cras_audio_thread_snapshot *snapshot)
643 {
644 printf("-------------snapshot------------\n");
645 printf("Event time: %" PRId64 ".%ld\n",
646 (int64_t)snapshot->timestamp.tv_sec,
647 snapshot->timestamp.tv_nsec);
648
649 printf("Event type: ");
650 switch(snapshot->event_type) {
651 case AUDIO_THREAD_EVENT_BUSYLOOP:
652 printf("busyloop\n");
653 break;
654 case AUDIO_THREAD_EVENT_UNDERRUN:
655 printf("underrun\n");
656 break;
657 case AUDIO_THREAD_EVENT_SEVERE_UNDERRUN:
658 printf("severe underrun\n");
659 break;
660 case AUDIO_THREAD_EVENT_DEBUG:
661 printf("debug\n");
662 break;
663 default:
664 printf("no such type\n");
665 }
666 print_audio_debug_info(&snapshot->audio_debug_info);
667 }
668
audio_thread_snapshots(struct cras_client * client)669 static void audio_thread_snapshots(struct cras_client *client)
670 {
671 const struct cras_audio_thread_snapshot_buffer *snapshot_buffer;
672 uint32_t i;
673 int j;
674 int count = 0;
675
676 snapshot_buffer = cras_client_get_audio_thread_snapshot_buffer(client);
677 i = snapshot_buffer->pos;
678 for(j = 0; j < CRAS_MAX_AUDIO_THREAD_SNAPSHOTS; j++)
679 {
680 if(snapshot_buffer->snapshots[i].timestamp.tv_sec ||
681 snapshot_buffer->snapshots[i].timestamp.tv_nsec)
682 {
683 print_cras_audio_thread_snapshot(
684 &snapshot_buffer->snapshots[i]);
685 count++;
686 }
687 i++;
688 i %= CRAS_MAX_AUDIO_THREAD_SNAPSHOTS;
689 }
690 printf("There are %d, snapshots.\n", count);
691
692 /* Signal main thread we are done after the last chunk. */
693 pthread_mutex_lock(&done_mutex);
694 pthread_cond_signal(&done_cond);
695 pthread_mutex_unlock(&done_mutex);
696 }
697
start_stream(struct cras_client * client,cras_stream_id_t * stream_id,struct cras_stream_params * params,float stream_volume)698 static int start_stream(struct cras_client *client,
699 cras_stream_id_t *stream_id,
700 struct cras_stream_params *params,
701 float stream_volume)
702 {
703 int rc;
704
705 if (pin_device_id)
706 rc = cras_client_add_pinned_stream(client, pin_device_id,
707 stream_id, params);
708 else
709 rc = cras_client_add_stream(client, stream_id, params);
710 if (rc < 0) {
711 fprintf(stderr, "adding a stream %d\n", rc);
712 return rc;
713 }
714 return cras_client_set_stream_volume(client, *stream_id, stream_volume);
715 }
716
parse_channel_layout(char * channel_layout_str,int8_t channel_layout[CRAS_CH_MAX])717 static int parse_channel_layout(char *channel_layout_str,
718 int8_t channel_layout[CRAS_CH_MAX])
719 {
720 int i = 0;
721 char *chp;
722
723 chp = strtok(channel_layout_str, ",");
724 while (chp && i < CRAS_CH_MAX) {
725 channel_layout[i++] = atoi(chp);
726 chp = strtok(NULL, ",");
727 }
728
729 return 0;
730 }
731
run_aecdump(struct cras_client * client,uint64_t stream_id,int start)732 static void run_aecdump(struct cras_client *client, uint64_t stream_id,
733 int start)
734 {
735 int aecdump_fd;
736 if (start) {
737 aecdump_fd = open(aecdump_file, O_CREAT | O_RDWR | O_TRUNC,
738 0666);
739 if (aecdump_fd == -1) {
740 printf("Fail to open file %s", aecdump_file);
741 return;
742 }
743
744 printf("Dumping AEC info to %s, stream %" PRId64 ", fd %d\n",
745 aecdump_file, stream_id, aecdump_fd);
746 cras_client_set_aec_dump(client, stream_id, 1, aecdump_fd);
747 } else {
748 cras_client_set_aec_dump(client, stream_id, 0, -1);
749 printf("Close AEC dump file %s\n", aecdump_file);
750 }
751 }
752
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,size_t num_channels,uint32_t flags,int is_loopback,int is_post_dsp)753 static int run_file_io_stream(struct cras_client *client,
754 int fd,
755 enum CRAS_STREAM_DIRECTION direction,
756 size_t block_size,
757 enum CRAS_STREAM_TYPE stream_type,
758 size_t rate,
759 size_t num_channels,
760 uint32_t flags,
761 int is_loopback,
762 int is_post_dsp)
763 {
764 int rc, tty;
765 struct cras_stream_params *params;
766 cras_unified_cb_t aud_cb;
767 cras_stream_id_t stream_id = 0;
768 int stream_playing = 0;
769 int *pfd = malloc(sizeof(*pfd));
770 *pfd = fd;
771 fd_set poll_set;
772 struct timespec sleep_ts;
773 float volume_scaler = 1.0;
774 size_t sys_volume = 100;
775 long cap_gain = 0;
776 int mute = 0;
777 int8_t layout[CRAS_CH_MAX];
778
779 /* Set the sleep interval between latency/RMS prints. */
780 sleep_ts.tv_sec = 1;
781 sleep_ts.tv_nsec = 0;
782
783 /* Open the pipe file descriptor. */
784 rc = pipe(pipefd);
785 if (rc == -1) {
786 perror("failed to open pipe");
787 return -errno;
788 }
789
790 /* Reset the total RMS value. */
791 total_rms_sqr_sum = 0;
792 total_rms_size = 0;
793
794 if (direction == CRAS_STREAM_INPUT)
795 aud_cb = got_samples;
796 else
797 aud_cb = put_samples;
798
799 if (fd == 0) {
800 if (direction != CRAS_STREAM_OUTPUT)
801 return -EINVAL;
802 aud_cb = put_stdin_samples;
803 }
804
805 aud_format = cras_audio_format_create(SND_PCM_FORMAT_S16_LE, rate,
806 num_channels);
807 if (aud_format == NULL)
808 return -ENOMEM;
809
810 if (channel_layout) {
811 /* Set channel layout to format */
812 parse_channel_layout(channel_layout, layout);
813 cras_audio_format_set_channel_layout(aud_format, layout);
814 }
815
816 params = cras_client_unified_params_create(direction,
817 block_size,
818 stream_type,
819 flags,
820 pfd,
821 aud_cb,
822 stream_error,
823 aud_format);
824 if (params == NULL)
825 return -ENOMEM;
826
827 if (effect_aec)
828 cras_client_stream_params_enable_aec(params);
829 if (effect_ns)
830 cras_client_stream_params_enable_ns(params);
831 if (effect_agc)
832 cras_client_stream_params_enable_agc(params);
833 if (effect_vad)
834 cras_client_stream_params_enable_vad(params);
835
836 cras_client_run_thread(client);
837 if (is_loopback) {
838 enum CRAS_NODE_TYPE type = (is_post_dsp ?
839 CRAS_NODE_TYPE_POST_DSP :
840 CRAS_NODE_TYPE_POST_MIX_PRE_DSP);
841
842 cras_client_connected_wait(client);
843 pin_device_id = cras_client_get_first_dev_type_idx(
844 client, type, CRAS_STREAM_INPUT);
845 }
846
847 stream_playing =
848 start_stream(client, &stream_id, params, volume_scaler) == 0;
849
850 tty = open("/dev/tty", O_RDONLY);
851
852 // There could be no terminal available when run in autotest.
853 if (tty == -1)
854 perror("warning: failed to open /dev/tty");
855
856 while (keep_looping) {
857 char input;
858 int nread;
859
860 FD_ZERO(&poll_set);
861 if (tty >= 0)
862 FD_SET(tty, &poll_set);
863 FD_SET(pipefd[0], &poll_set);
864 pselect(MAX(tty, pipefd[0]) + 1,
865 &poll_set,
866 NULL,
867 NULL,
868 show_latency || show_rms ? &sleep_ts : NULL,
869 NULL);
870
871 if (stream_playing && show_latency)
872 print_last_latency();
873
874 if (stream_playing && show_rms)
875 print_last_rms();
876
877 if (tty < 0 || !FD_ISSET(tty, &poll_set))
878 continue;
879
880 nread = read(tty, &input, 1);
881 if (nread < 1) {
882 fprintf(stderr, "Error reading stdin\n");
883 return nread;
884 }
885 switch (input) {
886 case 'p':
887 pause_client = !pause_client;
888 break;
889 case 'i':
890 pause_a_reply = 1;
891 break;
892 case 'q':
893 terminate_stream_loop();
894 break;
895 case 's':
896 if (stream_playing)
897 break;
898
899 /* If started by hand keep running after it finishes. */
900 exit_after_done_playing = 0;
901
902 stream_playing = start_stream(client,
903 &stream_id,
904 params,
905 volume_scaler) == 0;
906 break;
907 case 'r':
908 if (!stream_playing)
909 break;
910 cras_client_rm_stream(client, stream_id);
911 stream_playing = 0;
912 break;
913 case 'u':
914 volume_scaler = MIN(volume_scaler + 0.1, 1.0);
915 cras_client_set_stream_volume(client,
916 stream_id,
917 volume_scaler);
918 break;
919 case 'd':
920 volume_scaler = MAX(volume_scaler - 0.1, 0.0);
921 cras_client_set_stream_volume(client,
922 stream_id,
923 volume_scaler);
924 break;
925 case 'k':
926 sys_volume = MIN(sys_volume + 1, 100);
927 cras_client_set_system_volume(client, sys_volume);
928 break;
929 case 'j':
930 sys_volume = sys_volume == 0 ? 0 : sys_volume - 1;
931 cras_client_set_system_volume(client, sys_volume);
932 break;
933 case 'K':
934 cap_gain = MIN(cap_gain + 100, 5000);
935 cras_client_set_system_capture_gain(client, cap_gain);
936 break;
937 case 'J':
938 cap_gain = cap_gain == -5000 ? -5000 : cap_gain - 100;
939 cras_client_set_system_capture_gain(client, cap_gain);
940 break;
941 case 'm':
942 mute = !mute;
943 cras_client_set_system_mute(client, mute);
944 break;
945 case '@':
946 print_device_lists(client);
947 break;
948 case '#':
949 print_attached_client_list(client);
950 break;
951 case 'v':
952 printf("Volume: %zu%s Min dB: %ld Max dB: %ld\n"
953 "Capture: %ld%s Min dB: %ld Max dB: %ld\n",
954 cras_client_get_system_volume(client),
955 cras_client_get_system_muted(client) ? "(Muted)"
956 : "",
957 cras_client_get_system_min_volume(client),
958 cras_client_get_system_max_volume(client),
959 cras_client_get_system_capture_gain(client),
960 cras_client_get_system_capture_muted(client) ?
961 "(Muted)" : "",
962 cras_client_get_system_min_capture_gain(client),
963 cras_client_get_system_max_capture_gain(client));
964 break;
965 case '\'':
966 play_short_sound_periods_left = play_short_sound_periods;
967 break;
968 case '\n':
969 break;
970 default:
971 printf("Invalid key\n");
972 break;
973 }
974 }
975
976 if (show_total_rms)
977 print_total_rms();
978
979 cras_client_stop(client);
980
981 cras_audio_format_destroy(aud_format);
982 cras_client_stream_params_destroy(params);
983 free(pfd);
984
985 close(pipefd[0]);
986 close(pipefd[1]);
987
988 return 0;
989 }
990
run_capture(struct cras_client * client,const char * file,size_t block_size,enum CRAS_STREAM_TYPE stream_type,size_t rate,size_t num_channels,uint32_t flags,int is_loopback,int is_post_dsp)991 static int run_capture(struct cras_client *client,
992 const char *file,
993 size_t block_size,
994 enum CRAS_STREAM_TYPE stream_type,
995 size_t rate,
996 size_t num_channels,
997 uint32_t flags,
998 int is_loopback,
999 int is_post_dsp)
1000 {
1001 int fd = open(file, O_CREAT | O_RDWR | O_TRUNC, 0666);
1002 if (fd == -1) {
1003 perror("failed to open file");
1004 return -errno;
1005 }
1006
1007 run_file_io_stream(client, fd, CRAS_STREAM_INPUT, block_size,
1008 stream_type, rate, num_channels, flags, is_loopback,
1009 is_post_dsp);
1010
1011 close(fd);
1012 return 0;
1013 }
1014
run_playback(struct cras_client * client,const char * file,size_t block_size,enum CRAS_STREAM_TYPE stream_type,size_t rate,size_t num_channels)1015 static int run_playback(struct cras_client *client,
1016 const char *file,
1017 size_t block_size,
1018 enum CRAS_STREAM_TYPE stream_type,
1019 size_t rate,
1020 size_t num_channels)
1021 {
1022 int fd;
1023
1024 fd = open(file, O_RDONLY);
1025 if (fd == -1) {
1026 perror("failed to open file");
1027 return -errno;
1028 }
1029
1030 run_file_io_stream(client, fd, CRAS_STREAM_OUTPUT, block_size,
1031 stream_type, rate, num_channels, 0, 0, 0);
1032
1033 close(fd);
1034 return 0;
1035 }
1036
print_server_info(struct cras_client * client)1037 static void print_server_info(struct cras_client *client)
1038 {
1039 cras_client_run_thread(client);
1040 cras_client_connected_wait(client); /* To synchronize data. */
1041 print_system_volumes(client);
1042 print_user_muted(client);
1043 print_device_lists(client);
1044 print_attached_client_list(client);
1045 print_active_stream_info(client);
1046 }
1047
show_audio_thread_snapshots(struct cras_client * client)1048 static void show_audio_thread_snapshots(struct cras_client *client)
1049 {
1050 struct timespec wait_time;
1051
1052 cras_client_run_thread(client);
1053 cras_client_connected_wait(client); /* To synchronize data. */
1054 cras_client_update_audio_thread_snapshots(client,
1055 audio_thread_snapshots);
1056
1057 clock_gettime(CLOCK_REALTIME, &wait_time);
1058 wait_time.tv_sec += 2;
1059
1060 pthread_mutex_lock(&done_mutex);
1061 pthread_cond_timedwait(&done_cond, &done_mutex, &wait_time);
1062 pthread_mutex_unlock(&done_mutex);
1063 }
1064
show_audio_debug_info(struct cras_client * client)1065 static void show_audio_debug_info(struct cras_client *client)
1066 {
1067 struct timespec wait_time;
1068
1069 cras_client_run_thread(client);
1070 cras_client_connected_wait(client); /* To synchronize data. */
1071 cras_client_update_audio_debug_info(client, audio_debug_info);
1072
1073 clock_gettime(CLOCK_REALTIME, &wait_time);
1074 wait_time.tv_sec += 2;
1075
1076 pthread_mutex_lock(&done_mutex);
1077 pthread_cond_timedwait(&done_cond, &done_mutex, &wait_time);
1078 pthread_mutex_unlock(&done_mutex);
1079 }
1080
hotword_models_cb(struct cras_client * client,const char * hotword_models)1081 static void hotword_models_cb(struct cras_client *client,
1082 const char *hotword_models)
1083 {
1084 printf("Hotword models: %s\n", hotword_models);
1085 }
1086
print_hotword_models(struct cras_client * client,cras_node_id_t id)1087 static void print_hotword_models(struct cras_client *client,
1088 cras_node_id_t id)
1089 {
1090 struct timespec wait_time;
1091
1092 cras_client_run_thread(client);
1093 cras_client_connected_wait(client);
1094 cras_client_get_hotword_models(client, id,
1095 hotword_models_cb);
1096
1097 clock_gettime(CLOCK_REALTIME, &wait_time);
1098 wait_time.tv_sec += 2;
1099
1100 pthread_mutex_lock(&done_mutex);
1101 pthread_cond_timedwait(&done_cond, &done_mutex, &wait_time);
1102 pthread_mutex_unlock(&done_mutex);
1103 }
1104
check_output_plugged(struct cras_client * client,const char * name)1105 static void check_output_plugged(struct cras_client *client, const char *name)
1106 {
1107 cras_client_run_thread(client);
1108 cras_client_connected_wait(client); /* To synchronize data. */
1109 printf("%s\n",
1110 cras_client_output_dev_plugged(client, name) ? "Yes" : "No");
1111 }
1112
1113 /* Repeatedly mute and unmute the output until there is an error. */
mute_loop_test(struct cras_client * client,int auto_reconnect)1114 static void mute_loop_test(struct cras_client *client, int auto_reconnect)
1115 {
1116 int mute = 0;
1117 int rc;
1118
1119 if (auto_reconnect)
1120 cras_client_run_thread(client);
1121 while(1) {
1122 rc = cras_client_set_user_mute(client, mute);
1123 printf("cras_client_set_user_mute(%d): %d\n", mute, rc);
1124 if (rc != 0 && !auto_reconnect)
1125 return;
1126 mute = !mute;
1127 sleep(2);
1128 }
1129 }
1130
1131 static struct option long_options[] = {
1132 {"show_latency", no_argument, &show_latency, 1},
1133 {"show_rms", no_argument, &show_rms, 1},
1134 {"show_total_rms", no_argument, &show_total_rms, 1},
1135 {"select_input", required_argument, 0, 'a'},
1136 {"block_size", required_argument, 0, 'b'},
1137 {"capture_file", required_argument, 0, 'c'},
1138 {"duration_seconds", required_argument, 0, 'd'},
1139 {"dump_events", no_argument, 0, 'e'},
1140 {"dump_dsp", no_argument, 0, 'f'},
1141 {"capture_gain", required_argument, 0, 'g'},
1142 {"help", no_argument, 0, 'h'},
1143 {"dump_server_info", no_argument, 0, 'i'},
1144 {"check_output_plugged",required_argument, 0, 'j'},
1145 {"add_active_input", required_argument, 0, 'k'},
1146 {"add_active_output", required_argument, 0, 't'},
1147 {"loopback_file", required_argument, 0, 'l'},
1148 {"dump_audio_thread", no_argument, 0, 'm'},
1149 {"num_channels", required_argument, 0, 'n'},
1150 {"channel_layout", required_argument, 0, 'o'},
1151 {"playback_file", required_argument, 0, 'p'},
1152 {"user_mute", required_argument, 0, 'q'},
1153 {"rate", required_argument, 0, 'r'},
1154 {"reload_dsp", no_argument, 0, 's'},
1155 {"mute", required_argument, 0, 'u'},
1156 {"volume", required_argument, 0, 'v'},
1157 {"set_node_volume", required_argument, 0, 'w'},
1158 {"plug", required_argument, 0, 'x'},
1159 {"select_output", required_argument, 0, 'y'},
1160 {"playback_delay_us", required_argument, 0, 'z'},
1161 {"capture_mute", required_argument, 0, '0'},
1162 {"rm_active_input", required_argument, 0, '1'},
1163 {"rm_active_output", required_argument, 0, '2'},
1164 {"swap_left_right", required_argument, 0, '3'},
1165 {"version", no_argument, 0, '4'},
1166 {"add_test_dev", required_argument, 0, '5'},
1167 {"test_hotword_file", required_argument, 0, '6'},
1168 {"listen_for_hotword", required_argument, 0, '7'},
1169 {"pin_device", required_argument, 0, '8'},
1170 {"suspend", required_argument, 0, '9'},
1171 {"set_node_gain", required_argument, 0, ':'},
1172 {"play_short_sound", required_argument, 0, '!'},
1173 {"config_global_remix", required_argument, 0, ';'},
1174 {"set_hotword_model", required_argument, 0, '<'},
1175 {"get_hotword_models", required_argument, 0, '>'},
1176 {"post_dsp", required_argument, 0, 'A'},
1177 {"stream_id", required_argument, 0, 'B'},
1178 {"aecdump", required_argument, 0, 'C'},
1179 {"reload_aec_config", no_argument, 0, 'D'},
1180 {"effects", required_argument, 0, 'E'},
1181 {"get_aec_supported", no_argument, 0, 'F'},
1182 {"syslog_mask", required_argument, 0, 'L'},
1183 {"mute_loop_test", required_argument, 0, 'M'},
1184 {"stream_type", required_argument, 0, 'T'},
1185 {0, 0, 0, 0}
1186 };
1187
show_usage()1188 static void show_usage()
1189 {
1190 printf("--add_active_input <N>:<M> - Add the ionode with the given id"
1191 "to active input device list\n");
1192 printf("--add_active_output <N>:<M> - Add the ionode with the given id"
1193 "to active output device list\n");
1194 printf("--add_test_dev <type> - add a test iodev.\n");
1195 printf("--block_size <N> - The number for frames per callback(dictates latency).\n");
1196 printf("--capture_file <name> - Name of file to record to.\n");
1197 printf("--capture_gain <dB> - Set system caputre gain in dB*100 (100 = 1dB).\n");
1198 printf("--capture_mute <0|1> - Set capture mute state.\n");
1199 printf("--channel_layout <layout_str> - Set multiple channel layout.\n");
1200 printf("--check_output_plugged <output name> - Check if the output is plugged in\n");
1201 printf("--dump_audio_thread - Dumps audio thread info.\n");
1202 printf("--dump_dsp - Print status of dsp to syslog.\n");
1203 printf("--dump_server_info - Print status of the server.\n");
1204 printf("--duration_seconds <N> - Seconds to record or playback.\n");
1205 printf("--get_hotword_models <N>:<M> - Get the supported hotword models of node\n");
1206 printf("--help - Print this message.\n");
1207 printf("--listen_for_hotword <name> - Listen and capture hotword stream if supported\n");
1208 printf("--loopback_file <name> - Name of file to record from loopback device.\n");
1209 printf("--mute <0|1> - Set system mute state.\n");
1210 printf("--mute_loop_test <0|1> - Continuously loop mute/umute. Argument: 0 - stop on error.\n"
1211 " 1 - automatically reconnect to CRAS.\n");
1212 printf("--num_channels <N> - Two for stereo.\n");
1213 printf("--pin_device <N> - Playback/Capture only on the given device."
1214 "\n");
1215 printf("--playback_file <name> - Name of file to play, "
1216 "\"-\" to playback raw audio from stdin.\n");
1217 printf("--play_short_sound <N> - Plays the content in the file for N periods when ' is pressed.\n");
1218 printf("--plug <N>:<M>:<0|1> - Set the plug state (0 or 1) for the"
1219 " ionode with the given index M on the device with index N\n");
1220 printf("--rate <N> - Specifies the sample rate in Hz.\n");
1221 printf("--reload_dsp - Reload dsp configuration from the ini file\n");
1222 printf("--rm_active_input <N>:<M> - Removes the ionode with the given"
1223 "id from active input device list\n");
1224 printf("--rm_active_output <N>:<M> - Removes the ionode with the given"
1225 "id from active output device list\n");
1226 printf("--select_input <N>:<M> - Select the ionode with the given id as preferred input\n");
1227 printf("--select_output <N>:<M> - Select the ionode with the given id as preferred output\n");
1228 printf("--set_hotword_model <N>:<M>:<model> - Set the model to node\n");
1229 printf("--playback_delay_us <N> - Set the time in us to delay a reply for playback when i is pressed\n");
1230 printf("--post_dsp <0|1> - Use this flag with --loopback_file. The default value is 0.\n"
1231 " Argument: 0 - Record from post-mix, pre-DSP loopback device.\n"
1232 " 1 - Record from post-DSP loopback device.\n");
1233 printf("--set_node_volume <N>:<M>:<0-100> - Set the volume of the ionode with the given id\n");
1234 printf("--show_latency - Display latency while playing or recording.\n");
1235 printf("--show_rms - Display RMS value of loopback stream.\n");
1236 printf("--show_total_rms - Display total RMS value of loopback stream at the end.\n");
1237 printf("--suspend <0|1> - Set audio suspend state.\n");
1238 printf("--swap_left_right <N>:<M>:<0|1> - Swap or unswap (1 or 0) the"
1239 " left and right channel for the ionode with the given index M"
1240 " on the device with index N\n");
1241 printf("--stream_type <N> - Specify the type of the stream.\n");
1242 printf("--syslog_mask <n> - Set the syslog mask to the given log level.\n");
1243 printf("--test_hotword_file <N>:<filename> - Use filename as a hotword buffer for device N\n");
1244 printf("--user_mute <0|1> - Set user mute state.\n");
1245 printf("--version - Print the git commit ID that was used to build the client.\n");
1246 printf("--volume <0-100> - Set system output volume.\n");
1247 }
1248
main(int argc,char ** argv)1249 int main(int argc, char **argv)
1250 {
1251 struct cras_client *client;
1252 int c, option_index;
1253 size_t block_size = NOT_ASSIGNED;
1254 size_t rate = 48000;
1255 size_t num_channels = 2;
1256 float duration_seconds = 0;
1257 const char *capture_file = NULL;
1258 const char *playback_file = NULL;
1259 const char *loopback_file = NULL;
1260 int post_dsp = 0;
1261 enum CRAS_STREAM_TYPE stream_type = CRAS_STREAM_TYPE_DEFAULT;
1262 int rc = 0;
1263 uint32_t stream_flags = 0;
1264 cras_stream_id_t stream_id = 0;
1265
1266 option_index = 0;
1267 openlog("cras_test_client", LOG_PERROR, LOG_USER);
1268 setlogmask(LOG_UPTO(LOG_INFO));
1269
1270 rc = cras_client_create(&client);
1271 if (rc < 0) {
1272 fprintf(stderr, "Couldn't create client.\n");
1273 return rc;
1274 }
1275
1276 rc = cras_client_connect_timeout(client, 1000);
1277 if (rc) {
1278 fprintf(stderr, "Couldn't connect to server.\n");
1279 goto destroy_exit;
1280 }
1281
1282 while (1) {
1283 c = getopt_long(argc, argv, "o:s:",
1284 long_options, &option_index);
1285 if (c == -1)
1286 break;
1287 switch (c) {
1288 case 'c':
1289 capture_file = optarg;
1290 break;
1291 case 'p':
1292 playback_file = optarg;
1293 break;
1294 case 'l':
1295 loopback_file = optarg;
1296 break;
1297 case 'A':
1298 post_dsp = atoi(optarg);
1299 break;
1300 case 'b':
1301 block_size = atoi(optarg);
1302 break;
1303 case 'r':
1304 rate = atoi(optarg);
1305 break;
1306 case 'n':
1307 num_channels = atoi(optarg);
1308 break;
1309 case 'd':
1310 duration_seconds = atof(optarg);
1311 break;
1312 case 'u': {
1313 int mute = atoi(optarg);
1314 rc = cras_client_set_system_mute(client, mute);
1315 if (rc < 0) {
1316 fprintf(stderr, "problem setting mute\n");
1317 goto destroy_exit;
1318 }
1319 break;
1320 }
1321 case 'q': {
1322 int mute = atoi(optarg);
1323 rc = cras_client_set_user_mute(client, mute);
1324 if (rc < 0) {
1325 fprintf(stderr, "problem setting mute\n");
1326 goto destroy_exit;
1327 }
1328 break;
1329 }
1330 case 'v': {
1331 int volume = atoi(optarg);
1332 volume = MIN(100, MAX(0, volume));
1333 rc = cras_client_set_system_volume(client, volume);
1334 if (rc < 0) {
1335 fprintf(stderr, "problem setting volume\n");
1336 goto destroy_exit;
1337 }
1338 break;
1339 }
1340 case 'g': {
1341 long gain = atol(optarg);
1342 rc = cras_client_set_system_capture_gain(client, gain);
1343 if (rc < 0) {
1344 fprintf(stderr, "problem setting capture\n");
1345 goto destroy_exit;
1346 }
1347 break;
1348 }
1349 case 'j':
1350 check_output_plugged(client, optarg);
1351 break;
1352 case 's':
1353 cras_client_reload_dsp(client);
1354 break;
1355 case 'f':
1356 cras_client_dump_dsp_info(client);
1357 break;
1358 case 'i':
1359 print_server_info(client);
1360 break;
1361 case 'h':
1362 show_usage();
1363 break;
1364 case 'x': {
1365 int dev_index = atoi(strtok(optarg, ":"));
1366 int node_index = atoi(strtok(NULL, ":"));
1367 int value = atoi(strtok(NULL, ":")) ;
1368 cras_node_id_t id = cras_make_node_id(dev_index,
1369 node_index);
1370 enum ionode_attr attr = IONODE_ATTR_PLUGGED;
1371 cras_client_set_node_attr(client, id, attr, value);
1372 break;
1373 }
1374 case 'y':
1375 case 'a': {
1376 int dev_index = atoi(strtok(optarg, ":"));
1377 int node_index = atoi(strtok(NULL, ":"));
1378 cras_node_id_t id = cras_make_node_id(dev_index,
1379 node_index);
1380
1381 enum CRAS_STREAM_DIRECTION direction = (c == 'y') ?
1382 CRAS_STREAM_OUTPUT : CRAS_STREAM_INPUT;
1383 cras_client_select_node(client, direction, id);
1384 break;
1385 }
1386 case 'z':
1387 pause_in_playback_reply = atoi(optarg);
1388 break;
1389 case 'k':
1390 case 't':
1391 case '1':
1392 case '2':{
1393 int dev_index = atoi(strtok(optarg, ":"));
1394 int node_index = atoi(strtok(NULL, ":"));
1395 enum CRAS_STREAM_DIRECTION dir;
1396 cras_node_id_t id = cras_make_node_id(dev_index,
1397 node_index);
1398
1399 if (c == 't' || c == '2')
1400 dir = CRAS_STREAM_OUTPUT;
1401 else
1402 dir = CRAS_STREAM_INPUT;
1403
1404 if (c == 'k' || c == 't')
1405 cras_client_add_active_node(client, dir, id);
1406 else
1407 cras_client_rm_active_node(client, dir, id);
1408 break;
1409 }
1410 case ':':
1411 case 'w': {
1412 const char *s;
1413 int dev_index;
1414 int node_index;
1415 int value;
1416
1417 s = strtok(optarg, ":");
1418 if (!s) {
1419 show_usage();
1420 return -EINVAL;
1421 }
1422 dev_index = atoi(s);
1423
1424 s = strtok(NULL, ":");
1425 if (!s) {
1426 show_usage();
1427 return -EINVAL;
1428 }
1429 node_index = atoi(s);
1430
1431 s = strtok(NULL, ":");
1432 if (!s) {
1433 show_usage();
1434 return -EINVAL;
1435 }
1436 value = atoi(s) ;
1437
1438 cras_node_id_t id = cras_make_node_id(dev_index,
1439 node_index);
1440
1441 if (c == 'w')
1442 cras_client_set_node_volume(client, id, value);
1443 else
1444 cras_client_set_node_capture_gain(
1445 client, id, value);
1446 break;
1447 }
1448 case '0': {
1449 int mute = atoi(optarg);
1450 rc = cras_client_set_system_capture_mute(client, mute);
1451 if (rc < 0) {
1452 fprintf(stderr, "problem setting mute\n");
1453 goto destroy_exit;
1454 }
1455 break;
1456 }
1457 case 'e':
1458 show_audio_thread_snapshots(client);
1459 break;
1460 case 'm':
1461 show_audio_debug_info(client);
1462 break;
1463 case 'o':
1464 channel_layout = optarg;
1465 break;
1466 case '3': {
1467 int dev_index = atoi(strtok(optarg, ":"));
1468 int node_index = atoi(strtok(NULL, ":"));
1469 int value = atoi(strtok(NULL, ":")) ;
1470 cras_node_id_t id = cras_make_node_id(dev_index,
1471 node_index);
1472 cras_client_swap_node_left_right(client, id, value);
1473 break;
1474 }
1475 case '4':
1476 printf("%s\n", VCSID);
1477 break;
1478 case '5': {
1479 cras_client_add_test_iodev(client, atoi(optarg));
1480 break;
1481 }
1482 case '6': {
1483 int dev_index = atoi(strtok(optarg, ":"));
1484 const char *file_name = strtok(NULL, ":");
1485 cras_client_test_iodev_command(client, dev_index,
1486 TEST_IODEV_CMD_HOTWORD_TRIGGER,
1487 strlen(file_name) + 1,
1488 (uint8_t *)file_name);
1489 break;
1490 }
1491 case '7': {
1492 stream_flags = HOTWORD_STREAM;
1493 capture_file = optarg;
1494 break;
1495 }
1496 case '8':
1497 pin_device_id = atoi(optarg);
1498 break;
1499 case '9': {
1500 int suspend = atoi(optarg);
1501 cras_client_set_suspend(client, suspend);
1502 break;
1503 }
1504 case '!': {
1505 play_short_sound = 1;
1506 play_short_sound_periods = atoi(optarg);
1507 break;
1508 }
1509 case ';': {
1510 char *s;
1511 int nch;
1512 int size = 0;
1513 float *coeff;
1514
1515 s = strtok(optarg, ":");
1516 nch = atoi(s);
1517 coeff = (float *)calloc(nch * nch,
1518 sizeof(*coeff));
1519 for (size = 0; size < nch * nch; size++) {
1520 s = strtok(NULL, ",");
1521 if (NULL == s)
1522 break;
1523 coeff[size] = atof(s);
1524 }
1525 cras_client_config_global_remix(client, nch, coeff);
1526 free(coeff);
1527 break;
1528 }
1529 case '<':
1530 case '>': {
1531 char *s;
1532 int dev_index;
1533 int node_index;
1534
1535 s = strtok(optarg, ":");
1536 if (!s) {
1537 show_usage();
1538 return -EINVAL;
1539 }
1540 dev_index = atoi(s);
1541
1542 s = strtok(NULL, ":");
1543 if (!s) {
1544 show_usage();
1545 return -EINVAL;
1546 }
1547 node_index = atoi(s);
1548
1549 s = strtok(NULL, ":");
1550 if (!s && c == ';') {
1551 show_usage();
1552 return -EINVAL;
1553 }
1554
1555 cras_node_id_t id = cras_make_node_id(dev_index,
1556 node_index);
1557 if (c == '<')
1558 cras_client_set_hotword_model(client, id, s);
1559 else
1560 print_hotword_models(client, id);
1561 break;
1562 }
1563 case 'L': {
1564 int log_level = atoi(optarg);
1565
1566 setlogmask(LOG_UPTO(log_level));
1567 break;
1568 }
1569 case 'M':
1570 mute_loop_test(client, atoi(optarg));
1571 break;
1572 case 'T':
1573 stream_type = atoi(optarg);
1574 break;
1575 case 'E': {
1576 char *s;
1577
1578 s = strtok(optarg, ",");
1579 while (s) {
1580 if (strcmp("aec", s) == 0)
1581 effect_aec = 1;
1582 else if (strcmp("ns", s) == 0)
1583 effect_ns = 1;
1584 else if (strcmp("agc", s) == 0)
1585 effect_agc = 1;
1586 else if (strcmp("vad", s) == 0)
1587 effect_vad = 1;
1588 else
1589 printf("Unknown effect %s\n", s);
1590 s = strtok(NULL, ",");
1591 }
1592 break;
1593 }
1594 case 'B':
1595 stream_id = atoi(optarg);
1596 break;
1597 case 'C':
1598 aecdump_file = optarg;
1599 break;
1600 case 'D':
1601 cras_client_reload_aec_config(client);
1602 break;
1603 case 'F':
1604 printf("AEC supported %d\n",
1605 !!cras_client_get_aec_supported(client));
1606 default:
1607 break;
1608 }
1609 }
1610
1611 duration_frames = duration_seconds * rate;
1612 if (block_size == NOT_ASSIGNED)
1613 block_size = get_block_size(PLAYBACK_BUFFERED_TIME_IN_US, rate);
1614
1615 if (capture_file != NULL) {
1616 if (strcmp(capture_file, "-") == 0)
1617 rc = run_file_io_stream(client, 1, CRAS_STREAM_INPUT,
1618 block_size, stream_type, rate,
1619 num_channels, stream_flags, 0, 0);
1620 else
1621 rc = run_capture(client, capture_file, block_size,
1622 stream_type, rate, num_channels,
1623 stream_flags, 0, 0);
1624 } else if (playback_file != NULL) {
1625 if (strcmp(playback_file, "-") == 0)
1626 rc = run_file_io_stream(client, 0, CRAS_STREAM_OUTPUT,
1627 block_size, stream_type, rate,
1628 num_channels, stream_flags, 0, 0);
1629 else
1630 rc = run_playback(client, playback_file, block_size,
1631 stream_type, rate, num_channels);
1632 } else if (loopback_file != NULL) {
1633 rc = run_capture(client, loopback_file, block_size,
1634 stream_type, rate, num_channels,
1635 stream_flags, 1, post_dsp);
1636 } else if (aecdump_file != NULL) {
1637 run_aecdump(client, stream_id, 1);
1638 sleep(duration_seconds);
1639 run_aecdump(client, stream_id, 0);
1640 }
1641
1642 destroy_exit:
1643 cras_client_destroy(client);
1644 return rc;
1645 }
1646