1 /*
2  * Copyright (C) 2013-2015 Intel Corporation
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  */
15 
16 #include "aconfig.h"
17 
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdbool.h>
21 #include <stdint.h>
22 #include <pthread.h>
23 #include <errno.h>
24 
25 #include <alsa/asoundlib.h>
26 
27 #include "gettext.h"
28 
29 #include "common.h"
30 #include "alsa.h"
31 #include "latencytest.h"
32 #include "os_compat.h"
33 
34 struct pcm_container {
35 	snd_pcm_t *handle;
36 	snd_pcm_uframes_t period_size;
37 	snd_pcm_uframes_t buffer_size;
38 	snd_pcm_format_t format;
39 	unsigned short channels;
40 	size_t period_bytes;
41 	size_t sample_bits;
42 	size_t frame_bits;
43 	char *buffer;
44 };
45 
46 struct format_map_table {
47 	enum _bat_pcm_format format_bat;
48 	snd_pcm_format_t format_alsa;
49 };
50 
51 static struct format_map_table map_tables[] = {
52 	{ BAT_PCM_FORMAT_UNKNOWN, SND_PCM_FORMAT_UNKNOWN },
53 	{ BAT_PCM_FORMAT_U8, SND_PCM_FORMAT_U8 },
54 	{ BAT_PCM_FORMAT_S16_LE, SND_PCM_FORMAT_S16_LE },
55 	{ BAT_PCM_FORMAT_S24_3LE, SND_PCM_FORMAT_S24_3LE },
56 	{ BAT_PCM_FORMAT_S32_LE, SND_PCM_FORMAT_S32_LE },
57 	{ BAT_PCM_FORMAT_MAX, 0 },
58 };
59 
format_convert(struct bat *bat, snd_pcm_format_t *fmt)60 static int format_convert(struct bat *bat, snd_pcm_format_t *fmt)
61 {
62 	struct format_map_table *t = map_tables;
63 
64 	for (; t->format_bat != BAT_PCM_FORMAT_MAX; t++) {
65 		if (t->format_bat == bat->format) {
66 			*fmt = t->format_alsa;
67 			return 0;
68 		}
69 	}
70 	fprintf(bat->err, _("Invalid format!\n"));
71 	return -EINVAL;
72 }
73 
set_snd_pcm_params(struct bat *bat, struct pcm_container *sndpcm)74 static int set_snd_pcm_params(struct bat *bat, struct pcm_container *sndpcm)
75 {
76 	snd_pcm_hw_params_t *params;
77 	snd_pcm_format_t format;
78 	unsigned int buffer_time = 0;
79 	unsigned int period_time = 0;
80 	snd_pcm_uframes_t buffer_size = 0;
81 	snd_pcm_uframes_t period_size = 0;
82 	unsigned int rate;
83 	int err;
84 	const char *device_name = snd_pcm_name(sndpcm->handle);
85 
86 	/* Convert common format to ALSA format */
87 	err = format_convert(bat, &format);
88 	if (err != 0)
89 		return err;
90 
91 	/* Allocate a hardware parameters object. */
92 	snd_pcm_hw_params_alloca(&params);
93 
94 	/* Fill it in with default values. */
95 	err = snd_pcm_hw_params_any(sndpcm->handle, params);
96 	if (err < 0) {
97 		fprintf(bat->err, _("Set parameter to device error: "));
98 		fprintf(bat->err, _("default params: %s: %s(%d)\n"),
99 				device_name, snd_strerror(err), err);
100 		return err;
101 	}
102 
103 	/* Set access mode */
104 	err = snd_pcm_hw_params_set_access(sndpcm->handle, params,
105 			SND_PCM_ACCESS_RW_INTERLEAVED);
106 	if (err < 0) {
107 		fprintf(bat->err, _("Set parameter to device error: "));
108 		fprintf(bat->err, _("access type: %s: %s(%d)\n"),
109 				device_name, snd_strerror(err), err);
110 		return err;
111 	}
112 
113 	/* Set format */
114 	err = snd_pcm_hw_params_set_format(sndpcm->handle, params, format);
115 	if (err < 0) {
116 		fprintf(bat->err, _("Set parameter to device error: "));
117 		fprintf(bat->err, _("PCM format: %d %s: %s(%d)\n"), format,
118 				device_name, snd_strerror(err), err);
119 		return err;
120 	}
121 
122 	/* Set channels */
123 	err = snd_pcm_hw_params_set_channels(sndpcm->handle,
124 			params, bat->channels);
125 	if (err < 0) {
126 		fprintf(bat->err, _("Set parameter to device error: "));
127 		fprintf(bat->err, _("channel number: %d %s: %s(%d)\n"),
128 				bat->channels,
129 				device_name, snd_strerror(err), err);
130 		return err;
131 	}
132 
133 	/* Set sampling rate */
134 	rate = bat->rate;
135 	err = snd_pcm_hw_params_set_rate_near(sndpcm->handle,
136 			params, &bat->rate,
137 			0);
138 	if (err < 0) {
139 		fprintf(bat->err, _("Set parameter to device error: "));
140 		fprintf(bat->err, _("sample rate: %d %s: %s(%d)\n"),
141 				bat->rate,
142 				device_name, snd_strerror(err), err);
143 		return err;
144 	}
145 	if ((float) rate * (1 + RATE_RANGE) < bat->rate
146 			|| (float) rate * (1 - RATE_RANGE) > bat->rate) {
147 		fprintf(bat->err, _("Invalid parameters: sample rate: "));
148 		fprintf(bat->err, _("requested %dHz, got %dHz\n"),
149 				rate, bat->rate);
150 		return -EINVAL;
151 	}
152 
153 	if (bat->buffer_size > 0 && bat->period_size == 0)
154 		bat->period_size = bat->buffer_size / DIV_BUFFERSIZE;
155 
156 	if (bat->roundtriplatency && bat->buffer_size == 0) {
157 		/* Set to minimum buffer size and period size
158 		   for latency test */
159 		if (snd_pcm_hw_params_get_buffer_size_min(params,
160 				&buffer_size) < 0) {
161 			fprintf(bat->err,
162 					_("Get parameter from device error: "));
163 			fprintf(bat->err, _("buffer size min: %d %s: %s(%d)\n"),
164 					(int) buffer_size,
165 					device_name, snd_strerror(err), err);
166 			return -EINVAL;
167 		}
168 
169 		if (snd_pcm_hw_params_get_period_size_min(params,
170 				&period_size, 0) < 0) {
171 			fprintf(bat->err,
172 					_("Get parameter from device error: "));
173 			fprintf(bat->err, _("period size min: %d %s: %s(%d)\n"),
174 					(int) period_size,
175 					device_name, snd_strerror(err), err);
176 			return -EINVAL;
177 		}
178 		bat->buffer_size = (int) buffer_size;
179 		bat->period_size = (int) period_size;
180 	}
181 
182 	if (bat->buffer_size > 0) {
183 		buffer_size = bat->buffer_size;
184 		period_size = bat->period_size;
185 
186 		fprintf(bat->log, _("Set period size: %d  buffer size: %d\n"),
187 				(int) period_size, (int) buffer_size);
188 
189 		err = snd_pcm_hw_params_set_buffer_size_near(sndpcm->handle,
190 				params, &buffer_size);
191 		if (err < 0) {
192 			fprintf(bat->err, _("Set parameter to device error: "));
193 			fprintf(bat->err, _("buffer size: %d %s: %s(%d)\n"),
194 					(int) buffer_size,
195 					device_name, snd_strerror(err), err);
196 			return err;
197 		}
198 
199 		err = snd_pcm_hw_params_set_period_size_near(sndpcm->handle,
200 				params, &period_size, 0);
201 		if (err < 0) {
202 			fprintf(bat->err, _("Set parameter to device error: "));
203 			fprintf(bat->err, _("period size: %d %s: %s(%d)\n"),
204 					(int) period_size,
205 					device_name, snd_strerror(err), err);
206 			return err;
207 		}
208 	} else {
209 		if (snd_pcm_hw_params_get_buffer_time_max(params,
210 				&buffer_time, 0) < 0) {
211 			fprintf(bat->err,
212 					_("Get parameter from device error: "));
213 			fprintf(bat->err, _("buffer time: %d %s: %s(%d)\n"),
214 					buffer_time,
215 					device_name, snd_strerror(err), err);
216 			return -EINVAL;
217 		}
218 
219 		if (buffer_time > MAX_BUFFERTIME)
220 			buffer_time = MAX_BUFFERTIME;
221 
222 		period_time = buffer_time / DIV_BUFFERTIME;
223 
224 		/* Set buffer time and period time */
225 		err = snd_pcm_hw_params_set_buffer_time_near(sndpcm->handle,
226 				params, &buffer_time, 0);
227 		if (err < 0) {
228 			fprintf(bat->err, _("Set parameter to device error: "));
229 			fprintf(bat->err, _("buffer time: %d %s: %s(%d)\n"),
230 					buffer_time,
231 					device_name, snd_strerror(err), err);
232 			return err;
233 		}
234 
235 		err = snd_pcm_hw_params_set_period_time_near(sndpcm->handle,
236 				params, &period_time, 0);
237 		if (err < 0) {
238 			fprintf(bat->err, _("Set parameter to device error: "));
239 			fprintf(bat->err, _("period time: %d %s: %s(%d)\n"),
240 					period_time,
241 					device_name, snd_strerror(err), err);
242 			return err;
243 		}
244 	}
245 
246 	/* Write the parameters to the driver */
247 	if (snd_pcm_hw_params(sndpcm->handle, params) < 0) {
248 		fprintf(bat->err, _("Set parameter to device error: "));
249 		fprintf(bat->err, _("hw params: %s: %s(%d)\n"),
250 				device_name, snd_strerror(err), err);
251 		return -EINVAL;
252 	}
253 
254 	err = snd_pcm_hw_params_get_period_size(params,
255 			&sndpcm->period_size, 0);
256 	if (err < 0) {
257 		fprintf(bat->err, _("Get parameter from device error: "));
258 		fprintf(bat->err, _("period size: %zd %s: %s(%d)\n"),
259 				sndpcm->period_size,
260 				device_name, snd_strerror(err), err);
261 		return err;
262 	}
263 
264 	err = snd_pcm_hw_params_get_buffer_size(params, &sndpcm->buffer_size);
265 	if (err < 0) {
266 		fprintf(bat->err, _("Get parameter from device error: "));
267 		fprintf(bat->err, _("buffer size: %zd %s: %s(%d)\n"),
268 				sndpcm->buffer_size,
269 				device_name, snd_strerror(err), err);
270 		return err;
271 	}
272 
273 	if (sndpcm->period_size == sndpcm->buffer_size) {
274 		fprintf(bat->err, _("Invalid parameters: can't use period "));
275 		fprintf(bat->err, _("equal to buffer size (%zd)\n"),
276 				sndpcm->period_size);
277 		return -EINVAL;
278 	}
279 
280 	fprintf(bat->log, _("Get period size: %d  buffer size: %d\n"),
281 			(int) sndpcm->period_size, (int) sndpcm->buffer_size);
282 
283 	err = snd_pcm_format_physical_width(format);
284 	if (err < 0) {
285 		fprintf(bat->err, _("Invalid parameters: "));
286 		fprintf(bat->err, _("snd_pcm_format_physical_width: %d\n"),
287 				err);
288 		return err;
289 	}
290 	sndpcm->sample_bits = err;
291 
292 	sndpcm->frame_bits = sndpcm->sample_bits * bat->channels;
293 
294 	/* Calculate the period bytes */
295 	sndpcm->period_bytes = sndpcm->period_size * sndpcm->frame_bits / 8;
296 	sndpcm->buffer = (char *) malloc(sndpcm->period_bytes);
297 	if (sndpcm->buffer == NULL) {
298 		fprintf(bat->err, _("Not enough memory: size=%zd\n"),
299 				sndpcm->period_bytes);
300 		return -ENOMEM;
301 	}
302 
303 	return 0;
304 }
305 
write_to_pcm(const struct pcm_container *sndpcm, int frames, struct bat *bat)306 static int write_to_pcm(const struct pcm_container *sndpcm,
307 		int frames, struct bat *bat)
308 {
309 	int err;
310 	int offset = 0;
311 	int remain = frames;
312 
313 	while (remain > 0) {
314 		err = snd_pcm_writei(sndpcm->handle, sndpcm->buffer + offset,
315 				remain);
316 		if (err == -EAGAIN || (err >= 0 && err < frames)) {
317 			snd_pcm_wait(sndpcm->handle, 500);
318 		} else if (err == -EPIPE) {
319 			fprintf(bat->err, _("Underrun: %s(%d)\n"),
320 					snd_strerror(err), err);
321 			if (bat->roundtriplatency)
322 				bat->latency.xrun_error = true;
323 			snd_pcm_prepare(sndpcm->handle);
324 		} else if (err == -ESTRPIPE) {
325 			while ((err = snd_pcm_resume(sndpcm->handle)) == -EAGAIN)
326 				sleep(1);  /* wait until resume flag is released */
327 			if (err < 0)
328 				snd_pcm_prepare(sndpcm->handle);
329 		} else if (err < 0) {
330 			fprintf(bat->err, _("Write PCM device error: %s(%d)\n"),
331 					snd_strerror(err), err);
332 			return err;
333 		}
334 
335 		if (err > 0) {
336 			remain -= err;
337 			offset += err * sndpcm->frame_bits / 8;
338 		}
339 	}
340 
341 	return 0;
342 }
343 
344 /**
345  * Process output data for latency test
346  */
latencytest_process_output(struct pcm_container *sndpcm, struct bat *bat)347 static int latencytest_process_output(struct pcm_container *sndpcm,
348 		struct bat *bat)
349 {
350 	int err = 0;
351 	int bytes = sndpcm->period_bytes; /* playback buffer size */
352 	int frames = sndpcm->period_size; /* frame count */
353 
354 	bat->latency.is_playing = true;
355 
356 	while (1) {
357 		/* generate output data */
358 		err = handleoutput(bat, sndpcm->buffer, bytes, frames);
359 		if (err != 0)
360 			break;
361 
362 		err = write_to_pcm(sndpcm, frames, bat);
363 		if (err != 0)
364 			break;
365 
366 		/* Xrun error, terminate the playback thread*/
367 		if (bat->latency.xrun_error == true)
368 			break;
369 
370 		if (bat->latency.state == LATENCY_STATE_COMPLETE_SUCCESS)
371 			break;
372 
373 		bat->periods_played++;
374 	}
375 
376 	bat->latency.is_playing = false;
377 
378 	return err;
379 }
380 
write_to_pcm_loop(struct pcm_container *sndpcm, struct bat *bat)381 static int write_to_pcm_loop(struct pcm_container *sndpcm, struct bat *bat)
382 {
383 	int err = 0;
384 	int bytes = sndpcm->period_bytes; /* playback buffer size */
385 	int frames = bytes * 8 / sndpcm->frame_bits; /* frame count */
386 	FILE *fp = NULL;
387 	int bytes_total = 0;
388 
389 	if (bat->debugplay) {
390 		fp = fopen(bat->debugplay, "wb");
391 		err = -errno;
392 		if (fp == NULL) {
393 			fprintf(bat->err, _("Cannot open file: %s %d\n"),
394 					bat->debugplay, err);
395 			return err;
396 		}
397 		/* leave space for wav header */
398 		if (fseek(fp, sizeof(struct wav_container), SEEK_SET) != 0) {
399 			err = -errno;
400 			fclose(fp);
401 			return err;
402 		}
403 	}
404 
405 	while (1) {
406 		err = generate_input_data(bat, sndpcm->buffer, bytes, frames);
407 		if (err != 0)
408 			break;
409 
410 		if (bat->debugplay) {
411 			if (fwrite(sndpcm->buffer, 1, bytes, fp) != (size_t)bytes) {
412 				err = -EIO;
413 				break;
414 			}
415 			bytes_total += bytes;
416 		}
417 
418 		bat->periods_played++;
419 		if (bat->period_is_limited
420 				&& bat->periods_played >= bat->periods_total)
421 			break;
422 
423 		err = write_to_pcm(sndpcm, frames, bat);
424 		if (err != 0)
425 			break;
426 	}
427 
428 	if (bat->debugplay) {
429 		update_wav_header(bat, fp, bytes_total);
430 		fclose(fp);
431 	}
432 
433 	snd_pcm_drain(sndpcm->handle);
434 
435 	return err;
436 }
437 
438 /**
439  * Play
440  */
playback_alsa(struct bat *bat)441 void *playback_alsa(struct bat *bat)
442 {
443 	int err = 0;
444 	struct pcm_container sndpcm;
445 
446 	fprintf(bat->log, _("Entering playback thread (ALSA).\n"));
447 
448 	retval_play = 0;
449 	memset(&sndpcm, 0, sizeof(sndpcm));
450 
451 	err = snd_pcm_open(&sndpcm.handle, bat->playback.device,
452 			SND_PCM_STREAM_PLAYBACK, 0);
453 	if (err != 0) {
454 		fprintf(bat->err, _("Cannot open PCM playback device: "));
455 		fprintf(bat->err, _("%s(%d)\n"), snd_strerror(err), err);
456 		retval_play = err;
457 		goto exit1;
458 	}
459 
460 	err = set_snd_pcm_params(bat, &sndpcm);
461 	if (err != 0) {
462 		retval_play = err;
463 		goto exit2;
464 	}
465 
466 	if (bat->playback.file == NULL) {
467 		fprintf(bat->log, _("Playing generated audio sine wave"));
468 		bat->sinus_duration == 0 ?
469 			fprintf(bat->log, _(" endlessly\n")) :
470 			fprintf(bat->log, _("\n"));
471 	} else {
472 		fprintf(bat->log, _("Playing input audio file: %s\n"),
473 				bat->playback.file);
474 		bat->fp = fopen(bat->playback.file, "rb");
475 		err = -errno;
476 		if (bat->fp == NULL) {
477 			fprintf(bat->err, _("Cannot open file: %s %d\n"),
478 					bat->playback.file, err);
479 			retval_play = err;
480 			goto exit3;
481 		}
482 		/* Skip header */
483 		err = read_wav_header(bat, bat->playback.file, bat->fp, true);
484 		if (err != 0) {
485 			retval_play = err;
486 			goto exit4;
487 		}
488 	}
489 
490 	if (bat->roundtriplatency)
491 		err = latencytest_process_output(&sndpcm, bat);
492 	else
493 		err = write_to_pcm_loop(&sndpcm, bat);
494 	if (err < 0) {
495 		retval_play = err;
496 		goto exit4;
497 	}
498 
499 exit4:
500 	if (bat->playback.file)
501 		fclose(bat->fp);
502 exit3:
503 	free(sndpcm.buffer);
504 exit2:
505 	snd_pcm_close(sndpcm.handle);
506 exit1:
507 	pthread_exit(&retval_play);
508 }
509 
read_from_pcm(struct pcm_container *sndpcm, int frames, struct bat *bat)510 static int read_from_pcm(struct pcm_container *sndpcm,
511 		int frames, struct bat *bat)
512 {
513 	int err = 0;
514 	int offset = 0;
515 	int remain = frames;
516 
517 	while (remain > 0) {
518 		err = snd_pcm_readi(sndpcm->handle,
519 				sndpcm->buffer + offset, remain);
520 		if (err == -EAGAIN || (err >= 0 && err < remain)) {
521 			snd_pcm_wait(sndpcm->handle, 500);
522 		} else if (err == -EPIPE) {
523 			snd_pcm_prepare(sndpcm->handle);
524 			fprintf(bat->err, _("Overrun: %s(%d)\n"),
525 					snd_strerror(err), err);
526 			if (bat->roundtriplatency)
527 				bat->latency.xrun_error = true;
528 		} else if (err == -ESTRPIPE) {
529 			while ((err = snd_pcm_resume(sndpcm->handle)) == -EAGAIN)
530 				sleep(1);  /* wait until resume flag is released */
531 			if (err < 0)
532 				snd_pcm_prepare(sndpcm->handle);
533 		} else if (err < 0) {
534 			fprintf(bat->err, _("Read PCM device error: %s(%d)\n"),
535 					snd_strerror(err), err);
536 			return err;
537 		}
538 
539 		if (err > 0) {
540 			remain -= err;
541 			offset += err * sndpcm->frame_bits / 8;
542 		}
543 	}
544 
545 	return 0;
546 }
547 
read_from_pcm_loop(struct pcm_container *sndpcm, struct bat *bat)548 static int read_from_pcm_loop(struct pcm_container *sndpcm, struct bat *bat)
549 {
550 	int err = 0;
551 	FILE *fp = NULL;
552 	int size, frames;
553 	int bytes_read = 0;
554 	int bytes_count = bat->frames * bat->frame_size;
555 	unsigned int remain = bytes_count;
556 
557 	remove(bat->capture.file);
558 	fp = fopen(bat->capture.file, "wb");
559 	err = -errno;
560 	if (fp == NULL) {
561 		fprintf(bat->err, _("Cannot open file: %s %d\n"),
562 				bat->capture.file, err);
563 		return err;
564 	}
565 	/* leave space for file header */
566 	if (fseek(fp, sizeof(struct wav_container), SEEK_SET) != 0) {
567 		err = -errno;
568 		fclose(fp);
569 		return err;
570 	}
571 
572 	while (remain > 0) {
573 		size = (remain <= sndpcm->period_bytes) ?
574 			remain : sndpcm->period_bytes;
575 		frames = size * 8 / sndpcm->frame_bits;
576 
577 		/* read a chunk from pcm device */
578 		err = read_from_pcm(sndpcm, frames, bat);
579 		if (err != 0)
580 			break;
581 
582 		/* write the chunk to file */
583 		if (fwrite(sndpcm->buffer, 1, size, fp) != (size_t)size) {
584 			err = -EIO;
585 			break;
586 		}
587 
588 		bytes_read += size;
589 		remain -= size;
590 		bat->periods_played++;
591 
592 		if (bat->period_is_limited
593 				&& bat->periods_played >= bat->periods_total)
594 			break;
595 	}
596 
597 	update_wav_header(bat, fp, bytes_read);
598 
599 	fclose(fp);
600 	return err;
601 }
602 
603 /**
604  * Process input data for latency test
605  */
latencytest_process_input(struct pcm_container *sndpcm, struct bat *bat)606 static int latencytest_process_input(struct pcm_container *sndpcm,
607 		struct bat *bat)
608 {
609 	int err = 0;
610 	FILE *fp = NULL;
611 	int bytes_read = 0;
612 	int frames = sndpcm->period_size;
613 	int size = sndpcm->period_bytes;
614 	int bytes_count = bat->frames * bat->frame_size;
615 
616 	remove(bat->capture.file);
617 	fp = fopen(bat->capture.file, "wb");
618 	err = -errno;
619 	if (fp == NULL) {
620 		fprintf(bat->err, _("Cannot open file: %s %d\n"),
621 				bat->capture.file, err);
622 		return err;
623 	}
624 	/* leave space for file header */
625 	if (fseek(fp, sizeof(struct wav_container), SEEK_SET) != 0) {
626 		fclose(fp);
627 		return err;
628 	}
629 
630 	bat->latency.is_capturing = true;
631 
632 	while (bytes_read < bytes_count) {
633 		/* read a chunk from pcm device */
634 		err = read_from_pcm(sndpcm, frames, bat);
635 		if (err != 0)
636 			break;
637 
638 		/* Xrun error, terminate the capture thread*/
639 		if (bat->latency.xrun_error == true)
640 			break;
641 
642 		err = handleinput(bat, sndpcm->buffer, frames);
643 		if (err != 0)
644 			break;
645 
646 		if (bat->latency.is_playing == false)
647 			break;
648 
649 		/* write the chunk to file */
650 		if (fwrite(sndpcm->buffer, 1, size, fp) != (size_t)size) {
651 			err = -EIO;
652 			break;
653 		}
654 
655 		bytes_read += size;
656 	}
657 
658 	bat->latency.is_capturing = false;
659 
660 	update_wav_header(bat, fp, bytes_read);
661 
662 	fclose(fp);
663 	return err;
664 }
665 
666 
pcm_cleanup(void *p)667 static void pcm_cleanup(void *p)
668 {
669 	snd_pcm_close(p);
670 }
671 
672 /**
673  * Record
674  */
record_alsa(struct bat *bat)675 void *record_alsa(struct bat *bat)
676 {
677 	int err = 0;
678 	struct pcm_container sndpcm;
679 
680 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
681 
682 	fprintf(bat->log, _("Entering capture thread (ALSA).\n"));
683 
684 	retval_record = 0;
685 	memset(&sndpcm, 0, sizeof(sndpcm));
686 
687 	err = snd_pcm_open(&sndpcm.handle, bat->capture.device,
688 			SND_PCM_STREAM_CAPTURE, 0);
689 	if (err != 0) {
690 		fprintf(bat->err, _("Cannot open PCM capture device: "));
691 		fprintf(bat->err, _("%s(%d)\n"), snd_strerror(err), err);
692 		retval_record = err;
693 		goto exit1;
694 	}
695 
696 	err = set_snd_pcm_params(bat, &sndpcm);
697 	if (err != 0) {
698 		retval_record = err;
699 		goto exit2;
700 	}
701 
702 	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
703 	pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
704 	pthread_cleanup_push(pcm_cleanup, sndpcm.handle);
705 	pthread_cleanup_push(free, sndpcm.buffer);
706 
707 	fprintf(bat->log, _("Recording ...\n"));
708 	if (bat->roundtriplatency)
709 		err = latencytest_process_input(&sndpcm, bat);
710 	else
711 		err = read_from_pcm_loop(&sndpcm, bat);
712 
713 	pthread_cleanup_pop(0);
714 	pthread_cleanup_pop(0);
715 
716 	if (err != 0) {
717 		retval_record = err;
718 		goto exit3;
719 	}
720 
721 	/* Normally we will never reach this part of code (unless error in
722 	 * previous call) (before exit3) as this thread will be cancelled
723 	 * by end of play thread. Except in single line mode. */
724 	snd_pcm_drain(sndpcm.handle);
725 	pthread_exit(&retval_record);
726 
727 exit3:
728 	free(sndpcm.buffer);
729 exit2:
730 	snd_pcm_close(sndpcm.handle);
731 exit1:
732 	pthread_exit(&retval_record);
733 }
734