mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-11-08 20:05:42 +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;
|
||||
}
|
||||
|
||||
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:
|
||||
|
|
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;
|
||||
}
|
||||
|
||||
/* 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 *);
|
||||
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);
|
||||
|
|
Loading…
Reference in a new issue