Skip to contentSkip to conversation

alsabat: clean structure and tinyalsa support

PATCH Superseded [email protected] 2 participants 8 messages Mar 22, 2016

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

v2 cover alsabat: clean structure and tinyalsa support

From: "Lu, Han" <[email protected]>

1. refactoring alsa process to make structure simpler and cleaner, use general functions and unified return value for convenience of maintaining;
2. add tinyalsa support, user can choose tinyalsa with "configure --enable-tinyalsa" option. By default ALSA lib is used. The purpose
is for alsabat to run on tinyalsa platforms such as Android and some IoT devices.

Lu, Han (6):
alsabat: refactoring alsa capture thread
alsabat: use general function for wav header update
alsabat: clean return value for playback and capture threads
alsabat: use general data generator function
alsabat: move alsa process to a single block
alsabat: add tinyalsa support

 bat/Makefile.am |  12 +-
 bat/alsa.c      | 217 +++++++++++---------------
 bat/alsabat.1   |   3 +
 bat/bat.c       |  58 +++----
 bat/common.c    |  68 +++++++++
 bat/common.h    |  17 ++-
 bat/signal.c    |  13 +-
 bat/tinyalsa.c  | 460 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 bat/tinyalsa.h  |  20 +++
 configure.ac    |  17 +++
 10 files changed, 711 insertions(+), 174 deletions(-)
 create mode 100644 bat/tinyalsa.c
 create mode 100644 bat/tinyalsa.h
Signature · 1 line
2.5.0
#1 lore raw

PATCH v2 1/6 alsabat: refactoring alsa capture thread

From: "Lu, Han" <[email protected]>

Refactoring ALSA capture thread:
1. Move file open/seek operations to sub function, so all file processes are now on a single function (read_from_pcm_loop()), so the structure is more reasonable, the function API is simplified and no need file cleanup in thread loop.
2. Replace the wav header processing lines with a general function (update_wav_header()), which can be reused in other sections.
3. Add pthread_exit() for thread to exit safely in single line mode, and correct comment.

bat/alsa.c +31 -38
index 79c86fe..666bcf2 100644
@@ -465,12 +465,29 @@ static int read_from_pcm(struct pcm_container *sndpcm,
 	return 0;
 }
 
-static int read_from_pcm_loop(FILE *fp, int count,
-		struct pcm_container *sndpcm, struct bat *bat)
+static int read_from_pcm_loop(struct pcm_container *sndpcm, struct bat *bat)
 {
 	int err = 0;
+	FILE *fp = NULL;
 	int size, frames;
-	int remain = count;
+	int bytes_read = 0;
+	int bytes_count = bat->frames * bat->frame_size;
+	int remain = bytes_count;
+
+	remove(bat->capture.file);
+	fp = fopen(bat->capture.file, "wb");
+	err = -errno;
+	if (fp == NULL) {
+		fprintf(bat->err, _("Cannot open file: %s %d\n"),
+				bat->capture.file, err);
+		return err;
+	}
+	/* leave space for file header */
+	if (fseek(fp, sizeof(struct wav_container), SEEK_SET) != 0) {
+		err = -errno;
+		fclose(fp);
+		return err;
+	}
 
 	while (remain > 0) {
 		size = (remain <= sndpcm->period_bytes) ?
@@ -489,6 +506,8 @@ static int read_from_pcm_loop(FILE *fp, int count,
 					snd_strerror(err), err);
 			return -EIO;
 		}
+
+		bytes_read += size;
 		remain -= size;
 		bat->periods_played++;
 
@@ -497,6 +516,9 @@ static int read_from_pcm_loop(FILE *fp, int count,
 			break;
 	}
 
+	update_wav_header(bat, fp, bytes_read);
+
+	fclose(fp);
 	return 0;
 }
 
@@ -505,21 +527,13 @@ static void pcm_cleanup(void *p)
 	snd_pcm_close(p);
 }
 
-static void file_cleanup(void *p)
-{
-	fclose(p);
-}
-
 /**
  * Record
  */
 void *record_alsa(struct bat *bat)
 {
 	int err = 0;
-	FILE *fp = NULL;
 	struct pcm_container sndpcm;
-	struct wav_container wav;
-	int count;
 
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
 
@@ -543,48 +557,27 @@ void *record_alsa(struct bat *bat)
 		goto exit2;
 	}
 
