mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-12-22 23:46:31 +01:00
alsabat: refactoring alsa capture thread
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. Signed-off-by: Lu, Han <han.lu@intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
c5b022e621
commit
241d7fc1bb
3 changed files with 48 additions and 38 deletions
69
bat/alsa.c
69
bat/alsa.c
|
@ -465,12 +465,29 @@ static int read_from_pcm(struct pcm_container *sndpcm,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_from_pcm_loop(FILE *fp, int count,
|
static int read_from_pcm_loop(struct pcm_container *sndpcm, struct bat *bat)
|
||||||
struct pcm_container *sndpcm, struct bat *bat)
|
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
FILE *fp = NULL;
|
||||||
int size, frames;
|
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) {
|
while (remain > 0) {
|
||||||
size = (remain <= sndpcm->period_bytes) ?
|
size = (remain <= sndpcm->period_bytes) ?
|
||||||
|
@ -489,6 +506,8 @@ static int read_from_pcm_loop(FILE *fp, int count,
|
||||||
snd_strerror(err), err);
|
snd_strerror(err), err);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bytes_read += size;
|
||||||
remain -= size;
|
remain -= size;
|
||||||
bat->periods_played++;
|
bat->periods_played++;
|
||||||
|
|
||||||
|
@ -497,6 +516,9 @@ static int read_from_pcm_loop(FILE *fp, int count,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_wav_header(bat, fp, bytes_read);
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,21 +527,13 @@ static void pcm_cleanup(void *p)
|
||||||
snd_pcm_close(p);
|
snd_pcm_close(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void file_cleanup(void *p)
|
|
||||||
{
|
|
||||||
fclose(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Record
|
* Record
|
||||||
*/
|
*/
|
||||||
void *record_alsa(struct bat *bat)
|
void *record_alsa(struct bat *bat)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
FILE *fp = NULL;
|
|
||||||
struct pcm_container sndpcm;
|
struct pcm_container sndpcm;
|
||||||
struct wav_container wav;
|
|
||||||
int count;
|
|
||||||
|
|
||||||
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
||||||
|
|
||||||
|
@ -543,48 +557,27 @@ void *record_alsa(struct bat *bat)
|
||||||
goto exit2;
|
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_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
|
||||||
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
|
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
|
||||||
pthread_cleanup_push(pcm_cleanup, sndpcm.handle);
|
pthread_cleanup_push(pcm_cleanup, sndpcm.handle);
|
||||||
pthread_cleanup_push(free, sndpcm.buffer);
|
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"));
|
fprintf(bat->log, _("Recording ...\n"));
|
||||||
err = read_from_pcm_loop(fp, count, &sndpcm, bat);
|
err = read_from_pcm_loop(&sndpcm, bat);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
retval_record = err;
|
retval_record = err;
|
||||||
goto exit4;
|
goto exit3;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Normally we will never reach this part of code (before fail_exit) as
|
/* Normally we will never reach this part of code (unless error in
|
||||||
this thread will be cancelled by end of play thread. */
|
* previous call) (before exit3) as this thread will be cancelled
|
||||||
pthread_cleanup_pop(0);
|
* by end of play thread. Except in single line mode. */
|
||||||
pthread_cleanup_pop(0);
|
pthread_cleanup_pop(0);
|
||||||
pthread_cleanup_pop(0);
|
pthread_cleanup_pop(0);
|
||||||
|
|
||||||
snd_pcm_drain(sndpcm.handle);
|
snd_pcm_drain(sndpcm.handle);
|
||||||
|
pthread_exit(&retval_record);
|
||||||
|
|
||||||
exit4:
|
|
||||||
fclose(fp);
|
|
||||||
exit3:
|
exit3:
|
||||||
free(sndpcm.buffer);
|
free(sndpcm.buffer);
|
||||||
exit2:
|
exit2:
|
||||||
|
|
16
bat/common.c
16
bat/common.c
|
@ -195,3 +195,19 @@ int write_wav_header(FILE *fp, struct wav_container *wav, struct bat *bat)
|
||||||
|
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -183,3 +183,4 @@ struct analyze {
|
||||||
void prepare_wav_info(struct wav_container *, struct bat *);
|
void prepare_wav_info(struct wav_container *, struct bat *);
|
||||||
int read_wav_header(struct bat *, char *, FILE *, bool);
|
int read_wav_header(struct bat *, char *, FILE *, bool);
|
||||||
int write_wav_header(FILE *, struct wav_container *, struct bat *);
|
int write_wav_header(FILE *, struct wav_container *, struct bat *);
|
||||||
|
int update_wav_header(struct bat *, FILE *, int);
|
||||||
|
|
Loading…
Reference in a new issue