Blame bat/tinyalsa.c

Packit 229ac0
/*
Packit 229ac0
 * Copyright (C) 2013-2015 Intel Corporation
Packit 229ac0
 *
Packit 229ac0
 * This program is free software; you can redistribute it and/or modify
Packit 229ac0
 * it under the terms of the GNU General Public License as published by
Packit 229ac0
 * the Free Software Foundation; either version 2 of the License, or
Packit 229ac0
 * (at your option) any later version.
Packit 229ac0
 *
Packit 229ac0
 * This program is distributed in the hope that it will be useful,
Packit 229ac0
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 229ac0
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 229ac0
 * GNU General Public License for more details.
Packit 229ac0
 *
Packit 229ac0
 */
Packit 229ac0
Packit 229ac0
#include <stdio.h>
Packit 229ac0
#include <string.h>
Packit 229ac0
#include <stdbool.h>
Packit 229ac0
#include <stdlib.h>
Packit 229ac0
#include <pthread.h>
Packit 229ac0
#include <errno.h>
Packit 229ac0
Packit 229ac0
#include <tinyalsa/asoundlib.h>
Packit 229ac0
Packit 229ac0
#include "aconfig.h"
Packit 229ac0
#include "gettext.h"
Packit 229ac0
Packit 229ac0
#include "common.h"
Packit 229ac0
#include "tinyalsa.h"
Packit 229ac0
#include "latencytest.h"
Packit 229ac0
Packit 229ac0
struct format_map_table {
Packit 229ac0
	enum _bat_pcm_format format_bat;
Packit 229ac0
	enum pcm_format format_tiny;
Packit 229ac0
};
Packit 229ac0
Packit 229ac0
static struct format_map_table map_tables[] = {
Packit 229ac0
	{ BAT_PCM_FORMAT_S16_LE, PCM_FORMAT_S16_LE },
Packit 229ac0
	{ BAT_PCM_FORMAT_S32_LE, PCM_FORMAT_S32_LE },
Packit 229ac0
	{ BAT_PCM_FORMAT_MAX, },
Packit 229ac0
};
Packit 229ac0
Packit 229ac0
static int format_convert(struct bat *bat, struct pcm_config *config)
Packit 229ac0
{
Packit 229ac0
	struct format_map_table *t = map_tables;
Packit 229ac0
Packit 229ac0
	for (; t->format_bat != BAT_PCM_FORMAT_MAX; t++) {
Packit 229ac0
		if (t->format_bat == bat->format) {
Packit 229ac0
			config->format = t->format_tiny;
Packit 229ac0
			return 0;
Packit 229ac0
		}
Packit 229ac0
	}
Packit 229ac0
	fprintf(bat->err, _("Invalid format!\n"));
Packit 229ac0
	return -EINVAL;
Packit 229ac0
}
Packit 229ac0
Packit 229ac0
static int init_config(struct bat *bat, struct pcm_config *config)
Packit 229ac0
{
Packit 229ac0
	config->channels = bat->channels;
Packit 229ac0
	config->rate = bat->rate;
Packit 229ac0
	if (bat->period_size > 0)
Packit 229ac0
		config->period_size = bat->period_size;
Packit 229ac0
	else
Packit 229ac0
		config->period_size = TINYALSA_PERIODSIZE;
Packit 229ac0
	config->period_count = 4;
Packit 229ac0
	config->start_threshold = 0;
Packit 229ac0
	config->stop_threshold = 0;
Packit 229ac0
	config->silence_threshold = 0;
Packit 229ac0
Packit 229ac0
	return format_convert(bat, config);
Packit 229ac0
}
Packit 229ac0
Packit 229ac0
/**
Packit 229ac0
 * Called when thread is finished
Packit 229ac0
 */