-	remove(bat->capture.file);
-	fp = fopen(bat->capture.file, "wb");
-	err = -errno;
-	if (fp == NULL) {
-		fprintf(bat->err, _("Cannot open file: %s %d\n"),
-				bat->capture.file, err);
-		retval_record = err;
-		goto exit3;
-	}
-
-	prepare_wav_info(&wav, bat);
-
 	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
 	pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
 	pthread_cleanup_push(pcm_cleanup, sndpcm.handle);
 	pthread_cleanup_push(free, sndpcm.buffer);
-	pthread_cleanup_push(file_cleanup, fp);
 
-	err = write_wav_header(fp, &wav, bat);
-	if (err != 0) {
-		retval_record = err;
-		goto exit4;
-	}
-
-	count = wav.chunk.length;
 	fprintf(bat->log, _("Recording ...\n"));
-	err = read_from_pcm_loop(fp, count, &sndpcm, bat);
+	err = read_from_pcm_loop(&sndpcm, bat);
 	if (err != 0) {
 		retval_record = err;
-		goto exit4;
+		goto exit3;
 	}
 
-	/* Normally we will never reach this part of code (before fail_exit) as
-	   this thread will be cancelled by end of play thread. */
-	pthread_cleanup_pop(0);
+	/* Normally we will never reach this part of code (unless error in
+	 * previous call) (before exit3) as this thread will be cancelled
+	 * by end of play thread. Except in single line mode. */
 	pthread_cleanup_pop(0);
 	pthread_cleanup_pop(0);
 
 	snd_pcm_drain(sndpcm.handle);
+	pthread_exit(&retval_record);
 
-exit4:
-	fclose(fp);
 exit3:
 	free(sndpcm.buffer);
 exit2:
bat/common.c +16 -0
index 41aaf3a..e51bafd 100644
@@ -195,3 +195,19 @@ int write_wav_header(FILE *fp, struct wav_container *wav, struct bat *bat)
 
 	return 0;
 }
