diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/modules/alsa-util.c | 33 | ||||
| -rw-r--r-- | src/modules/alsa-util.h | 1 | ||||
| -rw-r--r-- | src/modules/module-alsa-sink.c | 58 | ||||
| -rw-r--r-- | src/modules/module-alsa-source.c | 48 | 
4 files changed, 91 insertions, 49 deletions
diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index dd9ac79e..dd063f3b 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -289,10 +289,11 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p      pa_assert(periods);      pa_assert(period_size); +    snd_pcm_hw_params_alloca(&hwparams); +          buffer_size = *periods * *period_size; -    if ((ret = snd_pcm_hw_params_malloc(&hwparams)) < 0 || -        (ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0 || +    if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0 ||          (ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0)          goto finish; @@ -355,12 +356,36 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p      ret = 0;  finish: -    if (hwparams) -        snd_pcm_hw_params_free(hwparams);      return ret;  } +int pa_alsa_set_sw_params(snd_pcm_t *pcm) { +    snd_pcm_sw_params_t *swparams; +    int err; +     +    pa_assert(pcm); + +    snd_pcm_sw_params_alloca(&swparams); + +    if ((err = snd_pcm_sw_params_current(pcm, swparams) < 0)) { +        pa_log_warn("Unable to determine current swparams: %s\n", snd_strerror(err)); +        return err; +    } + +    if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, (snd_pcm_uframes_t) -1)) < 0) { +        pa_log_warn("Unable to set stop threshold: %s\n", snd_strerror(err)); +        return err; +    } +     +    if ((err = snd_pcm_sw_params(pcm, swparams)) < 0) { +        pa_log_warn("Unable to set sw params: %s\n", snd_strerror(err)); +        return err; +    } + +    return 0; +} +  int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev) {      int err; diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h index f79325c6..6f1f927e 100644 --- a/src/modules/alsa-util.h +++ b/src/modules/alsa-util.h @@ -39,6 +39,7 @@ void pa_alsa_fdlist_free(struct pa_alsa_fdlist *fdl);  int pa_alsa_fdlist_set_mixer(struct pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, pa_mainloop_api* m);  int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size, int *use_mmap); +int pa_alsa_set_sw_params(snd_pcm_t *pcm);  int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev);  snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const char *fallback); diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index ced42ee3..5765d780 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -545,18 +545,23 @@ static void thread_func(void *userdata) {                      goto fail;              } else { -                ssize_t l; - -                if ((err = snd_pcm_status(u->pcm_handle, status)) >= 0) -                    l = snd_pcm_status_get_avail(status) * u->frame_size; -                else -                    l = u->fragment_size; - -                while (l > 0) { +                for (;;) {                      void *p;                      snd_pcm_sframes_t t; +                    ssize_t l; +                 +                    if ((err = snd_pcm_status(u->pcm_handle, status)) < 0) { +                        pa_log("Failed to query DSP status data: %s", snd_strerror(t)); +                        goto fail; +                    } -                    pa_assert(l > 0); +                    if (snd_pcm_status_get_avail_max(status)*u->frame_size >= u->hwbuf_size) +                        pa_log_debug("Buffer underrun!"); +                     +                    l = snd_pcm_status_get_avail(status) * u->frame_size; + +                    if (l <= 0) +                        break;                      if (u->memchunk.length <= 0)                          pa_sink_render(u->sink, l, &u->memchunk); @@ -573,10 +578,7 @@ static void thread_func(void *userdata) {                      if (t < 0) { -                        if (t == -EPIPE) { -                            pa_log_debug("Buffer underrun!"); -                            u->first = 1; -                        } +                        pa_assert(t != -EPIPE);                          if ((t = snd_pcm_recover(u->pcm_handle, t, 1)) == 0)                              continue; @@ -588,21 +590,20 @@ static void thread_func(void *userdata) {                              pa_log("Failed to write data to DSP: %s", snd_strerror(t));                              goto fail;                          } +                    } -                    } else { -                         -                        u->memchunk.index += t * u->frame_size; -                        u->memchunk.length -= t * u->frame_size; -                         -                        if (u->memchunk.length <= 0) { -                            pa_memblock_unref(u->memchunk.memblock); -                            pa_memchunk_reset(&u->memchunk); -                        } -                         -                        l -= t * u->frame_size; - -                        work_done = 1; +                    u->memchunk.index += t * u->frame_size; +                    u->memchunk.length -= t * u->frame_size; +                     +                    if (u->memchunk.length <= 0) { +                        pa_memblock_unref(u->memchunk.memblock); +                        pa_memchunk_reset(&u->memchunk);                      } + +                    work_done = 1; + +                    if (t * u->frame_size >= (unsigned) l) +                        break;                  }               } @@ -756,6 +757,11 @@ int pa__init(pa_core *c, pa_module*m) {      if (u->use_mmap)          pa_log_info("Successfully enabled mmap() mode."); +    if ((err = pa_alsa_set_sw_params(u->pcm_handle)) < 0) { +        pa_log("Failed to set software parameters: %s", snd_strerror(err)); +        goto fail; +    } +      /* ALSA might tweak the sample spec, so recalculate the frame size */      frame_size = pa_frame_size(&ss); diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 0fd7bca0..9a5d5acb 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -533,19 +533,25 @@ static void thread_func(void *userdata) {                      goto fail;              } else { -                ssize_t l; -                if ((err = snd_pcm_status(u->pcm_handle, status)) >= 0) -                    l = snd_pcm_status_get_avail(status) * u->frame_size; -                else -                    l = u->fragment_size; - -                while (l > 0) { +                for (;;) {                      void *p;                      snd_pcm_sframes_t t; +                    ssize_t l; -                    pa_assert(l > 0); +                    if ((err = snd_pcm_status(u->pcm_handle, status)) < 0) { +                        pa_log("Failed to query DSP status data: %s", snd_strerror(t)); +                        goto fail; +                    } +                    if (snd_pcm_status_get_avail_max(status)*u->frame_size >= u->hwbuf_size) +                        pa_log_debug("Buffer overrun!"); +                     +                    l = snd_pcm_status_get_avail(status) * u->frame_size; + +                    if (l <= 0) +                        break; +                                          chunk.memblock = pa_memblock_new(u->core->mempool, l);                      p = pa_memblock_acquire(chunk.memblock); @@ -559,8 +565,7 @@ static void thread_func(void *userdata) {                      if (t < 0) {                          pa_memblock_unref(chunk.memblock); -                        if (t == -EPIPE) -                            pa_log_debug("Buffer underrun!"); +                        pa_assert(t != -EPIPE);                          if ((t = snd_pcm_recover(u->pcm_handle, t, 1)) == 0)                              continue; @@ -573,18 +578,18 @@ static void thread_func(void *userdata) {                              goto fail;                          } -                    } else { +                    }  -                        chunk.index = 0; -                        chunk.length = t * u->frame_size; +                    chunk.index = 0; +                    chunk.length = t * u->frame_size; -                        pa_source_post(u->source, &chunk); -                        pa_memblock_unref(chunk.memblock); -                         -                        l -= t * u->frame_size; +                    pa_source_post(u->source, &chunk); +                    pa_memblock_unref(chunk.memblock); +                     +                    work_done = 1; -                        work_done = 1; -                    } +                    if (t * u->frame_size >= (unsigned) l) +                        break;                  }               } @@ -730,6 +735,11 @@ int pa__init(pa_core *c, pa_module*m) {      if (u->use_mmap)          pa_log_info("Successfully enabled mmap() mode."); + +    if ((err = pa_alsa_set_sw_params(u->pcm_handle)) < 0) { +        pa_log("Failed to set software parameters: %s", snd_strerror(err)); +        goto fail; +    }      /* ALSA might tweak the sample spec, so recalculate the frame size */      frame_size = pa_frame_size(&ss);  | 