Packit 229ac0
static void close_handle(void *handle)
Packit 229ac0
{
Packit 229ac0
	struct pcm *pcm = handle;
Packit 229ac0
Packit 229ac0
	if (NULL != pcm)
Packit 229ac0
		pcm_close(pcm);
Packit 229ac0
}
Packit 229ac0
Packit 229ac0
/**
Packit 229ac0
 * Check that a parameter is inside bounds
Packit 229ac0
 */
Packit 229ac0
static int check_param(struct bat *bat, struct pcm_params *params,
Packit 229ac0
		unsigned int param, unsigned int value,
Packit 229ac0
		char *param_name, char *param_unit)
Packit 229ac0
{
Packit 229ac0
	unsigned int min;
Packit 229ac0
	unsigned int max;
Packit 229ac0
	int ret = 0;
Packit 229ac0
Packit 229ac0
	min = pcm_params_get_min(params, param);
Packit 229ac0
	if (value < min) {
Packit 229ac0
		fprintf(bat->err,
Packit 229ac0
			_("%s is %u%s, device only supports >= %u%s!\n"),
Packit 229ac0
			param_name, value, param_unit, min, param_unit);
Packit 229ac0
		ret = -EINVAL;
Packit 229ac0
	}
Packit 229ac0
Packit 229ac0
	max = pcm_params_get_max(params, param);
Packit 229ac0
	if (value > max) {
Packit 229ac0
		fprintf(bat->err,
Packit 229ac0
			_("%s is %u%s, device only supports <= %u%s!\n"),
Packit 229ac0
			param_name, value, param_unit, max, param_unit);
Packit 229ac0
		ret = -EINVAL;
Packit 229ac0
	}
Packit 229ac0
Packit 229ac0
	return ret;
Packit 229ac0
}
Packit 229ac0
Packit 229ac0
/**
Packit 229ac0
 * Check all parameters
Packit 229ac0
 */
Packit 229ac0
static int check_playback_params(struct bat *bat,
Packit 229ac0
		struct pcm_config *config)
Packit 229ac0
{
Packit 229ac0
	struct pcm_params *params;
Packit 229ac0
	unsigned int card = bat->playback.card_tiny;
Packit 229ac0
	unsigned int device = bat->playback.device_tiny;
Packit 229ac0
	int err = 0;
Packit 229ac0
Packit 229ac0
	params = pcm_params_get(card, device, PCM_OUT);
Packit 229ac0
	if (params == NULL) {
Packit 229ac0
		fprintf(bat->err, _("Unable to open PCM device %u!\n"),
Packit 229ac0
				device);
Packit 229ac0
		return -EINVAL;
Packit 229ac0
	}
Packit 229ac0
Packit 229ac0
	err = check_param(bat, params, PCM_PARAM_RATE,
Packit 229ac0
			config->rate, "Sample rate", "Hz");
Packit 229ac0
	if (err < 0)
Packit 229ac0
		goto exit;
Packit 229ac0
	err = check_param(bat, params, PCM_PARAM_CHANNELS,
Packit 229ac0
			config->channels, "Sample", " channels");
Packit 229ac0
	if (err < 0)
Packit 229ac0
		goto exit;
Packit 229ac0
	err = check_param(bat, params, PCM_PARAM_SAMPLE_BITS,
Packit 229ac0
			bat->sample_size * 8, "Bitrate", " bits");
Packit 229ac0
	if (err < 0)
Packit 229ac0
		goto exit;
Packit 229ac0
	err = check_param(bat, params, PCM_PARAM_PERIOD_SIZE,
Packit 229ac0
			config->period_size, "Period size", "Hz");
Packit 229ac0
	if (err < 0)
Packit 229ac0
		goto exit;
Packit 229ac0
	err = check_param(bat, params, PCM_PARAM_PERIODS,
Packit 229ac0
			config->period_count, "Period count", "Hz");
Packit 229ac0
	if (err < 0)
Packit 229ac0
		goto exit;
Packit 229ac0
Packit 229ac0
exit:
Packit 229ac0
	pcm_params_free(params);
Packit 229ac0
Packit 229ac0
	return err;
Packit 229ac0
}
Packit 229ac0
Packit 229ac0
/**
Packit 229ac0
 * Process output data for latency test
Packit 229ac0
 */
