]> git.alsa-project.org Git - alsa-utils.git/commitdiff
alsabat: refactoring alsa capture thread
authorLu, Han <han.lu@intel.com>
Wed, 23 Mar 2016 07:52:42 +0000 (15:52 +0800)
committerTakashi Iwai <tiwai@suse.de>
Wed, 23 Mar 2016 16:51:21 +0000 (17:51 +0100)
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>
bat/alsa.c
bat/common.c
bat/common.h

index 79c86fe62b11c4756e59f59c81c60031854aa133..666bcf2f2eac7ba5d52641ec7251e86eec879165 100644 (file)
@@ -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:
index 41aaf3abde57d6cf957d841124c23f5a6c0967e5..e51bafd8949e257c41942a29724068c5349374a0 100644 (file)
@@ -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;
+}
index 30e39fcfeb5e32acf9a6e4d65c1222c76a7da83c..d72a94039250e7ce4f35263bf492e3b956873a8a 100644 (file)
@@ -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);