]> git.alsa-project.org Git - alsa-utils.git/commitdiff
alsaloop: Delay the restart a bit (to handle snd-aloop playback xruns better)
authorJaroslav Kysela <perex@perex.cz>
Wed, 20 Oct 2010 07:26:24 +0000 (09:26 +0200)
committerJaroslav Kysela <perex@perex.cz>
Wed, 20 Oct 2010 07:31:01 +0000 (09:31 +0200)
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
alsaloop/alsaloop.h
alsaloop/pcmjob.c

index e506427e9112dc295c72e16e97716e76e3523adb..8dc445ae2fc69315d7f8f29d9ef9682756a6b7a1 100644 (file)
@@ -143,6 +143,8 @@ struct loopback {
        unsigned int linked:1;          /* linked streams */
        unsigned int reinit:1;
        unsigned int running:1;
+       unsigned int stop_pending:1;
+       snd_pcm_uframes_t stop_count;
        sync_type_t sync;               /* type of sync */
        slave_type_t slave;
        int thread;                     /* thread number */
index 925380c086c9c169585bcda2b7527f17afb97e7a..23270a0331a64a7d37924b4a6680af9f1c5f0a59 100644 (file)
@@ -738,6 +738,15 @@ static int writeit(struct loopback_handle *lhandle)
                lhandle->buf_pos += r;
                lhandle->buf_pos %= lhandle->buf_size;
                xrun_profile(lhandle->loopback);
+               if (lhandle->loopback->stop_pending) {
+                       lhandle->loopback->stop_count += r;
+                       if (lhandle->loopback->stop_count * lhandle->pitch >
+                           lhandle->loopback->latency * 3) {
+                               lhandle->loopback->stop_pending = 0;
+                               lhandle->loopback->reinit = 1;
+                               break;
+                       }
+               }
        }
        return res;
 }
@@ -1521,6 +1530,7 @@ int pcmjob_start(struct loopback *loop)
                goto __error;
        }
        loop->running = 1;
+       loop->stop_pending = 0;
        if (loop->xrun) {
                getcurtimestamp(&loop->xrun_last_update);
                loop->xrun_last_pdelay = XRUN_PROFILE_UNKNOWN;
@@ -1638,6 +1648,7 @@ static int ctl_event_check(snd_ctl_elem_value_t *val, snd_ctl_event_t *ev)
 static int handle_ctl_events(struct loopback_handle *lhandle,
                             unsigned short events)
 {
+       struct loopback *loop = lhandle->loopback;
        snd_ctl_event_t *ev;
        int err;
 
@@ -1647,16 +1658,24 @@ static int handle_ctl_events(struct loopback_handle *lhandle,
                        break;
                if (snd_ctl_event_get_type(ev) != SND_CTL_EVENT_ELEM)
                        continue;
-               if (lhandle == lhandle->loopback->play)
+               if (lhandle == loop->play)
                        goto __ctl_check;
                if (verbose > 6)
-                       snd_output_printf(lhandle->loopback->output, "%s: ctl event!!!! %s\n", lhandle->id, snd_ctl_event_elem_get_name(ev));
+                       snd_output_printf(loop->output, "%s: ctl event!!!! %s\n", lhandle->id, snd_ctl_event_elem_get_name(ev));
                if (ctl_event_check(lhandle->ctl_active, ev)) {
                        err = get_active(lhandle);
                        if (verbose > 7)
-                               snd_output_printf(lhandle->loopback->output, "%s: ctl event active %i\n", lhandle->id, err);
-                       if (err != lhandle->loopback->running)
-                               goto __restart;
+                               snd_output_printf(loop->output, "%s: ctl event active %i\n", lhandle->id, err);
+                       if (!err) {
+                               if (lhandle->loopback->running) {
+                                       loop->stop_pending = 1;
+                                       loop->stop_count = 0;
+                               }
+                       } else {
+                               loop->stop_pending = 0;
+                               if (loop->running == 0)
+                                       goto __restart;
+                       }
                } else if (ctl_event_check(lhandle->ctl_format, ev)) {
                        err = get_format(lhandle);
                        if (lhandle->format != err)
@@ -1676,8 +1695,8 @@ static int handle_ctl_events(struct loopback_handle *lhandle,
        return 0;
 
       __restart:
-       pcmjob_stop(lhandle->loopback);
-       err = pcmjob_start(lhandle->loopback);
+       pcmjob_stop(loop);
+       err = pcmjob_start(loop);
        if (err < 0)
                return err;
        return 1;