Packit 229ac0
static int latencytest_process_output(struct bat *bat, struct pcm *pcm,
Packit 229ac0
		void *buffer, int bytes)
Packit 229ac0
{
Packit 229ac0
	int err = 0;
Packit 229ac0
	int frames = bytes / bat->frame_size;
Packit 229ac0
Packit 229ac0
	fprintf(bat->log, _("Play sample with %d frames buffer\n"), frames);
Packit 229ac0
Packit 229ac0
	bat->latency.is_playing = true;
Packit 229ac0
Packit 229ac0
	while (1) {
Packit 229ac0
		/* generate output data */
Packit 229ac0
		err = handleoutput(bat, buffer, bytes, frames);
Packit 229ac0
		if (err != 0)
Packit 229ac0
			break;
Packit 229ac0
Packit 229ac0
		err = pcm_write(pcm, buffer, bytes);
Packit 229ac0
		if (err != 0)
Packit 229ac0
			break;
Packit 229ac0
Packit 229ac0
		if (bat->latency.state == LATENCY_STATE_COMPLETE_SUCCESS)
Packit 229ac0
			break;
Packit 229ac0
Packit 229ac0
		bat->periods_played++;
Packit 229ac0
	}
Packit 229ac0
Packit 229ac0
	bat->latency.is_playing = false;
Packit 229ac0
Packit 229ac0
	return err;
Packit 229ac0
}
Packit 229ac0
Packit 229ac0
/**
Packit 229ac0
 * Play sample
Packit 229ac0
 */
Packit 229ac0
static int play_sample(struct bat *bat, struct pcm *pcm,
Packit 229ac0
		void *buffer, int bytes)
Packit 229ac0
{
Packit 229ac0
	int err = 0;
Packit 229ac0
	int frames = bytes / bat->frame_size;
Packit 229ac0
	FILE *fp = NULL;
Packit 229ac0
	int bytes_total = 0;
Packit 229ac0
Packit 229ac0
	if (bat->debugplay) {
Packit 229ac0
		fp = fopen(bat->debugplay, "wb");
Packit 229ac0
		err = -errno;
Packit 229ac0
		if (fp == NULL) {
Packit 229ac0
			fprintf(bat->err, _("Cannot open file: %s %d\n"),
Packit 229ac0
					bat->debugplay, err);
Packit 229ac0
			return err;
Packit 229ac0
		}
Packit 229ac0
		/* leave space for file header */
Packit 229ac0
		if (fseek(fp, sizeof(struct wav_container), SEEK_SET) != 0) {
Packit 229ac0
			err = -errno;
Packit 229ac0
			fclose(fp);
Packit 229ac0
			return err;
Packit 229ac0
		}
Packit 229ac0
	}
Packit 229ac0
Packit 229ac0
	while (1) {
Packit 229ac0
		err = generate_input_data(bat, buffer, bytes, frames);
Packit 229ac0
		if (err != 0)
Packit 229ac0
			break;
Packit 229ac0
Packit 229ac0
		if (bat->debugplay) {
Packit 229ac0
			if (fwrite(buffer, 1, bytes, fp) != bytes) {
Packit 229ac0
				err = -EIO;
Packit 229ac0
				break;
Packit 229ac0
			}
Packit 229ac0
			bytes_total += bytes;
Packit 229ac0
		}
Packit 229ac0
Packit 229ac0
		bat->periods_played++;
Packit 229ac0
		if (bat->period_is_limited
Packit 229ac0
				&& bat->periods_played >= bat->periods_total)
Packit 229ac0
			break;
Packit 229ac0
Packit 229ac0
		err = pcm_write(pcm, buffer, bytes);
Packit 229ac0
		if (err != 0)
Packit 229ac0
			break;
Packit 229ac0
	}
Packit 229ac0
Packit 229ac0
	if (bat->debugplay) {
Packit 229ac0
		update_wav_header(bat, fp, bytes_total);
Packit 229ac0
		fclose(fp);
Packit 229ac0
	}
Packit 229ac0
	return err;
Packit 229ac0
}
Packit 229ac0
Packit 229ac0
static int get_tiny_device(struct bat *bat, char *alsa_device,
Packit 229ac0
		unsigned int *tiny_card, unsigned int *tiny_device)
