[pulseaudio-commits] [SCM] PulseAudio Sound Server branch, stable-queue, updated. v0.9.21-88-geef247b

Colin Guthrie gitmailer-noreply at 0pointer.de
Tue Sep 14 11:54:52 PDT 2010


This is an automated email from the git hooks/post-receive script. It was
generated because of a push to the "PulseAudio Sound Server" repository.

The stable-queue branch has been updated
      from  4fb02d8e0efed20a3e01f3456d091e408a72953f (commit)

- Log -----------------------------------------------------------------
eef247b alsa: Only set the 'first' flag to false when we actually call snd_pcm_start()
28f4aeb alsa-mixer: add profile for Traktor Kontrol S4
1ff360c alsa: make defines for smoother configuration
1c29f55 alsa: work around slightly broken _delay implementations
74c117f alsa-time-test: make test usable for capture too
1503b8c alsa-source: refactor smoother and device start
3d9b710 smoother: avoid losing precision
a65825f alsa: Set the rewind safeguard proportionally to sample spec
8748ebd alsa-sink: Get rid of a compiler warning regarding rewind_safeguard type.
514fd1e add rewind-safeguard parameter
e2ef3a1 alsa: don't make use of tsched related variables when tsched is disabled
-----------------------------------------------------------------------

Summary of changes:
 src/Makefile.am                                    |    3 +-
 src/modules/alsa/alsa-sink.c                       |   61 +++++++++++----
 src/modules/alsa/alsa-source.c                     |   63 ++++++++++-----
 src/modules/alsa/alsa-util.c                       |   46 ++++++++++-
 src/modules/alsa/alsa-util.h                       |    2 +-
 .../alsa/mixer/profile-sets/90-pulseaudio.rules    |    1 +
 .../native-instruments-traktorkontrol-s4.conf      |   81 ++++++++++++++++++++
 src/modules/alsa/module-alsa-sink.c                |    4 +-
 src/pulsecore/time-smoother.c                      |    4 +-
 src/tests/alsa-time-test.c                         |   59 ++++++++++----
 10 files changed, 260 insertions(+), 64 deletions(-)
 create mode 100644 src/modules/alsa/mixer/profile-sets/native-instruments-traktorkontrol-s4.conf

-----------------------------------------------------------------------

commit e2ef3a1391956bddefdce8716f28776190122ae3
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Feb 23 03:23:22 2010 +0100

    alsa: don't make use of tsched related variables when tsched is disabled

diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index a253cc5..3b13cc2 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -632,11 +632,14 @@ static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polle
         }
     }
 
-    *sleep_usec = pa_bytes_to_usec(left_to_play, &u->sink->sample_spec);
+    if (u->use_tsched) {
+        *sleep_usec = pa_bytes_to_usec(left_to_play, &u->sink->sample_spec);
 
-    if (*sleep_usec > process_usec)
-        *sleep_usec -= process_usec;
-    else
+        if (*sleep_usec > process_usec)
+            *sleep_usec -= process_usec;
+        else
+            *sleep_usec = 0;
+    } else
         *sleep_usec = 0;
 
     return work_done ? 1 : 0;
@@ -769,11 +772,14 @@ static int unix_write(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polle
         }
     }
 
-    *sleep_usec = pa_bytes_to_usec(left_to_play, &u->sink->sample_spec);
+    if (u->use_tsched) {
+        *sleep_usec = pa_bytes_to_usec(left_to_play, &u->sink->sample_spec);
 
-    if (*sleep_usec > process_usec)
-        *sleep_usec -= process_usec;
-    else
+        if (*sleep_usec > process_usec)
+            *sleep_usec -= process_usec;
+        else
+            *sleep_usec = 0;
+    } else
         *sleep_usec = 0;
 
     return work_done ? 1 : 0;
@@ -1275,6 +1281,9 @@ static void sink_update_requested_latency_cb(pa_sink *s) {
     struct userdata *u = s->userdata;
     size_t before;
     pa_assert(u);
+    pa_assert(u->use_tsched); /* only when timer scheduling is used
+                               * we can dynamically adjust the
+                               * latency */
 
     if (!u->pcm_handle)
         return;
@@ -1309,7 +1318,10 @@ static int process_rewind(struct userdata *u) {
         return -1;
     }
 
-    unused_nbytes = u->tsched_watermark + (size_t) unused * u->frame_size;
+    unused_nbytes = (size_t) unused * u->frame_size;
+
+    if (u->use_tsched)
+        unused_nbytes += u->tsched_watermark;
 
     if (u->hwbuf_size > unused_nbytes)
         limit_nbytes = u->hwbuf_size - unused_nbytes;
@@ -1870,7 +1882,8 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
     }
 
     u->sink->parent.process_msg = sink_process_msg;
-    u->sink->update_requested_latency = sink_update_requested_latency_cb;
+    if (u->use_tsched)
+        u->sink->update_requested_latency = sink_update_requested_latency_cb;
     u->sink->set_state = sink_set_state_cb;
     u->sink->set_port = sink_set_port_cb;
     u->sink->userdata = u;
