• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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