Packit 229ac0
{
Packit 229ac0
	char *tmp1, *tmp2, *tmp3;
Packit 229ac0
Packit 229ac0
	if (alsa_device == NULL)
Packit 229ac0
		goto fail;
Packit 229ac0
Packit 229ac0
	tmp1 = strchr(alsa_device, ':');
Packit 229ac0
	if (tmp1 == NULL)
Packit 229ac0
		goto fail;
Packit 229ac0
Packit 229ac0
	tmp3 = tmp1 + 1;
Packit 229ac0
	tmp2 = strchr(tmp3, ',');
Packit 229ac0
	if (tmp2 == NULL)
Packit 229ac0
		goto fail;
Packit 229ac0
Packit 229ac0
	tmp1 = tmp2 + 1;
Packit 229ac0
	*tiny_device = atoi(tmp1);
Packit 229ac0
	*tmp2 = '\0';
Packit 229ac0
	*tiny_card = atoi(tmp3);
Packit 229ac0
	*tmp2 = ',';
Packit 229ac0
Packit 229ac0
	return 0;
Packit 229ac0
fail:
Packit 229ac0
	fprintf(bat->err, _("Invalid tiny device: %s\n"), alsa_device);
Packit 229ac0
	return -EINVAL;
Packit 229ac0
}
Packit 229ac0
Packit 229ac0
/**
Packit 229ac0
 * Play
Packit 229ac0
 */
Packit 229ac0
void *playback_tinyalsa(struct bat *bat)
Packit 229ac0
{
Packit 229ac0
	int err = 0;
Packit 229ac0
	struct pcm_config config;
Packit 229ac0
	struct pcm *pcm = NULL;
Packit 229ac0
	void *buffer = NULL;
Packit 229ac0
	int bufbytes;
Packit 229ac0
Packit 229ac0
	fprintf(bat->log, _("Entering playback thread (tinyalsa).\n"));
Packit 229ac0
Packit 229ac0
	retval_play = 0;
Packit 229ac0
Packit 229ac0
	/* init device */
Packit 229ac0
	err = get_tiny_device(bat, bat->playback.device,
Packit 229ac0
			&bat->playback.card_tiny,
Packit 229ac0
			&bat->playback.device_tiny);
Packit 229ac0
	if (err < 0) {
Packit 229ac0
		retval_play = err;
Packit 229ac0
		goto exit1;
Packit 229ac0
	}
Packit 229ac0
Packit 229ac0
	/* init config */
Packit 229ac0
	err = init_config(bat, &config);
Packit 229ac0
	if (err < 0) {
Packit 229ac0
		retval_play = err;
Packit 229ac0
		goto exit1;
Packit 229ac0
	}
Packit 229ac0
Packit 229ac0
	/* check param before open device */
Packit 229ac0
	err = check_playback_params(bat, &config);
Packit 229ac0
	if (err < 0) {
Packit 229ac0
		retval_play = err;
Packit 229ac0
		goto exit1;
Packit 229ac0
	}
Packit 229ac0
Packit 229ac0
	/* open device */
Packit 229ac0
	pcm = pcm_open(bat->playback.card_tiny, bat->playback.device_tiny,
Packit 229ac0
			PCM_OUT, &config);
Packit 229ac0
	if (!pcm || !pcm_is_ready(pcm)) {
Packit 229ac0
		fprintf(bat->err, _("Unable to open PCM device %u (%s)!\n"),
Packit 229ac0
				bat->playback.device_tiny, pcm_get_error(pcm));
Packit 229ac0
		retval_play = -EINVAL;
Packit 229ac0
		goto exit1;
Packit 229ac0
	}
Packit 229ac0
Packit 229ac0
	/* init buffer */
Packit 229ac0
	bufbytes = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm));