@@ -1919,7 +1932,6 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
     } else
         pa_sink_set_fixed_latency(u->sink, pa_bytes_to_usec(u->hwbuf_size, &ss));
 
-
     reserve_update(u);
 
     if (update_sw_params(u) < 0)
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index c9c6048..ecea191 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -603,12 +603,14 @@ static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polled
         }
     }
 
-    *sleep_usec = pa_bytes_to_usec(left_to_record, &u->source->sample_spec);
+    if (u->use_tsched) {
+        *sleep_usec = pa_bytes_to_usec(left_to_record, &u->source->sample_spec);
 
-    if (*sleep_usec > process_usec)
-        *sleep_usec -= process_usec;
-    else
-        *sleep_usec = 0;
+        if (*sleep_usec > process_usec)
+            *sleep_usec -= process_usec;
+        else
+            *sleep_usec = 0;
+    }
 
     return work_done ? 1 : 0;
 }
@@ -730,12 +732,14 @@ static int unix_read(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polled
         }
     }
 
-    *sleep_usec = pa_bytes_to_usec(left_to_record, &u->source->sample_spec);
+    if (u->use_tsched) {
+        *sleep_usec = pa_bytes_to_usec(left_to_record, &u->source->sample_spec);
 
-    if (*sleep_usec > process_usec)
-        *sleep_usec -= process_usec;
-    else
-        *sleep_usec = 0;
+        if (*sleep_usec > process_usec)
+            *sleep_usec -= process_usec;
+        else
+            *sleep_usec = 0;
+    }
 
     return work_done ? 1 : 0;
 }