+
+/* update wav header when data size changed */
+int update_wav_header(struct bat *bat, FILE *fp, int bytes)
+{
+	int err = 0;
+	struct wav_container wav;
+
+	prepare_wav_info(&wav, bat);
+	wav.chunk.length = bytes;
+	wav.header.length = (wav.chunk.length) + sizeof(wav.chunk)
+		+ sizeof(wav.format) + sizeof(wav.header) - 8;
+	rewind(fp);
+	err = write_wav_header(fp, &wav, bat);
+
+	return err;
+}
bat/common.h +1 -0
index 30e39fc..d72a940 100644
@@ -183,3 +183,4 @@ struct analyze {
 void prepare_wav_info(struct wav_container *, struct bat *);
 int read_wav_header(struct bat *, char *, FILE *, bool);
 int write_wav_header(FILE *, struct wav_container *, struct bat *);
+int update_wav_header(struct bat *, FILE *, int);
Signature · 1 line
2.5.0
#2 lore raw

PATCH v2 2/6 alsabat: use general function for wav header update

In reply to [email protected]

From: "Lu, Han" <[email protected]>

In playback thread, use general function update_wav_header() to replace a bunch of code, so the structure is cleaner and no need to define variable "wav".

bat/alsa.c +3 -16
index 666bcf2..5acc2bc 100644
@@ -292,11 +292,10 @@ static int write_to_pcm(const struct pcm_container *sndpcm,
 
 static int write_to_pcm_loop(struct pcm_container *sndpcm, struct bat *bat)
 {
-	int err;
+	int err = 0;
 	int bytes = sndpcm->period_bytes; /* playback buffer size */
 	int frames = bytes * 8 / sndpcm->frame_bits; /* frame count */
 	FILE *fp = NULL;
-	struct wav_container wav;
 	int bytes_total = 0;
 
 	if (bat->debugplay) {
@@ -308,7 +307,7 @@ static int write_to_pcm_loop(struct pcm_container *sndpcm, struct bat *bat)
 			return err;
 		}
 		/* leave space for wav header */
-		if (fseek(fp, sizeof(wav), SEEK_SET) != 0) {
+		if (fseek(fp, sizeof(struct wav_container), SEEK_SET) != 0) {
 			err = -errno;
 			fclose(fp);
 			return err;
@@ -344,19 +343,7 @@ static int write_to_pcm_loop(struct pcm_container *sndpcm, struct bat *bat)
 	}
 
 	if (bat->debugplay) {
-		/* update wav header */
-		prepare_wav_info(&wav, bat);
-		wav.chunk.length = bytes_total;
-		wav.header.length = (wav.chunk.length) + sizeof(wav.chunk)
-			+ sizeof(wav.format) + sizeof(wav.header) - 8;
-
-		rewind(fp);
-		err = write_wav_header(fp, &wav, bat);
-		if (err != 0) {
-			fprintf(bat->err, _("Write file error: %s %s(%d)\n"),
-					bat->debugplay, snd_strerror(err), err);
-			return err;
-		}
+		update_wav_header(bat, fp, bytes_total);
 		fclose(fp);
 	}
 
Signature · 1 line
2.5.0
#3 lore raw

PATCH v2 3/6 alsabat: clean return value for playback and capture threads

In reply to [email protected]

From: "Lu, Han" <[email protected]>

Remove unnecessary prints in playback and capture threads, and replace the return value "0" with error code for convenience of maintaining.

bat/alsa.c +12 -19
index 5acc2bc..aae2eb0 100644
@@ -316,18 +316,13 @@ static int write_to_pcm_loop(struct pcm_container *sndpcm, struct bat *bat)
 
 	while (1) {
 		err = generate_input_data(sndpcm, bytes, bat);
-		if (err < 0)
-			return err;
-		else if (err > 0)
+		if (err != 0)
 			break;
 
 		if (bat->debugplay) {
-			err = fwrite(sndpcm->buffer, 1, bytes, fp);
-			if (err != bytes) {
-				fprintf(bat->err, _("Write file error: "));
-				fprintf(bat->err, _("%s(%d)\n"),
-						snd_strerror(err), err);
-				return -EIO;
+			if (fwrite(sndpcm->buffer, 1, bytes, fp) != bytes) {
+				err = -EIO;
+				break;
 			}
 			bytes_total += bytes;
 		}
@@ -339,7 +334,7 @@ static int write_to_pcm_loop(struct pcm_container *sndpcm, struct bat *bat)
 
 		err = write_to_pcm(sndpcm, frames, bat);
 		if (err != 0)
-			return err;
+			break;
 	}
 
 	if (bat->debugplay) {
@@ -349,7 +344,7 @@ static int write_to_pcm_loop(struct pcm_container *sndpcm, struct bat *bat)
 
 	snd_pcm_drain(sndpcm->handle);
 
-	return 0;
+	return err;
 }
 
 /**
@@ -405,7 +400,7 @@ void *playback_alsa(struct bat *bat)
 	}
 
 	err = write_to_pcm_loop(&sndpcm, bat);
-	if (err != 0) {
+	if (err < 0) {
 		retval_play = err;
 		goto exit4;
 	}
@@ -484,14 +479,12 @@ static int read_from_pcm_loop(struct pcm_container *sndpcm, struct bat *bat)
 		/* read a chunk from pcm device */
 		err = read_from_pcm(sndpcm, frames, bat);
 		if (err != 0)
-			return err;
+			break;
 
 		/* write the chunk to file */
-		err = fwrite(sndpcm->buffer, 1, size, fp);
-		if (err != size) {
-			fprintf(bat->err, _("Write file error: %s(%d)\n"),
-					snd_strerror(err), err);
-			return -EIO;
+		if (fwrite(sndpcm->buffer, 1, size, fp) != size) {
+			err = -EIO;
+			break;
 		}
 
 		bytes_read += size;
@@ -506,7 +499,7 @@ static int read_from_pcm_loop(struct pcm_container *sndpcm, struct bat *bat)
 	update_wav_header(bat, fp, bytes_read);
 
 	fclose(fp);
-	return 0;
+	return err;
 }
 
 static void pcm_cleanup(void *p)
Signature · 1 line
2.5.0
#4 lore raw

PATCH v2 4/6 alsabat: use general data generator function

In reply to [email protected]

From: "Lu, Han" <[email protected]>

Use general data generator to replace local function, so other modules can reuse the data generator rather than re-implement it.

bat/alsa.c +1 -56
index aae2eb0..94f47f4 100644
@@ -16,7 +16,6 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdbool.h>
-#include <math.h>
 #include <stdint.h>
 #include <pthread.h>
 #include <errno.h>
@@ -28,7 +27,6 @@
 
 #include "common.h"
 #include "alsa.h"
-#include "bat-signal.h"
 
 struct pcm_container {
 	snd_pcm_t *handle;
@@ -206,59 +204,6 @@ static int set_snd_pcm_params(struct bat *bat, struct pcm_container *sndpcm)
 	return 0;
 }
 
-/*
- * Generate buffer to be played either from input file or from generated data
- * Return value
- * <0 error
- * 0 ok
- * >0 break
- */
-static int generate_input_data(struct pcm_container *sndpcm, int bytes,
-		struct bat *bat)
-{
-	int err;
-	static int load;
-	int frames = bytes * 8 / sndpcm->frame_bits;
-
-	if (bat->playback.file != NULL) {
-		/* From input file */
-		load = 0;
-
-		while (1) {
-			err = fread(sndpcm->buffer + load, 1,
-					bytes - load, bat->fp);
-			if (0 == err) {
-				if (feof(bat->fp)) {
-					fprintf(bat->log,
-							_("End of playing.\n"));
-					return 1;
-				}
-			} else if (err < bytes - load) {
-				if (ferror(bat->fp)) {
-					fprintf(bat->err, _("Read file error"));
-					fprintf(bat->err, _(": %d\n"), err);
-					return -EIO;
-				}
-				load += err;
-			} else {
-				break;
-			}
-		}
-	} else {
-		/* Generate sine wave */
-		if ((bat->sinus_duration) && (load > bat->sinus_duration))
-			return 1;
-
-		err = generate_sine_wave(bat, frames, (void *)sndpcm->buffer);
-		if (err != 0)
-			return err;
-
-		load += frames;
-	}
-
-	return 0;
-}
-
 static int write_to_pcm(const struct pcm_container *sndpcm,
 		int frames, struct bat *bat)
 {
@@ -315,7 +260,7 @@ static int write_to_pcm_loop(struct pcm_container *sndpcm, struct bat *bat)
 	}
 
 	while (1) {
-		err = generate_input_data(sndpcm, bytes, bat);
+		err = generate_input_data(bat, sndpcm->buffer, bytes, frames);
 		if (err != 0)
 			break;
 
bat/common.c +51 -0

60 lines not on this page · raw message

bat/common.h +1 -0
index d72a940..37d1e4b 100644
@@ -184,3 +184,4 @@ void prepare_wav_info(struct wav_container *, struct bat *);
 int read_wav_header(struct bat *, char *, FILE *, bool);
 int write_wav_header(FILE *, struct wav_container *, struct bat *);
 int update_wav_header(struct bat *, FILE *, int);
+int generate_input_data(struct bat *, void *, int, int);
Signature · 1 line
2.5.0
#5 lore raw

PATCH v2 5/6 alsabat: move alsa process to a single block

In reply to [email protected]

From: "Lu, Han" <[email protected]>

Move all alsa callings to a single block (alsa.c), so other blocks such as the main structure, the signal process and the data analysis modules will be independent to alsa, and new modules such as a tinyalsa interface can be easily embedded into alsabat.

bat/alsa.c +37 -4
index 94f47f4..75158cb 100644
@@ -40,15 +40,49 @@ struct pcm_container {
 	char *buffer;
 };
 
+struct format_map_table {
+	enum _bat_pcm_format format_bat;
+	snd_pcm_format_t format_alsa;
+};
+
+static struct format_map_table map_tables[] = {
+	{ BAT_PCM_FORMAT_UNKNOWN, SND_PCM_FORMAT_UNKNOWN },
+	{ BAT_PCM_FORMAT_U8, SND_PCM_FORMAT_U8 },
+	{ BAT_PCM_FORMAT_S16_LE, SND_PCM_FORMAT_S16_LE },
+	{ BAT_PCM_FORMAT_S24_3LE, SND_PCM_FORMAT_S24_3LE },
+	{ BAT_PCM_FORMAT_S32_LE, SND_PCM_FORMAT_S32_LE },
+	{ BAT_PCM_FORMAT_MAX, },
+};
+
+static int format_convert(struct bat *bat, snd_pcm_format_t *fmt)
+{
+	struct format_map_table *t = map_tables;
+
+	for (; t->format_bat != BAT_PCM_FORMAT_MAX; t++) {
+		if (t->format_bat == bat->format) {
+			*fmt = t->format_alsa;
+			return 0;
+		}
+	}
+	fprintf(bat->err, _("Invalid format!\n"));
+	return -EINVAL;
+}
+
 static int set_snd_pcm_params(struct bat *bat, struct pcm_container *sndpcm)
 {
 	snd_pcm_hw_params_t *params;
+	snd_pcm_format_t format;
 	unsigned int buffer_time = 0;
 	unsigned int period_time = 0;
 	unsigned int rate;
 	int err;
 	const char *device_name = snd_pcm_name(sndpcm->handle);
 
+	/* Convert common format to ALSA format */
+	err = format_convert(bat, &format);
+	if (err != 0)
+		return err;
+
 	/* Allocate a hardware parameters object. */
 	snd_pcm_hw_params_alloca(&params);
 
@@ -72,11 +106,10 @@ static int set_snd_pcm_params(struct bat *bat, struct pcm_container *sndpcm)
 	}
 
 	/* Set format */
-	err = snd_pcm_hw_params_set_format(sndpcm->handle, params, bat->format);
+	err = snd_pcm_hw_params_set_format(sndpcm->handle, params, format);
 	if (err < 0) {
 		fprintf(bat->err, _("Set parameter to device error: "));
-		fprintf(bat->err, _("PCM format: %d %s: %s(%d)\n"),
-				bat->format,
+		fprintf(bat->err, _("PCM format: %d %s: %s(%d)\n"), format,
 				device_name, snd_strerror(err), err);
 		return err;
 	}
@@ -181,7 +214,7 @@ static int set_snd_pcm_params(struct bat *bat, struct pcm_container *sndpcm)
 		return -EINVAL;
 	}
 
-	err = snd_pcm_format_physical_width(bat->format);
+	err = snd_pcm_format_physical_width(format);
 	if (err < 0) {
 		fprintf(bat->err, _("Invalid parameters: "));
 		fprintf(bat->err, _("snd_pcm_format_physical_width: %d\n"),
bat/bat.c +18 -28

73 lines not on this page · raw message

bat/common.c +1 -0
index 11a7e4e..d3d1f28 100644
@@ -17,6 +17,7 @@
 #include <stddef.h>
 #include <stdlib.h>
 #include <stdbool.h>
+#include <errno.h>
 
 #include "aconfig.h"
 #include "gettext.h"
bat/common.h +10 -3
index 37d1e4b..ed33d51 100644
@@ -13,8 +13,6 @@
  *
  */
 
-#include <alsa/asoundlib.h>
-
 #define TEMP_RECORD_FILE_NAME		"/tmp/bat.wav.XXXXXX"
 #define DEFAULT_DEV_NAME		"default"
 
@@ -110,6 +108,15 @@ struct wav_container {
 
 struct bat;
 
+enum _bat_pcm_format {
+	BAT_PCM_FORMAT_UNKNOWN = -1,
+	BAT_PCM_FORMAT_S16_LE = 0,
+	BAT_PCM_FORMAT_S32_LE,
+	BAT_PCM_FORMAT_U8,
+	BAT_PCM_FORMAT_S24_3LE,
+	BAT_PCM_FORMAT_MAX
+};
+
 enum _bat_op_mode {
 	MODE_UNKNOWN = -1,
 	MODE_SINGLE = 0,
@@ -142,7 +149,7 @@ struct bat {
 	int frames;			/* nb of frames */
 	int frame_size;			/* size of frame */
 	int sample_size;		/* size of sample */
-	snd_pcm_format_t format;	/* PCM format */
+	enum _bat_pcm_format format;	/* PCM format */
 
 	float sigma_k;			/* threshold for peak detection */
 	float target_freq[MAX_CHANNELS];
bat/signal.c +7 -6
index 8026a35..a47ba97 100644
@@ -23,9 +23,11 @@
 #include <stdio.h>
 #include <stddef.h>
 #include <stdlib.h>
+#include <string.h>
 #include <math.h>
 #include <stdint.h>
 #include <stdbool.h>
+#include <errno.h>
 
 #include "gettext.h"
 #include "common.h"
@@ -113,22 +115,21 @@ static int adjust_waveform(struct bat *bat, float *val, int frames)
 	float factor, offset = 0.0;
 
 	switch (bat->format) {
-	case SND_PCM_FORMAT_U8:
+	case BAT_PCM_FORMAT_U8:
 		max = INT8_MAX;
 		offset = max;	/* shift for unsigned format */
 		break;
-	case SND_PCM_FORMAT_S16_LE:
+	case BAT_PCM_FORMAT_S16_LE:
 		max  = INT16_MAX;
 		break;
-	case SND_PCM_FORMAT_S24_3LE:
+	case BAT_PCM_FORMAT_S24_3LE:
 		max = (1 << 23) - 1;
 		break;
-	case SND_PCM_FORMAT_S32_LE:
+	case BAT_PCM_FORMAT_S32_LE:
 		max = INT32_MAX;
 		break;
 	default:
-		fprintf(bat->err, _("Invalid PCM format: %s\n"),
-				snd_pcm_format_name(bat->format));
+		fprintf(bat->err, _("Invalid PCM format: %d\n"), bat->format);
 		return -EINVAL;
 	}
 
Signature · 1 line
2.5.0
#6 lore raw

PATCH v2 6/6 alsabat: add tinyalsa support

In reply to [email protected]

From: "Lu, Han" <[email protected]>

Use "configure --enable-tinyalsa" for alsabat to use tinyalsa instead of ALSA.
On a system that has both ALSA and tinyalsa libraries installed, User can choose either library through configure option. By default alsabat will use ALSA library.
The intention is for alsabat to run on tinyalsa platforms such as Android or some Internet of Things(IoT) devices.

bat/Makefile.am +9 -3
index 712f5bf..24e3eb8 100644
@@ -7,13 +7,11 @@ alsabat_SOURCES = \
 	bat.c \
 	common.c \
 	signal.c \
-	convert.c \
-	alsa.c
+	convert.c
 
 noinst_HEADERS = \
 	common.h \
 	bat-signal.h \
-	alsa.h \
 	convert.h
 
 if HAVE_LIBFFTW3
@@ -21,6 +19,14 @@ alsabat_SOURCES += analyze.c
 noinst_HEADERS += analyze.h
 endif
 
+if HAVE_LIBTINYALSA
+alsabat_SOURCES += tinyalsa.c
+noinst_HEADERS += tinyalsa.h
+else
+alsabat_SOURCES += alsa.c
+noinst_HEADERS += alsa.h
+endif
+
 AM_CPPFLAGS = \
 	      -Wall -I$(top_srcdir)/include
 
bat/alsabat.1 +3 -0
index 5f41669..9b969c2 100644
@@ -33,6 +33,9 @@ analog loopback :-
 
 https://source.android.com/devices/audio/loopback.html
 
+If tinyalsa lib is installed in system, ALSABAT will use tinyalsa lib instead
+of ALSA lib.
+
 .SH OPTIONS
 .TP
 \fI\-h, \-\-help\fP
bat/bat.c +11 -1
index f10c647..e824065 100644
@@ -31,7 +31,11 @@
 
 #include "common.h"
 
+#ifdef HAVE_LIBTINYALSA
+#include "tinyalsa.h"
+#else
 #include "alsa.h"
+#endif
 #include "convert.h"
 #ifdef HAVE_LIBFFTW3
 #include "analyze.h"
@@ -301,7 +305,6 @@ static void set_defaults(struct bat *bat)
 
 	/* Set default values */
 	bat->rate = 44100;
-	bat->channels = 1;
 	bat->frame_size = 2;
 	bat->sample_size = 2;
 	bat->format = BAT_PCM_FORMAT_S16_LE;
@@ -315,8 +318,15 @@ static void set_defaults(struct bat *bat)
 	bat->capture.device = NULL;
 	bat->buf = NULL;
 	bat->local = false;
+#ifdef HAVE_LIBTINYALSA
+	bat->channels = 2;
+	bat->playback.fct = &playback_tinyalsa;
+	bat->capture.fct = &record_tinyalsa;
+#else
+	bat->channels = 1;
 	bat->playback.fct = &playback_alsa;
 	bat->capture.fct = &record_alsa;
+#endif
 	bat->playback.mode = MODE_LOOPBACK;
 	bat->capture.mode = MODE_LOOPBACK;
 	bat->period_is_limited = false;
bat/common.h +2 -0
index ed33d51..b789af5 100644
@@ -125,6 +125,8 @@ enum _bat_op_mode {
 };
 
 struct pcm {
+	unsigned int card_tiny;
+	unsigned int device_tiny;
 	char *device;
 	char *file;
 	enum _bat_op_mode mode;
bat/tinyalsa.c new file +460 -0

460 lines not on this page · raw message

bat/tinyalsa.h new file +20 -0
new file mode 100644
index 0000000..60f78f7
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2013-2015 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+extern int retval_play;
+extern int retval_record;
+
+void *playback_tinyalsa(struct bat *);
+void *record_tinyalsa(struct bat *);
configure.ac +17 -0
index d712872..bd39c6f 100644
@@ -58,6 +58,16 @@ AM_CONDITIONAL(HAVE_UCM, test "$have_ucm" = "yes")
 AM_CONDITIONAL(HAVE_TOPOLOGY, test "$have_topology" = "yes")
 AM_CONDITIONAL(HAVE_SAMPLERATE, test "$have_samplerate" = "yes")
 
+dnl Use tinyalsa
+tinyalsa=
+AC_ARG_ENABLE(tinyalsa,
+    AS_HELP_STRING([--disable-tinyalsa], [Use tinyalsa instead of ALSA]),
+    [case "${enableval}" in
+      yes) tinyalsa=true ;;
+      no) tinyalsa=false ;;
+      *) AC_MSG_ERROR(bad value ${enableval} for --enable-tinyalsa) ;;
+    esac],[tinyalsa=false])
+
 dnl Disable bat
 bat=
 if test "$have_pcm" = "yes"; then
@@ -82,6 +92,12 @@ if test x$bat = xtrue; then
   dnl Check for libfftw3
   have_libfftw3="yes"
   AC_CHECK_LIB([fftw3], [fftw_malloc], , [have_libfftw3="no"])
+  dnl Check for libtinyalsa
+  have_libtinyalsa=
+  if test x$tinyalsa = xtrue; then
+    have_libtinyalsa="yes"
+    AC_CHECK_LIB([tinyalsa], [pcm_open], , [have_libtinyalsa="no"])
+  fi
   AC_CHECK_LIB([m], [sqrtf], , [AC_MSG_ERROR([Error: Need sqrtf])])
   AC_CHECK_LIB([pthread], [pthread_create], , [AC_MSG_ERROR([Error: need PTHREAD library])])
   FFTW_CFLAGS="$CFLAGS"
@@ -95,6 +111,7 @@ if test x$bat = xtrue; then
 
 fi
 AM_CONDITIONAL(HAVE_LIBFFTW3, test "$have_libfftw3" = "yes")
+AM_CONDITIONAL(HAVE_LIBTINYALSA, test "$have_libtinyalsa" = "yes")
 
 dnl Check for librt
 LIBRT=""
Signature · 1 line
2.5.0
#7 lore raw

Re: [PATCH V2 6/6] alsabat: add tinyalsa support

bat/alsabat.1 analog loopback :- · line 38

Quoted 12 lines · On Tue, 22 Mar 2016 15:31:38 +0100, [email protected] wrote:
bat/alsabat.1 +3 -0
index 5f41669..9b969c2 100644
@@ -33,6 +33,9 @@ analog loopback :-
 
 https://source.android.com/devices/audio/loopback.html
 
+If tinyalsa lib is installed in system, ALSABAT will use tinyalsa lib instead
+of ALSA lib.
+

This text doesn't match with the behavior of your latest version. Forgot to update?

Quoted 7 lines
configure.ac +0 -0
index d712872..bd39c6f 100644
@@ -58,6 +58,16 @@ AM_CONDITIONAL(HAVE_UCM, test "$have_ucm" = "yes")
 AM_CONDITIONAL(HAVE_TOPOLOGY, test "$have_topology" = "yes")
 AM_CONDITIONAL(HAVE_SAMPLERATE, test "$have_samplerate" = "yes")

configure.ac AM_CONDITIONAL(HAVE_UCM, test "$have_ucm" = "yes") · line 69

Quoted 10 lines
configure.ac +9 -0
 
+dnl Use tinyalsa
+tinyalsa=
+AC_ARG_ENABLE(tinyalsa,
+    AS_HELP_STRING([--disable-tinyalsa], [Use tinyalsa instead of ALSA]),
+    [case "${enableval}" in
+      yes) tinyalsa=true ;;
+      no) tinyalsa=false ;;
+      *) AC_MSG_ERROR(bad value ${enableval} for --enable-tinyalsa) ;;
+    esac],[tinyalsa=false])

This doesn't look consistent. The default is false while the description shows --disable-tinyalsa.

thanks,

Takashi