Packit 229ac0
	buffer = malloc(bufbytes);
Packit 229ac0
	if (!buffer) {
Packit 229ac0
		retval_play = -ENOMEM;
Packit 229ac0
		goto exit2;
Packit 229ac0
	}
Packit 229ac0
Packit 229ac0
	/* init playback source */
Packit 229ac0
	if (bat->playback.file == NULL) {
Packit 229ac0
		fprintf(bat->log, _("Playing generated audio sine wave"));
Packit 229ac0
		bat->sinus_duration == 0 ?
Packit 229ac0
			fprintf(bat->log, _(" endlessly\n")) :
Packit 229ac0
			fprintf(bat->log, _("\n"));
Packit 229ac0
	} else {
Packit 229ac0
		fprintf(bat->log, _("Playing input audio file: %s\n"),
Packit 229ac0
				bat->playback.file);
Packit 229ac0
		bat->fp = fopen(bat->playback.file, "rb");
Packit 229ac0
		err = -errno;
Packit 229ac0
		if (bat->fp == NULL) {
Packit 229ac0
			fprintf(bat->err, _("Cannot open file: %s %d\n"),
Packit 229ac0
					bat->playback.file, err);
Packit 229ac0
			retval_play = err;
Packit 229ac0
			goto exit3;
Packit 229ac0
		}
Packit 229ac0
		/* Skip header */
Packit 229ac0
		err = read_wav_header(bat, bat->playback.file, bat->fp, true);
Packit 229ac0
		if (err != 0) {
Packit 229ac0
			retval_play = err;
Packit 229ac0
			goto exit4;
Packit 229ac0
		}
Packit 229ac0
	}
Packit 229ac0
Packit 229ac0
	if (bat->roundtriplatency)
Packit 229ac0
		err = latencytest_process_output(bat, pcm, buffer, bufbytes);
Packit 229ac0
	else
Packit 229ac0
		err = play_sample(bat, pcm, buffer, bufbytes);
Packit 229ac0
	if (err < 0) {
Packit 229ac0
		retval_play = err;
Packit 229ac0
		goto exit4;
Packit 229ac0
	}
Packit 229ac0
Packit 229ac0
exit4:
Packit 229ac0
	if (bat->playback.file)
Packit 229ac0
		fclose(bat->fp);
Packit 229ac0
exit3:
Packit 229ac0
	free(buffer);
Packit 229ac0
exit2:
Packit 229ac0
	pcm_close(pcm);
Packit 229ac0
exit1:
Packit 229ac0
	pthread_exit(&retval_play);
Packit 229ac0
}
Packit 229ac0
Packit 229ac0
/**
Packit 229ac0
 * Capture sample
Packit 229ac0
 */
Packit 229ac0
static int capture_sample(struct bat *bat, struct pcm *pcm,
Packit 229ac0
		void *buffer, unsigned int bytes)