@@ -1205,6 +1209,7 @@ static int source_set_port_cb(pa_source *s, pa_device_port *p) {
 static void source_update_requested_latency_cb(pa_source *s) {
     struct userdata *u = s->userdata;
     pa_assert(u);
+    pa_assert(u->use_tsched);
 
     if (!u->pcm_handle)
         return;
@@ -1693,7 +1698,8 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
     }
 
     u->source->parent.process_msg = source_process_msg;
-    u->source->update_requested_latency = source_update_requested_latency_cb;
+    if (u->use_tsched)
+        u->source->update_requested_latency = source_update_requested_latency_cb;
     u->source->set_state = source_set_state_cb;
     u->source->set_port = source_set_port_cb;
     u->source->userdata = u;

commit 514fd1eee848c3a81298fa34422df3a98027b322
Author: Pierre-Louis Bossart <pierre-louis.bossart at intel.com>
Date:   Thu Apr 29 10:48:11 2010 -0500

    add rewind-safeguard parameter
    
    Rewinding the ring buffer completely causes audible issues with DMAs.
    Previous solution didn't work with tsched=0, and used tsched_watermark
    for guardband, which isn't linked to hardware and could become really high
    if underflows occurred.
    
    Added separate parameter that can be tuned to hardware limitations and size
    of DMA bursts.

diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index 3b13cc2..41ddce7 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -83,6 +83,8 @@
 
 #define VOLUME_ACCURACY (PA_VOLUME_NORM/100)  /* don't require volume adjustments to be perfectly correct. don't necessarily extend granularity in software unless the differences get greater than this level */
 
+#define DEFAULT_REWIND_SAFEGUARD_BYTES (256) /* 1.33ms @48kHz, should work for most hardware */
+
 struct userdata {
     pa_core *core;
     pa_module *module;
@@ -112,7 +114,8 @@ struct userdata {
         watermark_inc_step,
         watermark_dec_step,
         watermark_inc_threshold,
-        watermark_dec_threshold;
+        watermark_dec_threshold,
+        rewind_safeguard;
 
     pa_usec_t watermark_dec_not_before;
 
@@ -1320,8 +1323,8 @@ static int process_rewind(struct userdata *u) {
 
     unused_nbytes = (size_t) unused * u->frame_size;
 
-    if (u->use_tsched)
-        unused_nbytes += u->tsched_watermark;
+    /* make sure rewind doesn't go too far, can cause issues with DMAs */
+    unused_nbytes += u->rewind_safeguard;
 
     if (u->hwbuf_size > unused_nbytes)
         limit_nbytes = u->hwbuf_size - unused_nbytes;
@@ -1676,7 +1679,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
     pa_channel_map map;
     uint32_t nfrags, frag_size, buffer_size, tsched_size, tsched_watermark;
     snd_pcm_uframes_t period_frames, buffer_frames, tsched_frames;
-    size_t frame_size;
+    size_t frame_size, rewind_safeguard;
     pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, ignore_dB = FALSE;
     pa_sink_new_data data;
     pa_alsa_profile_set *profile_set = NULL;
@@ -1730,6 +1733,12 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
         goto fail;
     }
 
+    rewind_safeguard = DEFAULT_REWIND_SAFEGUARD_BYTES;
+    if (pa_modargs_get_value_u32(ma, "rewind_safeguard", &rewind_safeguard) < 0) {
+        pa_log("Failed to parse rewind_safeguard argument");
+        goto fail;
+    }
+
     use_tsched = pa_alsa_may_tsched(use_tsched);
 
     u = pa_xnew0(struct userdata, 1);
@@ -1738,6 +1747,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
     u->use_mmap = use_mmap;
     u->use_tsched = use_tsched;
     u->first = TRUE;
+    u->rewind_safeguard = rewind_safeguard;
     u->rtpoll = pa_rtpoll_new();
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
 
diff --git a/src/modules/alsa/module-alsa-sink.c b/src/modules/alsa/module-alsa-sink.c
index 3aa89b2..a73274f 100644
--- a/src/modules/alsa/module-alsa-sink.c
+++ b/src/modules/alsa/module-alsa-sink.c
@@ -54,7 +54,8 @@ PA_MODULE_USAGE(
         "tsched_buffer_size=<buffer size when using timer based scheduling> "
         "tsched_buffer_watermark=<lower fill watermark> "
         "ignore_dB=<ignore dB information from the device?> "
-        "control=<name of mixer control>");
+        "control=<name of mixer control>"
+        "rewind_safeguard=<number of bytes that cannot be rewound");
 
 static const char* const valid_modargs[] = {
     "name",
@@ -74,6 +75,7 @@ static const char* const valid_modargs[] = {
     "tsched_buffer_watermark",
     "ignore_dB",
     "control",
+    "rewind_safeguard",
     NULL
 };
 

commit 8748ebdad3c15dae3cafe6a0ae9227fc3bb9f7ad
Author: Tanu Kaskinen <tanuk at iki.fi>
Date:   Tue Aug 24 17:47:25 2010 +0300

    alsa-sink: Get rid of a compiler warning regarding rewind_safeguard type.
    
    GCC gave a warning, because the pointer given to pa_modargs_get_value_u32() had
    type size_t instead of uint32_t.

diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index 41ddce7..9e200bd 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -1677,9 +1677,9 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
     const char *dev_id = NULL;
     pa_sample_spec ss, requested_ss;
     pa_channel_map map;
-    uint32_t nfrags, frag_size, buffer_size, tsched_size, tsched_watermark;
+    uint32_t nfrags, frag_size, buffer_size, tsched_size, tsched_watermark, rewind_safeguard;
     snd_pcm_uframes_t period_frames, buffer_frames, tsched_frames;
-    size_t frame_size, rewind_safeguard;
+    size_t frame_size;
     pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, ignore_dB = FALSE;
     pa_sink_new_data data;
     pa_alsa_profile_set *profile_set = NULL;

commit a65825fa45a1c393899eeb1e4532236964ea3a2c
Author: Colin Guthrie <cguthrie at mandriva.org>
Date:   Sat Sep 4 11:58:05 2010 +0100

    alsa: Set the rewind safeguard proportionally to sample spec
    
    Currently when rewinding alsa, a fixed value of 256 bytes is used,
    which represents 1.33ms @ 48kHz (2ch, 16bit). This is typically fine
    and due to DMA constraints we would not want to rewind less than this.
    
    However with more demanding sample specs, (e.g. 8ch 192kHz 32bit)
    256 bytes is likely not sufficient, so calculate what 1.33ms would
    be and use which ever value is bigger.
    
    Discussed with David Henningsson and Pierre-Louis Bossart here:
     http://thread.gmane.org/gmane.comp.audio.pulseaudio.general/7286

diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index 9e200bd..4a5fe3f 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -83,7 +83,8 @@
 
 #define VOLUME_ACCURACY (PA_VOLUME_NORM/100)  /* don't require volume adjustments to be perfectly correct. don't necessarily extend granularity in software unless the differences get greater than this level */
 
-#define DEFAULT_REWIND_SAFEGUARD_BYTES (256) /* 1.33ms @48kHz, should work for most hardware */
+#define DEFAULT_REWIND_SAFEGUARD_BYTES (256U) /* 1.33ms @48kHz, we'll never rewind less than this */
+#define DEFAULT_REWIND_SAFEGUARD_USEC (1330) /* 1.33ms, depending on channels/rate/sample we may rewind more than 256 above */
 
 struct userdata {
     pa_core *core;
@@ -1733,7 +1734,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
         goto fail;
     }
 
-    rewind_safeguard = DEFAULT_REWIND_SAFEGUARD_BYTES;
+    rewind_safeguard = PA_MAX(DEFAULT_REWIND_SAFEGUARD_BYTES, pa_usec_to_bytes(DEFAULT_REWIND_SAFEGUARD_USEC, &ss));
     if (pa_modargs_get_value_u32(ma, "rewind_safeguard", &rewind_safeguard) < 0) {
         pa_log("Failed to parse rewind_safeguard argument");
         goto fail;

commit 3d9b710bea79a3663aa7f78a182991e3e1502ecf
Author: Wim Taymans <wim.taymans at collabora.co.uk>
Date:   Mon Sep 6 15:22:26 2010 +0200

    smoother: avoid losing precision
    
    Avoid losing precision by subtracting uint64 values before converting them to
    doubles.

diff --git a/src/pulsecore/time-smoother.c b/src/pulsecore/time-smoother.c
index d6c3787..422f12d 100644
--- a/src/pulsecore/time-smoother.c
+++ b/src/pulsecore/time-smoother.c
@@ -313,10 +313,8 @@ static void estimate(pa_smoother *s, pa_usec_t x, pa_usec_t *y, double *deriv) {
 
         calc_abc(s);
 
-        tx = (double) x;
-
         /* Move to origin */
-        tx -= (double) s->ex;
+        tx = (double) (x - s->ex);
 
         /* Horner scheme */
         ty = (tx * (s->c + tx * (s->b + tx * s->a)));

commit 1503b8cf9babe338e51598b0c689890f37d0850a
Author: Wim Taymans <wim.taymans at collabora.co.uk>
Date:   Mon Sep 6 15:26:19 2010 +0200

    alsa-source: refactor smoother and device start
    
    Move the code to start the capture and the smoother closer together to improve
    smoother accuracy.
    Rework things to look more like the alsa sink where the device is started in
    only one place.

diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index ecea191..8b2cee5 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -116,6 +116,8 @@ struct userdata {
 
     pa_bool_t use_mmap:1, use_tsched:1;
 
+    pa_bool_t first;
+
     pa_rtpoll_item *alsa_rtpoll_item;
 
     snd_mixer_selem_channel_id_t mixer_map[SND_MIXER_SCHN_LAST];
@@ -397,7 +399,7 @@ static int try_recover(struct userdata *u, const char *call, int err) {
         return -1;
     }
 
-    snd_pcm_start(u->pcm_handle);
+    u->first = TRUE;
     return 0;
 }
 
@@ -946,13 +948,13 @@ static int unsuspend(struct userdata *u) {
 
     /* FIXME: We need to reload the volume somehow */
 
-    snd_pcm_start(u->pcm_handle);
-
     u->read_count = 0;
-    pa_smoother_reset(u->smoother, pa_rtclock_now(), FALSE);
+    pa_smoother_reset(u->smoother, pa_rtclock_now(), TRUE);
     u->smoother_interval = SMOOTHER_MIN_INTERVAL;
     u->last_smoother_update = 0;
 
+    u->first = TRUE;
+
     pa_log_info("Resumed successfully...");
 
     return 0;
@@ -1003,8 +1005,6 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
                     if (u->source->thread_info.state == PA_SOURCE_INIT) {
                         if (build_pollfd(u) < 0)
                             return -PA_ERR_IO;
-
-                        snd_pcm_start(u->pcm_handle);
                     }
 
                     if (u->source->thread_info.state == PA_SOURCE_SUSPENDED) {
@@ -1243,6 +1243,15 @@ static void thread_func(void *userdata) {
             pa_usec_t sleep_usec = 0;
             pa_bool_t on_timeout = pa_rtpoll_timer_elapsed(u->rtpoll);
 
+            if (u->first) {
+                pa_log_info("Starting capture.");
+                snd_pcm_start(u->pcm_handle);
+
+                pa_smoother_resume(u->smoother, pa_rtclock_now(), TRUE);
+
+                u->first = FALSE;
+            }
+
             if (u->use_mmap)
                 work_done = mmap_read(u, &sleep_usec, revents & POLLIN, on_timeout);
             else
@@ -1302,7 +1311,7 @@ static void thread_func(void *userdata) {
                 if (pa_alsa_recover_from_poll(u->pcm_handle, revents) < 0)
                     goto fail;
 
-                snd_pcm_start(u->pcm_handle);
+                u->first = TRUE;
             } else if (revents && u->use_tsched && pa_log_ratelimit())
                 pa_log_debug("Wakeup from ALSA!");
 
@@ -1556,6 +1565,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
     u->module = m;
     u->use_mmap = use_mmap;
     u->use_tsched = use_tsched;
+    u->first = TRUE;
     u->rtpoll = pa_rtpoll_new();
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
 
@@ -1566,7 +1576,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
             TRUE,
             5,
             pa_rtclock_now(),
-            FALSE);
+            TRUE);
     u->smoother_interval = SMOOTHER_MIN_INTERVAL;
 
     dev_id = pa_modargs_get_value(

commit 74c117f49f9a896448ba9c4140d0fa0ed4be71d2
Author: Wim Taymans <wim.taymans at collabora.co.uk>
Date:   Mon Sep 6 17:48:56 2010 +0200

    alsa-time-test: make test usable for capture too
    
    Extend the test to also work for capture devices.

diff --git a/src/tests/alsa-time-test.c b/src/tests/alsa-time-test.c
index 233bbe6..1a572b3 100644
--- a/src/tests/alsa-time-test.c
+++ b/src/tests/alsa-time-test.c
@@ -12,7 +12,7 @@ static uint64_t timespec_us(const struct timespec *ts) {
 
 int main(int argc, char *argv[]) {
     const char *dev;
-    int r;
+    int r, cap;
     snd_pcm_hw_params_t *hwparams;
     snd_pcm_sw_params_t *swparams;
     snd_pcm_status_t *status;
@@ -38,8 +38,12 @@ int main(int argc, char *argv[]) {
     start_us = timespec_us(&start);
 
     dev = argc > 1 ? argv[1] : "front:AudioPCI";
+    cap = argc > 2 ? atoi(argv[2]) : 0;
 
-    r = snd_pcm_open(&pcm, dev, SND_PCM_STREAM_PLAYBACK, 0);
+    if (cap == 0)
+      r = snd_pcm_open(&pcm, dev, SND_PCM_STREAM_PLAYBACK, 0);
+    else
+      r = snd_pcm_open(&pcm, dev, SND_PCM_STREAM_CAPTURE, 0);
     assert(r == 0);
 
     r = snd_pcm_hw_params_any(pcm, hwparams);
@@ -78,7 +82,10 @@ int main(int argc, char *argv[]) {
     r = snd_pcm_sw_params_current(pcm, swparams);
     assert(r == 0);
 
-    r = snd_pcm_sw_params_set_avail_min(pcm, swparams, 1);
+    if (cap == 0)
+      r = snd_pcm_sw_params_set_avail_min(pcm, swparams, 1);
+    else
+      r = snd_pcm_sw_params_set_avail_min(pcm, swparams, 0);
     assert(r == 0);
 
     r = snd_pcm_sw_params_set_period_event(pcm, swparams, 0);
@@ -117,13 +124,19 @@ int main(int argc, char *argv[]) {
     r = snd_pcm_poll_descriptors(pcm, pollfds, n_pollfd);
     assert(r == n_pollfd);
 
+    if (cap) {
+      r = snd_pcm_start(pcm);
+      assert(r == 0);
+    }
+
     for (;;) {
         snd_pcm_sframes_t avail, delay;
         struct timespec now, timestamp;
         unsigned short revents;
-        int written = 0;
+        int handled = 0;
         uint64_t now_us, timestamp_us;
         snd_pcm_state_t state;
+        unsigned long long pos;
 
         r = poll(pollfds, n_pollfd, 0);
         assert(r >= 0);
@@ -131,7 +144,10 @@ int main(int argc, char *argv[]) {
         r = snd_pcm_poll_descriptors_revents(pcm, pollfds, n_pollfd, &revents);
         assert(r == 0);
 
-        assert((revents & ~POLLOUT) == 0);
+        if (cap == 0)
+          assert((revents & ~POLLOUT) == 0);
+        else
+          assert((revents & ~POLLIN) == 0);
 
         avail = snd_pcm_avail(pcm);
         assert(avail >= 0);
@@ -152,18 +168,22 @@ int main(int argc, char *argv[]) {
 
         assert(!revents || avail > 0);
 
-        if (avail) {
+        if ((!cap && avail) || (cap && (unsigned)avail >= buffer_size)) {
             snd_pcm_sframes_t sframes;
-            static const uint16_t samples[2] = { 0, 0 };
+            static const uint16_t psamples[2] = { 0, 0 };
+            uint16_t csamples[2];
 
-            sframes = snd_pcm_writei(pcm, samples, 1);
+            if (cap == 0)
+              sframes = snd_pcm_writei(pcm, psamples, 1);
+            else
+              sframes = snd_pcm_readi(pcm, csamples, 1);
             assert(sframes == 1);
 
-            written = 1;
+            handled = 1;
             sample_count++;
         }
 
-        if (!written &&
+        if (!handled &&
             memcmp(&timestamp, &last_timestamp, sizeof(timestamp)) == 0 &&
             avail == last_avail &&
             delay == last_delay) {
@@ -174,19 +194,26 @@ int main(int argc, char *argv[]) {
         now_us = timespec_us(&now);
         timestamp_us = timespec_us(&timestamp);
 
-        printf("%llu\t%llu\t%llu\t%li\t%li\t%i\t%i\t%i\n",
+        if (cap == 0)
+            pos = (unsigned long long) ((sample_count - handled - delay) * 1000000LU / 44100);
+        else
+            pos = (unsigned long long) ((sample_count - handled + delay) * 1000000LU / 44100);
+
+        printf("%llu\t%llu\t%llu\t%llu\t%li\t%li\t%i\t%i\t%i\n",
                (unsigned long long) (now_us - start_us),
                (unsigned long long) (timestamp_us ? timestamp_us - start_us : 0),
-               (unsigned long long) ((sample_count - 1 - delay) * 1000000LU / 44100),
+               pos,
+               (unsigned long long) sample_count,
                (signed long) avail,
                (signed long) delay,
                revents,
-               written,
+               handled,
                state);
 
-        /** When this assert is hit, most likely something bad
-         * happened, i.e. the avail jumped suddenly. */
-        assert((unsigned) avail <= buffer_size);
+        if (cap == 0)
+          /** When this assert is hit, most likely something bad
+           * happened, i.e. the avail jumped suddenly. */
+          assert((unsigned) avail <= buffer_size);
 
         last_avail = avail;
         last_delay = delay;

commit 1c29f5582d3638a32271d8882de7c22579a42c6f
Author: Wim Taymans <wim.taymans at collabora.co.uk>
Date:   Wed Sep 8 13:26:39 2010 +0200

    alsa: work around slightly broken _delay implementations
    
    Use snd_pcm_avail_delay() in pa_alsa_safe_delay() so that we can check the delay
    value against the avail value and patch it up when it looks invalid. Only do
    this for capture.

diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index 4a5fe3f..ae7fecd 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -803,7 +803,7 @@ static void update_smoother(struct userdata *u) {
 
     /* Let's update the time smoother */
 
-    if (PA_UNLIKELY((err = pa_alsa_safe_delay(u->pcm_handle, &delay, u->hwbuf_size, &u->sink->sample_spec)) < 0)) {
+    if (PA_UNLIKELY((err = pa_alsa_safe_delay(u->pcm_handle, &delay, u->hwbuf_size, &u->sink->sample_spec, FALSE)) < 0)) {
         pa_log_warn("Failed to query DSP status data: %s", pa_alsa_strerror(err));
         return;
     }
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index 8b2cee5..10f0d74 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -760,7 +760,7 @@ static void update_smoother(struct userdata *u) {
 
     /* Let's update the time smoother */
 
-    if (PA_UNLIKELY((err = pa_alsa_safe_delay(u->pcm_handle, &delay, u->hwbuf_size, &u->source->sample_spec)) < 0)) {
+    if (PA_UNLIKELY((err = pa_alsa_safe_delay(u->pcm_handle, &delay, u->hwbuf_size, &u->source->sample_spec, TRUE)) < 0)) {
         pa_log_warn("Failed to get delay: %s", pa_alsa_strerror(err));
         return;
     }
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
index 1cbb3f3..2d0d356 100644
--- a/src/modules/alsa/alsa-util.c
+++ b/src/modules/alsa/alsa-util.c
@@ -1125,10 +1125,11 @@ snd_pcm_sframes_t pa_alsa_safe_avail(snd_pcm_t *pcm, size_t hwbuf_size, const pa
     return n;
 }
 
-int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delay, size_t hwbuf_size, const pa_sample_spec *ss) {
+int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delay, size_t hwbuf_size, const pa_sample_spec *ss, pa_bool_t capture) {
     ssize_t k;
     size_t abs_k;
     int r;
+    snd_pcm_sframes_t avail = 0;
 
     pa_assert(pcm);
     pa_assert(delay);
@@ -1136,9 +1137,10 @@ int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delay, size_t hwbuf_si
     pa_assert(ss);
 
     /* Some ALSA driver expose weird bugs, let's inform the user about
-     * what is going on */
+     * what is going on. We're going to get both the avail and delay values so
+     * that we can compare and check them for capture */
 
-    if ((r = snd_pcm_delay(pcm, delay)) < 0)
+    if ((r = snd_pcm_avail_delay(pcm, &avail, delay)) < 0)
         return r;
 
     k = (ssize_t) *delay * (ssize_t) pa_frame_size(ss);
@@ -1167,6 +1169,44 @@ int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delay, size_t hwbuf_si
             *delay = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
     }
 
+    if (capture) {
+        abs_k = (size_t) avail * pa_frame_size(ss);
+
+        if (abs_k >= hwbuf_size * 5 ||
+            abs_k >= pa_bytes_per_second(ss)*10) {
+
+            PA_ONCE_BEGIN {
+                char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
+                pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
+                         "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
+                       (unsigned long) k,
+                       (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
+                       pa_strnull(dn));
+                pa_xfree(dn);
+                pa_alsa_dump(PA_LOG_ERROR, pcm);
+            } PA_ONCE_END;
+
+            /* Mhmm, let's try not to fail completely */
+            avail = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
+        }
+
+        if (*delay < avail) {
+            PA_ONCE_BEGIN {
+                char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
+                pa_log(_("snd_pcm_avail_delay() returned strange values: delay %lu is less than avail %lu.\n"
+                         "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
+                       (unsigned long) *delay,
+                       (unsigned long) avail,
+                       pa_strnull(dn));
+                pa_xfree(dn);
+                pa_alsa_dump(PA_LOG_ERROR, pcm);
+            } PA_ONCE_END;
+
+            /* try to fixup */
+            *delay = avail;
+        }
+    }
+
     return 0;
 }
 
diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h
index 1d1256b..9e29fd4 100644
--- a/src/modules/alsa/alsa-util.h
+++ b/src/modules/alsa/alsa-util.h
@@ -129,7 +129,7 @@ int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents);
 pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll);
 
 snd_pcm_sframes_t pa_alsa_safe_avail(snd_pcm_t *pcm, size_t hwbuf_size, const pa_sample_spec *ss);
-int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delay, size_t hwbuf_size, const pa_sample_spec *ss);
+int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delay, size_t hwbuf_size, const pa_sample_spec *ss, pa_bool_t capture);
 int pa_alsa_safe_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas, snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames, size_t hwbuf_size, const pa_sample_spec *ss);
 
 char *pa_alsa_get_driver_name(int card);

commit 1ff360c7b107ba5710cc084183fb1c4bc49cd6af
Author: Wim Taymans <wim.taymans at collabora.co.uk>
Date:   Thu Sep 9 12:29:59 2010 +0200

    alsa: make defines for smoother configuration
    
    Make new defines for the smoother window size and adjust time constants instead
    of reusing some unrelated constant.
    
    Increase the smoother window size even more because the bigger it is, the
    better. Since we have a 200ms max update interval and the max smoother history
    is 64 entries, 10seconds is a good default.
    
    Decrease the smoother adjust time to 1 second. The previous value of 4 seconds
    was too much to adapt quickly after a resume.

diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index ae7fecd..935b1f8 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -78,6 +78,9 @@
 #define TSCHED_MIN_SLEEP_USEC (10*PA_USEC_PER_MSEC)                /* 10ms  -- Sleep at least 10ms on each iteration */
 #define TSCHED_MIN_WAKEUP_USEC (4*PA_USEC_PER_MSEC)                /* 4ms   -- Wakeup at least this long before the buffer runs empty*/
 
+#define SMOOTHER_WINDOW_USEC  (10*PA_USEC_PER_SEC)                 /* 10s   -- smoother windows size */
+#define SMOOTHER_ADJUST_USEC  (1*PA_USEC_PER_SEC)                  /* 1s    -- smoother adjust time */
+
 #define SMOOTHER_MIN_INTERVAL (2*PA_USEC_PER_MSEC)                 /* 2ms   -- min smoother update interval */
 #define SMOOTHER_MAX_INTERVAL (200*PA_USEC_PER_MSEC)               /* 200ms -- max smoother update interval */
 
@@ -1753,8 +1756,8 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
 
     u->smoother = pa_smoother_new(
-            DEFAULT_TSCHED_BUFFER_USEC*2,
-            DEFAULT_TSCHED_BUFFER_USEC*2,
+            SMOOTHER_ADJUST_USEC,
+            SMOOTHER_WINDOW_USEC,
             TRUE,
             TRUE,
             5,
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index 10f0d74..0ad0fbc 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -73,6 +73,9 @@
 #define TSCHED_MIN_SLEEP_USEC (10*PA_USEC_PER_MSEC)                /* 10ms */
 #define TSCHED_MIN_WAKEUP_USEC (4*PA_USEC_PER_MSEC)                /* 4ms */
 
+#define SMOOTHER_WINDOW_USEC  (10*PA_USEC_PER_SEC)                 /* 10s */
+#define SMOOTHER_ADJUST_USEC  (1*PA_USEC_PER_SEC)                  /* 1s */
+
 #define SMOOTHER_MIN_INTERVAL (2*PA_USEC_PER_MSEC)                 /* 2ms */
 #define SMOOTHER_MAX_INTERVAL (200*PA_USEC_PER_MSEC)               /* 200ms */
 
@@ -1570,8 +1573,8 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
 
     u->smoother = pa_smoother_new(
-            DEFAULT_TSCHED_BUFFER_USEC*2,
-            DEFAULT_TSCHED_BUFFER_USEC*2,
+            SMOOTHER_ADJUST_USEC,
+            SMOOTHER_WINDOW_USEC,
             TRUE,
             TRUE,
             5,

commit 28f4aebfbf49a346f978b76efaac53768f5440f9
Author: Daniel Mack <daniel at caiaq.de>
Date:   Sat Sep 11 10:06:00 2010 +0800

    alsa-mixer: add profile for Traktor Kontrol S4
    
    This new audio interface from Native Instruments has 2 stereo channels
    for both input and output direction. This patch adds mappings for them.

diff --git a/src/Makefile.am b/src/Makefile.am
index ffe7558..e7af61c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -111,7 +111,8 @@ ALSA_PROFILES = \
 		modules/alsa/mixer/profile-sets/default.conf \
 		modules/alsa/mixer/profile-sets/maudio-fasttrack-pro.conf \
 		modules/alsa/mixer/profile-sets/native-instruments-audio4dj.conf \
-		modules/alsa/mixer/profile-sets/native-instruments-audio8dj.conf
+		modules/alsa/mixer/profile-sets/native-instruments-audio8dj.conf \
+		modules/alsa/mixer/profile-sets/native-instruments-traktorkontrol-s4.conf
 
 ALSA_PATHS = \
 		modules/alsa/mixer/paths/analog-input-aux.conf \
diff --git a/src/modules/alsa/mixer/profile-sets/90-pulseaudio.rules b/src/modules/alsa/mixer/profile-sets/90-pulseaudio.rules
index b8e88d0..7a425b5 100644
--- a/src/modules/alsa/mixer/profile-sets/90-pulseaudio.rules
+++ b/src/modules/alsa/mixer/profile-sets/90-pulseaudio.rules
@@ -22,6 +22,7 @@ KERNEL!="card*", GOTO="pulseaudio_end"
 
 SUBSYSTEMS=="usb", ATTRS{idVendor}=="17cc", ATTRS{idProduct}=="1978", ENV{PULSE_PROFILE_SET}="native-instruments-audio8dj.conf"
 SUBSYSTEMS=="usb", ATTRS{idVendor}=="17cc", ATTRS{idProduct}=="0839", ENV{PULSE_PROFILE_SET}="native-instruments-audio4dj.conf"
+SUBSYSTEMS=="usb", ATTRS{idVendor}=="17cc", ATTRS{idProduct}=="baff", ENV{PULSE_PROFILE_SET}="native-instruments-traktorkontrol-s4.conf"
 SUBSYSTEMS=="usb", ATTRS{idVendor}=="0763", ATTRS{idProduct}=="2012", ENV{PULSE_PROFILE_SET}="maudio-fasttrack-pro.conf"
 
 LABEL="pulseaudio_end"
diff --git a/src/modules/alsa/mixer/profile-sets/native-instruments-traktorkontrol-s4.conf b/src/modules/alsa/mixer/profile-sets/native-instruments-traktorkontrol-s4.conf
new file mode 100644
index 0000000..1da843a
--- /dev/null
+++ b/src/modules/alsa/mixer/profile-sets/native-instruments-traktorkontrol-s4.conf
@@ -0,0 +1,81 @@
+# This file is part of PulseAudio.
+#
+# PulseAudio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# PulseAudio is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with PulseAudio; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+
+; Native Instruments Traktor Kontrol S4
+;
+; This controller has two stereo pairs of input (named "Channel C" and
+; "Channel D") and two stereo pairs of output, one "Main Out" and
+; "Headphone Out".
+;
+; See default.conf for an explanation on the directives used here.
+
+[General]
+auto-profiles = no
+
+[Mapping analog-stereo-output-main]
+description = Analog Stereo Main Out
+device-strings = hw:%f,0,0
+channel-map = left,right
+
+[Mapping analog-stereo-output-headphone]
+description = Analog Stereo Headphones Out
+device-strings = hw:%f,0,1
+channel-map = left,right
+direction = output
+
+[Mapping analog-stereo-c-input]
+description = Analog Stereo Channel C
+device-strings = hw:%f,0,1
+channel-map = left,right
+direction = input
+
+[Mapping analog-stereo-d-input]
+description = Analog Stereo Channel D
+device-strings = hw:%f,0,1
+channel-map = left,right
+direction = input
+
+[Profile output:analog-stereo-all+input:analog-stereo-all]
+description = Analog Stereo Duplex
+output-mappings = analog-stereo-output-main analog-stereo-output-headphone
+input-mappings = analog-stereo-c-input analog-stereo-d-input
+priority = 100
+skip-probe = yes
+
+[Profile output:analog-stereo-main]
+description = Analog Stereo Main Output
+output-mappings = analog-stereo-output-main
+priority = 4
+skip-probe = yes
+
+[Profile output:analog-stereo-headphone]
+description = Analog Stereo Output Headphones Out
+output-mappings = analog-stereo-output-headphone
+priority = 3
+skip-probe = yes
+
+[Profile input:analog-stereo-c]
+description = Analog Stereo Input Channel C
+input-mappings = analog-stereo-c-input
+priority = 2
+skip-probe = yes
+
+[Profile input:analog-stereo-d]
+description = Analog Stereo Input Channel D
+input-mappings = analog-stereo-d-input
+priority = 1
+skip-probe = yes
+

commit eef247b57e97841525a89c26f1eb35c52bf1af9e
Author: Colin Guthrie <cguthrie at mandriva.org>
Date:   Tue Sep 14 19:44:57 2010 +0100

    alsa: Only set the 'first' flag to false when we actually call snd_pcm_start()
    
    Previously, if work_done was false, we could conceivably not call snd_pcm_start().

diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index 935b1f8..112f02e 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -1420,6 +1420,8 @@ static void thread_func(void *userdata) {
                     snd_pcm_start(u->pcm_handle);
 
                     pa_smoother_resume(u->smoother, pa_rtclock_now(), TRUE);
+
+                    u->first = FALSE;
                 }
 
                 update_smoother(u);
@@ -1457,7 +1459,6 @@ static void thread_func(void *userdata) {
                 pa_rtpoll_set_timer_relative(u->rtpoll, PA_MIN(sleep_usec, cusec));
             }
 
-            u->first = FALSE;
             u->after_rewind = FALSE;
 
         } else if (u->use_tsched)

-- 
hooks/post-receive
PulseAudio Sound Server



More information about the pulseaudio-commits mailing list