ALSA: pcm: Use a common helper for PCM state check and hwsync
authorTakashi Iwai <tiwai@suse.de>
Fri, 19 May 2017 18:04:23 +0000 (20:04 +0200)
committerTakashi Iwai <tiwai@suse.de>
Sun, 21 May 2017 06:57:31 +0000 (08:57 +0200)
The mostly same codes for checking the current PCM state and calling
hwsync are found in a few places.  This patch simplifies them by
creating a common helper function.

It also fixes a couple of cases where we missed the proper state check
(e.g. PAUSED state wasn't handled in rewind and snd_pcm_hwsync()),
too.

Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/core/pcm_native.c

index f3a3580eb44caa0402069d1f54f0e4637edb742e..93bd2c662c1df0928ee38ef1c55ec0221076cde6 100644 (file)
@@ -2431,6 +2431,30 @@ static int snd_pcm_release(struct inode *inode, struct file *file)
        return 0;
 }
 
+/* check and update PCM state; return 0 or a negative error
+ * call this inside PCM lock
+ */
+static int do_pcm_hwsync(struct snd_pcm_substream *substream)
+{
+       switch (substream->runtime->status->state) {
+       case SNDRV_PCM_STATE_DRAINING:
+               if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+                       return -EBADFD;
+               /* Fall through */
+       case SNDRV_PCM_STATE_RUNNING:
+               return snd_pcm_update_hw_ptr(substream);
+       case SNDRV_PCM_STATE_PREPARED:
+       case SNDRV_PCM_STATE_PAUSED:
+               return 0;
+       case SNDRV_PCM_STATE_SUSPENDED:
+               return -ESTRPIPE;
+       case SNDRV_PCM_STATE_XRUN:
+               return -EPIPE;
+       default:
+               return -EBADFD;
+       }
+}
+
 static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream,
                                                 snd_pcm_uframes_t frames)
 {
@@ -2443,25 +2467,9 @@ static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *subst
                return 0;
 
        snd_pcm_stream_lock_irq(substream);
-       switch (runtime->status->state) {
-       case SNDRV_PCM_STATE_PREPARED:
-               break;
-       case SNDRV_PCM_STATE_DRAINING:
-       case SNDRV_PCM_STATE_RUNNING:
-               if (snd_pcm_update_hw_ptr(substream) >= 0)
-                       break;
-               /* Fall through */
-       case SNDRV_PCM_STATE_XRUN:
-               ret = -EPIPE;
-               goto __end;
-       case SNDRV_PCM_STATE_SUSPENDED:
-               ret = -ESTRPIPE;
-               goto __end;
-       default:
-               ret = -EBADFD;
+       ret = do_pcm_hwsync(substream);
+       if (ret < 0)
                goto __end;
-       }
-
        hw_avail = snd_pcm_playback_hw_avail(runtime);
        if (hw_avail <= 0) {
                ret = 0;
@@ -2491,25 +2499,9 @@ static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substr
                return 0;
 
        snd_pcm_stream_lock_irq(substream);
-       switch (runtime->status->state) {
-       case SNDRV_PCM_STATE_PREPARED:
-       case SNDRV_PCM_STATE_DRAINING:
-               break;
-       case SNDRV_PCM_STATE_RUNNING:
-               if (snd_pcm_update_hw_ptr(substream) >= 0)
-                       break;
-               /* Fall through */
-       case SNDRV_PCM_STATE_XRUN:
-               ret = -EPIPE;
+       ret = do_pcm_hwsync(substream);
+       if (ret < 0)
                goto __end;
-       case SNDRV_PCM_STATE_SUSPENDED:
-               ret = -ESTRPIPE;
-               goto __end;
-       default:
-               ret = -EBADFD;
-               goto __end;
-       }
-
        hw_avail = snd_pcm_capture_hw_avail(runtime);
        if (hw_avail <= 0) {
                ret = 0;
@@ -2539,26 +2531,9 @@ static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *subs
                return 0;
 
        snd_pcm_stream_lock_irq(substream);
-       switch (runtime->status->state) {
-       case SNDRV_PCM_STATE_PREPARED:
-       case SNDRV_PCM_STATE_PAUSED:
-               break;
-       case SNDRV_PCM_STATE_DRAINING:
-       case SNDRV_PCM_STATE_RUNNING:
-               if (snd_pcm_update_hw_ptr(substream) >= 0)
-                       break;
-               /* Fall through */
-       case SNDRV_PCM_STATE_XRUN:
-               ret = -EPIPE;
-               goto __end;
-       case SNDRV_PCM_STATE_SUSPENDED:
-               ret = -ESTRPIPE;
+       ret = do_pcm_hwsync(substream);
+       if (ret < 0)
                goto __end;
-       default:
-               ret = -EBADFD;
-               goto __end;
-       }
-
        avail = snd_pcm_playback_avail(runtime);
        if (avail <= 0) {
                ret = 0;
@@ -2588,26 +2563,9 @@ static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *subst
                return 0;
 
        snd_pcm_stream_lock_irq(substream);
-       switch (runtime->status->state) {
-       case SNDRV_PCM_STATE_PREPARED:
-       case SNDRV_PCM_STATE_DRAINING:
-       case SNDRV_PCM_STATE_PAUSED:
-               break;
-       case SNDRV_PCM_STATE_RUNNING:
-               if (snd_pcm_update_hw_ptr(substream) >= 0)
-                       break;
-               /* Fall through */
-       case SNDRV_PCM_STATE_XRUN:
-               ret = -EPIPE;
-               goto __end;
-       case SNDRV_PCM_STATE_SUSPENDED:
-               ret = -ESTRPIPE;
+       ret = do_pcm_hwsync(substream);
+       if (ret < 0)
                goto __end;
-       default:
-               ret = -EBADFD;
-               goto __end;
-       }
-
        avail = snd_pcm_capture_avail(runtime);
        if (avail <= 0) {
                ret = 0;
@@ -2627,33 +2585,10 @@ static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *subst
 
 static int snd_pcm_hwsync(struct snd_pcm_substream *substream)
 {
-       struct snd_pcm_runtime *runtime = substream->runtime;
        int err;
 
        snd_pcm_stream_lock_irq(substream);
-       switch (runtime->status->state) {
-       case SNDRV_PCM_STATE_DRAINING:
-               if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
-                       goto __badfd;
-               /* Fall through */
-       case SNDRV_PCM_STATE_RUNNING:
-               if ((err = snd_pcm_update_hw_ptr(substream)) < 0)
-                       break;
-               /* Fall through */
-       case SNDRV_PCM_STATE_PREPARED:
-               err = 0;
-               break;
-       case SNDRV_PCM_STATE_SUSPENDED:
-               err = -ESTRPIPE;
-               break;
-       case SNDRV_PCM_STATE_XRUN:
-               err = -EPIPE;
-               break;
-       default:
-             __badfd:
-               err = -EBADFD;
-               break;
-       }
+       err = do_pcm_hwsync(substream);
        snd_pcm_stream_unlock_irq(substream);
        return err;
 }
@@ -2666,31 +2601,13 @@ static int snd_pcm_delay(struct snd_pcm_substream *substream,
        snd_pcm_sframes_t n = 0;
 
        snd_pcm_stream_lock_irq(substream);
-       switch (runtime->status->state) {
-       case SNDRV_PCM_STATE_DRAINING:
-               if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
-                       goto __badfd;
-               /* Fall through */
-       case SNDRV_PCM_STATE_RUNNING:
-               if ((err = snd_pcm_update_hw_ptr(substream)) < 0)
-                       break;
-               /* Fall through */
-       case SNDRV_PCM_STATE_PREPARED:
-       case SNDRV_PCM_STATE_SUSPENDED:
-               err = 0;
+       err = do_pcm_hwsync(substream);
+       if (!err) {
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                        n = snd_pcm_playback_hw_avail(runtime);
                else
                        n = snd_pcm_capture_avail(runtime);
                n += runtime->delay;
-               break;
-       case SNDRV_PCM_STATE_XRUN:
-               err = -EPIPE;
-               break;
-       default:
-             __badfd:
-               err = -EBADFD;
-               break;
        }
        snd_pcm_stream_unlock_irq(substream);
        if (!err)