Packit 229ac0
{
Packit 229ac0
	int err = 0;
Packit 229ac0
	FILE *fp = NULL;
Packit 229ac0
	unsigned int bytes_read = 0;
Packit 229ac0
	unsigned int bytes_count = bat->frames * bat->frame_size;
Packit 229ac0
Packit 229ac0
	remove(bat->capture.file);
Packit 229ac0
	fp = fopen(bat->capture.file, "wb");
Packit 229ac0
	err = -errno;
Packit 229ac0
	if (fp == NULL) {
Packit 229ac0
		fprintf(bat->err, _("Cannot open file: %s %d\n"),
Packit 229ac0
				bat->capture.file, err);
Packit 229ac0
		return err;
Packit 229ac0
	}
Packit 229ac0
	/* leave space for file header */
Packit 229ac0
	if (fseek(fp, sizeof(struct wav_container), SEEK_SET) != 0) {
Packit 229ac0
		err = -errno;
Packit 229ac0
		fclose(fp);
Packit 229ac0
		return err;
Packit 229ac0
	}
Packit 229ac0
Packit 229ac0
	while (bytes_read < bytes_count && !pcm_read(pcm, buffer, bytes)) {
Packit 229ac0
		if (fwrite(buffer, 1, bytes, fp) != bytes)
Packit 229ac0
			break;
Packit 229ac0
Packit 229ac0
		bytes_read += bytes;
Packit 229ac0
Packit 229ac0
		bat->periods_played++;
Packit 229ac0
Packit 229ac0
		if (bat->period_is_limited
Packit 229ac0
				&& bat->periods_played >= bat->periods_total)
Packit 229ac0
			break;
Packit 229ac0
	}
Packit 229ac0
Packit 229ac0
	err = update_wav_header(bat, fp, bytes_read);
Packit 229ac0
Packit 229ac0
	fclose(fp);
Packit 229ac0
	return err;
Packit 229ac0
}
Packit 229ac0
Packit 229ac0
/**
Packit 229ac0
 * Process input data for latency test
Packit 229ac0
 */
Packit 229ac0
static int latencytest_process_input(struct bat *bat, struct pcm *pcm,
Packit 229ac0
		void *buffer, unsigned int bytes)
Packit 229ac0
{
Packit 229ac0
	int err = 0;
Packit 229ac0
	FILE *fp = NULL;
Packit 229ac0
	unsigned int bytes_read = 0;
Packit 229ac0
	unsigned int bytes_count = bat->frames * bat->frame_size;
Packit 229ac0
Packit 229ac0
	remove(bat->capture.file);
Packit 229ac0
	fp = fopen(bat->capture.file, "wb");
Packit 229ac0
	err = -errno;
Packit 229ac0
	if (fp == NULL) {
Packit 229ac0
		fprintf(bat->err, _("Cannot open file: %s %d\n"),
Packit 229ac0
				bat->capture.file, err);
Packit 229ac0
		return err;
Packit 229ac0
	}
Packit 229ac0
	/* leave space for file header */
Packit 229ac0
	if (fseek(fp, sizeof(struct wav_container), SEEK_SET) != 0) {
Packit 229ac0
		err = -errno;
Packit 229ac0
		fclose(fp);
Packit 229ac0
		return err;
Packit 229ac0
	}
Packit 229ac0
Packit 229ac0
	bat->latency.is_capturing = true;
Packit 229ac0
Packit 229ac0
	while (bytes_read < bytes_count && !pcm_read(pcm, buffer, bytes)) {
Packit 229ac0
		if (fwrite(buffer, 1, bytes, fp) != bytes)
Packit 229ac0
			break;
Packit 229ac0
Packit 229ac0
		err = handleinput(bat, buffer, bytes / bat->frame_size);
Packit 229ac0
		if (err != 0)
Packit 229ac0
			break;
Packit 229ac0
Packit 229ac0
		if (bat->latency.is_playing == false)
Packit 229ac0
			break;
Packit 229ac0
Packit 229ac0
		bytes_read += bytes;
Packit 229ac0
	}
Packit 229ac0
Packit 229ac0
	bat->latency.is_capturing = false;
Packit 229ac0
Packit 229ac0
	err = update_wav_header(bat, fp, bytes_read);
Packit 229ac0
Packit 229ac0
	fclose(fp);
Packit 229ac0
	return err;
Packit 229ac0
}
Packit 229ac0
Packit 229ac0
/**
Packit 229ac0
 * Record
Packit 229ac0
 */
Packit 229ac0
void *record_tinyalsa(struct bat *bat)
Packit 229ac0
{
Packit 229ac0
	int err = 0;
Packit 229ac0
	struct pcm_config config;
Packit 229ac0
	struct pcm *pcm;
Packit 229ac0
	void *buffer;
Packit 229ac0
	unsigned int bufbytes;
Packit 229ac0
Packit 229ac0
	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
Packit 229ac0
Packit 229ac0
	fprintf(bat->log, _("Entering capture thread (tinyalsa).\n"));
Packit 229ac0
Packit 229ac0
	retval_record = 0;
Packit 229ac0
Packit 229ac0
	/* init device */
Packit 229ac0
	err = get_tiny_device(bat, bat->capture.device,
Packit 229ac0
			&bat->capture.card_tiny,
Packit 229ac0
			&bat->capture.device_tiny);
Packit 229ac0
	if (err < 0) {
Packit 229ac0
		retval_record = err;
Packit 229ac0
		goto exit1;
Packit 229ac0
	}
Packit 229ac0
Packit 229ac0
	/* init config */
Packit 229ac0
	err = init_config(bat, &config);
Packit 229ac0
	if (err < 0) {
Packit 229ac0
		retval_record = err;
Packit 229ac0
		goto exit1;
Packit 229ac0
	}
Packit 229ac0
Packit 229ac0
	/* open device */
Packit 229ac0
	pcm = pcm_open(bat->capture.card_tiny, bat->capture.device_tiny,
Packit 229ac0
			PCM_IN, &config);
Packit 229ac0
	if (!pcm || !pcm_is_ready(pcm)) {
Packit 229ac0
		fprintf(bat->err, _("Unable to open PCM device (%s)!\n"),
Packit 229ac0
				pcm_get_error(pcm));
Packit 229ac0
		retval_record = -EINVAL;
Packit 229ac0
		goto exit1;
Packit 229ac0
	}
Packit 229ac0
Packit 229ac0
	/* init buffer */
Packit 229ac0
	bufbytes = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm));
Packit 229ac0
	buffer = malloc(bufbytes);
Packit 229ac0
	if (!buffer) {
Packit 229ac0
		retval_record = -ENOMEM;
Packit 229ac0
		goto exit2;
Packit 229ac0
	}
Packit 229ac0
Packit 229ac0
	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
Packit 229ac0
	pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
Packit 229ac0
	pthread_cleanup_push(close_handle, pcm);
Packit 229ac0
	pthread_cleanup_push(free, buffer);
Packit 229ac0
Packit 229ac0
	fprintf(bat->log, _("Recording ...\n"));
Packit 229ac0
	if (bat->roundtriplatency)
Packit 229ac0
		err = latencytest_process_input(bat, pcm, buffer, bufbytes);
Packit 229ac0
	else
Packit 229ac0
		err = capture_sample(bat, pcm, buffer, bufbytes);
Packit 229ac0
	if (err != 0) {
Packit 229ac0
		retval_record = err;
Packit 229ac0
		goto exit3;
Packit 229ac0
	}
Packit 229ac0
Packit 229ac0
	/* Normally we will never reach this part of code (unless error in
Packit 229ac0
	 * previous call) (before exit3) as this thread will be cancelled
Packit 229ac0
	 *  by end of play thread. Except in single line mode. */
Packit 229ac0
	pthread_cleanup_pop(0);
Packit 229ac0
	pthread_cleanup_pop(0);
Packit 229ac0
	pthread_exit(&retval_record);
Packit 229ac0
Packit 229ac0
exit3:
Packit 229ac0
	free(buffer);
Packit 229ac0
exit2:
Packit 229ac0
	pcm_close(pcm);
Packit 229ac0
exit1:
Packit 229ac0
	pthread_exit(&retval_record);
Packit 229ac0
}