[pulseaudio-commits] [SCM] PulseAudio Sound Server branch, master-tx, updated. v0.9.13-223-g2ecf4c3

Lennart Poettering gitmailer-noreply at 0pointer.de
Mon Jan 12 11:02:33 PST 2009


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 master-tx branch has been updated
      from  cf3abcdbdaf018cbc2d7e507df1e45da34d86a6f (commit)

- Log -----------------------------------------------------------------
2ecf4c3... Merge commit 'origin/master-tx'
f67066b... Port sine modules to pa_memchunk_sine()
b8e6aae... add new API function pa_memchunk_sine()
949de81... Extend command name lookup tables to cover complete protocol
aff7243... Fix suspending of all sinks/sources
d94d39d... read base volume only in proto 15
b9e96e0... for record streams fill in the latency as the fragsize
947a828... fix version check
b6804ee... Make sure we don't drop any data on the client side
8a3dc57... make module-sine-source actually work
4e8ada5... show maximum usable slot size
c850aa0... Add new pa_reduce() and pa_gcd() functions
98049fb... make things compile again
7b52840... add a few missing parens
5daf141... drop a few warning options, add a few new ones
c2002dc... Merge branch 'master' of ssh://rootserver/home/lennart/git/public/pulseaudio
9fc726c... Add new test source module-sine-source
e5c0938... A few minor cleanups and updates
aff7768... Add new debuuging API pa_memchunk_dump_to_file()
2ff20ce... Rework handling of the PA_SINK_LATENCY/PA_SOURCE_LATENCY flags
fb4c111... Implement base_volume for ALSA sinks/sources
6130c5c... Add "base volume" field to sinks/sources
3e3c103... Add APIs to pass pa_volume_t fields in a tagstruct
6342053... Add new API functions pa_volume_snprint() and pa_sw_volume_snprint_dB()
-----------------------------------------------------------------------

Summary of changes:
 configure.ac                                       |    2 +-
 src/Makefile.am                                    |    6 +
 src/map-file                                       |    2 +
 src/modules/module-alsa-sink.c                     |   43 +++--
 src/modules/module-alsa-source.c                   |   44 +++--
 src/modules/module-null-sink.c                     |   18 +-
 src/modules/module-pipe-source.c                   |    5 +-
 .../{module-pipe-source.c => module-sine-source.c} |  229 +++++++++-----------
 src/modules/module-sine.c                          |   58 ++---
 src/pulse/introspect.c                             |   10 +-
 src/pulse/introspect.h                             |    2 +
 src/pulse/volume.c                                 |   43 ++++-
 src/pulse/volume.h                                 |   20 ++
 src/pulsecore/cli-text.c                           |   30 +++-
 src/pulsecore/core-util.c                          |   24 ++
 src/pulsecore/core-util.h                          |    3 +
 src/pulsecore/endianmacros.h                       |   18 +-
 src/pulsecore/memblock.c                           |    5 +-
 src/pulsecore/pdispatch.c                          |   92 +++++++-
 src/pulsecore/protocol-native.c                    |   13 +-
 src/pulsecore/sample-util.c                        |   64 ++++++-
 src/pulsecore/sample-util.h                        |    4 +
 src/pulsecore/sink.c                               |   12 +-
 src/pulsecore/sink.h                               |    2 +
 src/pulsecore/source.c                             |    4 +
 src/pulsecore/source.h                             |    2 +
 src/pulsecore/tagstruct.c                          |   38 ++++
 src/pulsecore/tagstruct.h                          |    6 +-
 src/utils/pacat.c                                  |   18 +-
 29 files changed, 566 insertions(+), 251 deletions(-)
 copy src/modules/{module-pipe-source.c => module-sine-source.c} (54%)

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

commit 6342053b34ab2f8addd2ed74cd965ec794ee50d4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Dec 24 00:45:06 2008 +0100

    Add new API functions pa_volume_snprint() and pa_sw_volume_snprint_dB()

diff --git a/src/map-file b/src/map-file
index ca523b9..82b9c38 100644
--- a/src/map-file
+++ b/src/map-file
@@ -234,6 +234,7 @@ pa_sw_volume_divide;
 pa_sw_volume_from_dB;
 pa_sw_volume_from_linear;
 pa_sw_volume_multiply;
+pa_sw_volume_snprint_dB;
 pa_sw_volume_to_dB;
 pa_sw_volume_to_linear;
 pa_threaded_mainloop_accept;
@@ -259,6 +260,7 @@ pa_usec_to_bytes;
 pa_utf8_filter;
 pa_utf8_to_locale;
 pa_utf8_valid;
+pa_volume_snprint;
 pa_xfree;
 pa_xmalloc;
 pa_xmalloc0;
diff --git a/src/pulse/volume.c b/src/pulse/volume.c
index 99a85f4..ace5c4d 100644
--- a/src/pulse/volume.c
+++ b/src/pulse/volume.c
@@ -179,6 +179,21 @@ char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c) {
     return s;
 }
 
+char *pa_volume_snprint(char *s, size_t l, pa_volume_t v) {
+    pa_assert(s);
+    pa_assert(l > 0);
+
+    pa_init_i18n();
+
+    if (v == (pa_volume_t) -1) {
+        pa_snprintf(s, l, _("(invalid)"));
+        return s;
+    }
+
+    pa_snprintf(s, l, "%3u%%", (v*100)/PA_VOLUME_NORM);
+    return s;
+}
+
 char *pa_sw_cvolume_snprint_dB(char *s, size_t l, const pa_cvolume *c) {
     unsigned channel;
     pa_bool_t first = TRUE;
@@ -198,10 +213,12 @@ char *pa_sw_cvolume_snprint_dB(char *s, size_t l, const pa_cvolume *c) {
     *(e = s) = 0;
 
     for (channel = 0; channel < c->channels && l > 1; channel++) {
+        double f = pa_sw_volume_to_dB(c->values[channel]);
+
         l -= pa_snprintf(e, l, "%s%u: %0.2f dB",
-                      first ? "" : " ",
-                      channel,
-                      pa_sw_volume_to_dB(c->values[channel]));
+                         first ? "" : " ",
+                         channel,
+                         isinf(f) < 0 || f <= -USER_DECIBEL_RANGE ? -INFINITY : f);
 
         e = strchr(e, 0);
         first = FALSE;
@@ -210,6 +227,26 @@ char *pa_sw_cvolume_snprint_dB(char *s, size_t l, const pa_cvolume *c) {
     return s;
 }
 
+char *pa_sw_volume_snprint_dB(char *s, size_t l, pa_volume_t v) {
+    double f;
+
+    pa_assert(s);
+    pa_assert(l > 0);
+
+    pa_init_i18n();
+
+    if (v == (pa_volume_t) -1) {
+        pa_snprintf(s, l, _("(invalid)"));
+        return s;
+    }
+
+    f = pa_sw_volume_to_dB(v);
+    pa_snprintf(s, l, "%0.2f dB",
+                isinf(f) < 0 || f <= -USER_DECIBEL_RANGE ?  -INFINITY : f);
+
+    return s;
+}
+
 /** Return non-zero if the volume of all channels is equal to the specified value */
 int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v) {
     unsigned c;
diff --git a/src/pulse/volume.h b/src/pulse/volume.h
index 75051af..5815c90 100644
--- a/src/pulse/volume.h
+++ b/src/pulse/volume.h
@@ -150,6 +150,26 @@ char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c);
 /** Pretty print a volume structure but show dB values. \since 0.9.13 */
 char *pa_sw_cvolume_snprint_dB(char *s, size_t l, const pa_cvolume *c);
 
+/** Maximum length of the strings returned by
+ * pa_volume_snprint(). Please note that this value can change with
+ * any release without warning and without being considered API or ABI
+ * breakage. You should not use this definition anywhere where it
+ * might become part of an ABI. \since 0.9.14 */
+#define PA_VOLUME_SNPRINT_MAX 10
+
+/** Pretty print a volume \since 0.9.14 */
+char *pa_volume_snprint(char *s, size_t l, pa_volume_t v);
+
+/** Maximum length of the strings returned by
+ * pa_volume_snprint_dB(). Please note that this value can change with
+ * any release without warning and without being considered API or ABI
+ * breakage. You should not use this definition anywhere where it
+ * might become part of an ABI. \since 0.9.14 */
+#define PA_SW_VOLUME_SNPRINT_DB_MAX 10
+
+/** Pretty print a volume but show dB values. \since 0.9.14 */
+char *pa_sw_volume_snprint_dB(char *s, size_t l, pa_volume_t v);
+
 /** Return the average volume of all channels */
 pa_volume_t pa_cvolume_avg(const pa_cvolume *a) PA_GCC_PURE;
 

commit 3e3c103ed9e9e4782c12380c3735ab9aaf2611c8
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Dec 24 00:46:02 2008 +0100

    Add APIs to pass pa_volume_t fields in a tagstruct

diff --git a/src/pulsecore/tagstruct.c b/src/pulsecore/tagstruct.c
index 62a3014..330b759 100644
--- a/src/pulsecore/tagstruct.c
+++ b/src/pulsecore/tagstruct.c
@@ -254,6 +254,17 @@ void pa_tagstruct_put_cvolume(pa_tagstruct *t, const pa_cvolume *cvolume) {
     }
 }
 
+void pa_tagstruct_put_volume(pa_tagstruct *t, pa_volume_t vol) {
+    uint32_t u;
+    pa_assert(t);
+
+    extend(t, 5);
+    t->data[t->length] = PA_TAG_VOLUME;
+    u = htonl((uint32_t) vol);
+    memcpy(t->data+t->length+1, &u, 4);
+    t->length += 5;
+}
+
 void pa_tagstruct_put_proplist(pa_tagstruct *t, pa_proplist *p) {
     void *state = NULL;
     pa_assert(t);
@@ -555,6 +566,25 @@ int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *cvolume) {
     return 0;
 }
 
+int pa_tagstruct_get_volume(pa_tagstruct*t, pa_volume_t *vol) {
+    uint32_t u;
+
+    pa_assert(t);
+    pa_assert(vol);
+
+    if (t->rindex+5 > t->length)
+        return -1;
+
+    if (t->data[t->rindex] != PA_TAG_VOLUME)
+        return -1;
+
+    memcpy(&u, t->data+t->rindex+1, 4);
+    *vol = (pa_volume_t) ntohl(u);
+
+    t->rindex += 5;
+    return 0;
+}
+
 int pa_tagstruct_get_proplist(pa_tagstruct *t, pa_proplist *p) {
     size_t saved_rindex;
 
@@ -663,6 +693,10 @@ void pa_tagstruct_put(pa_tagstruct *t, ...) {
                 pa_tagstruct_put_cvolume(t, va_arg(va, pa_cvolume *));
                 break;
 
+            case PA_TAG_VOLUME:
+                pa_tagstruct_put_volume(t, va_arg(va, pa_volume_t));
+                break;
+
             case PA_TAG_PROPLIST:
                 pa_tagstruct_put_proplist(t, va_arg(va, pa_proplist *));
                 break;
@@ -738,6 +772,10 @@ int pa_tagstruct_get(pa_tagstruct *t, ...) {
                 ret = pa_tagstruct_get_cvolume(t, va_arg(va, pa_cvolume *));
                 break;
 
+            case PA_TAG_VOLUME:
+                ret = pa_tagstruct_get_volume(t, va_arg(va, pa_volume_t *));
+                break;
+
             case PA_TAG_PROPLIST:
                 ret = pa_tagstruct_get_proplist(t, va_arg(va, pa_proplist *));
                 break;
diff --git a/src/pulsecore/tagstruct.h b/src/pulsecore/tagstruct.h
index e7d0705..19288ee 100644
--- a/src/pulsecore/tagstruct.h
+++ b/src/pulsecore/tagstruct.h
@@ -54,7 +54,8 @@ enum {
     PA_TAG_USEC = 'U'  /* 64bit unsigned */,
     PA_TAG_CHANNEL_MAP = 'm',
     PA_TAG_CVOLUME = 'v',
-    PA_TAG_PROPLIST = 'P'
+    PA_TAG_PROPLIST = 'P',
+    PA_TAG_VOLUME = 'V'
 };
 
 pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length);
@@ -79,6 +80,7 @@ void pa_tagstruct_put_usec(pa_tagstruct*t, pa_usec_t u);
 void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map);
 void pa_tagstruct_put_cvolume(pa_tagstruct *t, const pa_cvolume *cvolume);
 void pa_tagstruct_put_proplist(pa_tagstruct *t, pa_proplist *p);
+void pa_tagstruct_put_volume(pa_tagstruct *t, pa_volume_t volume);
 
 int pa_tagstruct_get(pa_tagstruct *t, ...);
 
@@ -95,6 +97,6 @@ int pa_tagstruct_get_usec(pa_tagstruct*t, pa_usec_t *u);
 int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map);
 int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *v);
 int pa_tagstruct_get_proplist(pa_tagstruct *t, pa_proplist *p);
-
+int pa_tagstruct_get_volume(pa_tagstruct *t, pa_volume_t *v);
 
 #endif

commit 6130c5c11b0b76cc779b52636c5635729fedf89a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Dec 24 00:49:43 2008 +0100

    Add "base volume" field to sinks/sources

diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c
index 3809158..5b905b7 100644
--- a/src/pulse/introspect.c
+++ b/src/pulse/introspect.c
@@ -154,6 +154,7 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, u
 
             memset(&i, 0, sizeof(i));
             i.proplist = pa_proplist_new();
+            i.base_volume = PA_VOLUME_NORM;
 
             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
                 pa_tagstruct_gets(t, &i.name) < 0 ||
@@ -170,7 +171,9 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, u
                 pa_tagstruct_getu32(t, &flags) < 0 ||
                 (o->context->version >= 13 &&
                  (pa_tagstruct_get_proplist(t, i.proplist) < 0 ||
-                  pa_tagstruct_get_usec(t, &i.configured_latency) < 0))) {
+                  pa_tagstruct_get_usec(t, &i.configured_latency) < 0)) ||
+                (o->context->version >= 14 &&
+                 pa_tagstruct_get_volume(t, &i.base_volume) < 0)) {
 
                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
                 pa_proplist_free(i.proplist);
@@ -275,6 +278,7 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command,
 
             memset(&i, 0, sizeof(i));
             i.proplist = pa_proplist_new();
+            i.base_volume = PA_VOLUME_NORM;
 
             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
                 pa_tagstruct_gets(t, &i.name) < 0 ||
@@ -291,7 +295,9 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command,
                 pa_tagstruct_getu32(t, &flags) < 0 ||
                 (o->context->version >= 13 &&
                  (pa_tagstruct_get_proplist(t, i.proplist) < 0 ||
-                  pa_tagstruct_get_usec(t, &i.configured_latency) < 0))) {
+                  pa_tagstruct_get_usec(t, &i.configured_latency) < 0)) ||
+                (o->context->version >= 14 &&
+                 pa_tagstruct_get_volume(t, &i.base_volume) < 0)) {
 
                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
                 pa_proplist_free(i.proplist);
diff --git a/src/pulse/introspect.h b/src/pulse/introspect.h
index 087bd9f..b409cad 100644
--- a/src/pulse/introspect.h
+++ b/src/pulse/introspect.h
@@ -231,6 +231,7 @@ typedef struct pa_sink_info {
     pa_sink_flags_t flags;             /**< Flags */
     pa_proplist *proplist;             /**< Property list \since 0.9.11 */
     pa_usec_t configured_latency;      /**< The latency this device has been configured to. \since 0.9.11 */
+    pa_volume_t base_volume;           /**< Some kind of "base" volume that refers to unamplified/unattenuated volume in the context of the output device. \since 0.9.14 */
 } pa_sink_info;
 
 /** Callback prototype for pa_context_get_sink_info_by_name() and friends */
@@ -286,6 +287,7 @@ typedef struct pa_source_info {
     pa_source_flags_t flags;            /**< Flags */
     pa_proplist *proplist;              /**< Property list \since 0.9.11 */
     pa_usec_t configured_latency;       /**< The latency this device has been configured to. \since 0.9.11 */
+    pa_volume_t base_volume;           /**< Some kind of "base" volume that refers to unamplified/unattenuated volume in the context of the input device. \since 0.9.14 */
 } pa_source_info;
 
 /** Callback prototype for pa_context_get_source_info_by_name() and friends */
diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c
index 7bbc266..362a979 100644
--- a/src/pulsecore/cli-text.c
+++ b/src/pulsecore/cli-text.c
@@ -115,7 +115,12 @@ char *pa_sink_list_to_string(pa_core *c) {
     pa_strbuf_printf(s, "%u sink(s) available.\n", pa_idxset_size(c->sinks));
 
     for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx)) {
-        char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t;
+        char ss[PA_SAMPLE_SPEC_SNPRINT_MAX],
+            cv[PA_CVOLUME_SNPRINT_MAX],
+            cvdb[PA_SW_CVOLUME_SNPRINT_DB_MAX],
+            v[PA_VOLUME_SNPRINT_MAX],
+            vdb[PA_SW_VOLUME_SNPRINT_DB_MAX],
+            cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t;
         pa_usec_t min_latency, max_latency;
 
         pa_sink_get_latency_range(sink, &min_latency, &max_latency);
@@ -127,7 +132,8 @@ char *pa_sink_list_to_string(pa_core *c) {
             "\tdriver: <%s>\n"
             "\tflags: %s%s%s%s%s%s\n"
             "\tstate: %s\n"
-            "\tvolume: %s\n"
+            "\tvolume: %s%s%s\n"
+            "\tbase volume: %s%s%s\n"
             "\tmuted: %s\n"
             "\tcurrent latency: %0.2f ms\n"
             "\tconfigured latency: %0.2f ms; range is %0.2f .. %0.2f ms\n"
@@ -150,6 +156,11 @@ char *pa_sink_list_to_string(pa_core *c) {
             sink->flags & PA_SINK_LATENCY ? "LATENCY " : "",
             state_table[pa_sink_get_state(sink)],
             pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink, FALSE)),
+            sink->flags & PA_SINK_DECIBEL_VOLUME ? "\n\t        " : "",
+            sink->flags & PA_SINK_DECIBEL_VOLUME ? pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), pa_sink_get_volume(sink, FALSE)) : "",
+            pa_volume_snprint(v, sizeof(v), sink->base_volume),
+            sink->flags & PA_SINK_DECIBEL_VOLUME ? "\n\t             " : "",
+            sink->flags & PA_SINK_DECIBEL_VOLUME ? pa_sw_volume_snprint_dB(vdb, sizeof(vdb), sink->base_volume) : "",
             pa_yes_no(pa_sink_get_mute(sink, FALSE)),
             (double) pa_sink_get_latency(sink) / (double) PA_USEC_PER_MSEC,
             (double) pa_sink_get_requested_latency(sink) / (double) PA_USEC_PER_MSEC,
@@ -192,7 +203,12 @@ char *pa_source_list_to_string(pa_core *c) {
     pa_strbuf_printf(s, "%u source(s) available.\n", pa_idxset_size(c->sources));
 
     for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) {
-        char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], *t;
+        char ss[PA_SAMPLE_SPEC_SNPRINT_MAX],
+            cv[PA_CVOLUME_SNPRINT_MAX],
+            cvdb[PA_SW_CVOLUME_SNPRINT_DB_MAX],
+            v[PA_VOLUME_SNPRINT_MAX],
+            vdb[PA_SW_VOLUME_SNPRINT_DB_MAX],
+            cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t;
         pa_usec_t min_latency, max_latency;
 
         pa_source_get_latency_range(source, &min_latency, &max_latency);
@@ -204,7 +220,8 @@ char *pa_source_list_to_string(pa_core *c) {
             "\tdriver: <%s>\n"
             "\tflags: %s%s%s%s%s%s\n"
             "\tstate: %s\n"
-            "\tvolume: %s\n"
+            "\tvolume: %s%s%s\n"
+            "\tbase volume: %s%s%s\n"
             "\tmuted: %s\n"
             "\tcurrent latency: %0.2f ms\n"
             "\tconfigured latency: %0.2f ms; range is %0.2f .. %0.2f ms\n"
@@ -225,6 +242,11 @@ char *pa_source_list_to_string(pa_core *c) {
             source->flags & PA_SOURCE_LATENCY ? "LATENCY " : "",
             state_table[pa_source_get_state(source)],
             pa_cvolume_snprint(cv, sizeof(cv), pa_source_get_volume(source, FALSE)),
+            source->flags & PA_SOURCE_DECIBEL_VOLUME ? "\n\t        " : "",
+            source->flags & PA_SOURCE_DECIBEL_VOLUME ? pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), pa_source_get_volume(source, FALSE)) : "",
+            pa_volume_snprint(v, sizeof(v), source->base_volume),
+            source->flags & PA_SOURCE_DECIBEL_VOLUME ? "\n\t             " : "",
+            source->flags & PA_SOURCE_DECIBEL_VOLUME ? pa_sw_volume_snprint_dB(vdb, sizeof(vdb), source->base_volume) : "",
             pa_yes_no(pa_source_get_mute(source, FALSE)),
             (double) pa_source_get_latency(source) / PA_USEC_PER_MSEC,
             (double) pa_source_get_requested_latency(source) / PA_USEC_PER_MSEC,
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 56e86cb..fa3e3f8 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -2677,6 +2677,9 @@ static void sink_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sin
         pa_tagstruct_put_proplist(t, sink->proplist);
         pa_tagstruct_put_usec(t, pa_sink_get_requested_latency(sink));
     }
+
+    if (c->version >= 14)
+        pa_tagstruct_put_volume(t, sink->base_volume);
 }
 
 static void source_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_source *source) {
@@ -2708,8 +2711,10 @@ static void source_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_s
         pa_tagstruct_put_proplist(t, source->proplist);
         pa_tagstruct_put_usec(t, pa_source_get_requested_latency(source));
     }
-}
 
+    if (c->version >= 14)
+        pa_tagstruct_put_volume(t, source->base_volume);
+}
 
 static void client_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_client *client) {
     pa_assert(t);
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 1580cf2..3738776 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -191,6 +191,7 @@ pa_sink* pa_sink_new(
     s->n_corked = 0;
 
     s->volume = data->volume;
+    s->base_volume = PA_VOLUME_NORM;
     s->muted = data->muted;
     s->refresh_volume = s->refresh_muted = FALSE;
 
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index c5a7321..254be3b 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -81,6 +81,8 @@ struct pa_sink {
     pa_cvolume volume;
     pa_bool_t muted;
 
+    pa_volume_t base_volume;  /* shall be constant */
+
     pa_bool_t refresh_volume:1;
     pa_bool_t refresh_muted:1;
 
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index f113e29..5538ced 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -185,6 +185,7 @@ pa_source* pa_source_new(
     s->volume = data->volume;
     s->muted = data->muted;
     s->refresh_volume = s->refresh_muted = FALSE;
+    s->base_volume = PA_VOLUME_NORM;
 
     reset_callbacks(s);
     s->userdata = NULL;
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index aaf904b..b93e4ad 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -84,6 +84,8 @@ struct pa_source {
     pa_cvolume volume;
     pa_bool_t muted;
 
+    pa_volume_t base_volume; /* shall be constant */
+
     pa_bool_t refresh_volume:1;
     pa_bool_t refresh_muted:1;
 

commit fb4c111d18932ca5643a44ad589a1fff5888260f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Dec 24 00:57:37 2008 +0100

    Implement base_volume for ALSA sinks/sources

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 6dea172..97ddbd8 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -1506,28 +1506,35 @@ int pa__init(pa_module*m) {
                 suitable = TRUE;
             }
 
-            if (snd_mixer_selem_get_playback_dB_range(u->mixer_elem, &u->hw_dB_min, &u->hw_dB_max) < 0)
-                pa_log_info("Mixer doesn't support dB information.");
-            else {
+            if (suitable) {
+                if (snd_mixer_selem_get_playback_dB_range(u->mixer_elem, &u->hw_dB_min, &u->hw_dB_max) < 0)
+                    pa_log_info("Mixer doesn't support dB information.");
+                else {
 #ifdef HAVE_VALGRIND_MEMCHECK_H
-                VALGRIND_MAKE_MEM_DEFINED(&u->hw_dB_min, sizeof(u->hw_dB_min));
-                VALGRIND_MAKE_MEM_DEFINED(&u->hw_dB_max, sizeof(u->hw_dB_max));
+                    VALGRIND_MAKE_MEM_DEFINED(&u->hw_dB_min, sizeof(u->hw_dB_min));
+                    VALGRIND_MAKE_MEM_DEFINED(&u->hw_dB_max, sizeof(u->hw_dB_max));
 #endif
 
-                if (u->hw_dB_min >= u->hw_dB_max)
-                    pa_log_warn("Your kernel driver is broken: it reports a volume range from %0.2f dB to %0.2f dB which makes no sense.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0);
-                else {
-                    pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0);
-                    u->hw_dB_supported = TRUE;
+                    if (u->hw_dB_min >= u->hw_dB_max)
+                        pa_log_warn("Your kernel driver is broken: it reports a volume range from %0.2f dB to %0.2f dB which makes no sense.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0);
+                    else {
+                        pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0);
+                        u->hw_dB_supported = TRUE;
+
+                        if (u->hw_dB_max > 0) {
+                            u->sink->base_volume = pa_sw_volume_from_dB(- (double) u->hw_dB_max/100.0);
+                            pa_log_info("Fixing base volume to %0.2f dB", pa_sw_volume_to_dB(u->sink->base_volume));
+                        } else
+                            pa_log_info("No particular base volume set, fixing to 0 dB");
+                    }
                 }
-            }
 
-            if (suitable &&
-                !u->hw_dB_supported &&
-                u->hw_volume_max - u->hw_volume_min < 3) {
+                if (!u->hw_dB_supported &&
+                    u->hw_volume_max - u->hw_volume_min < 3) {
 
-                pa_log_info("Device doesn't do dB volume and has less than 4 volume levels. Falling back to software volume control.");
-                suitable = FALSE;
+                    pa_log_info("Device doesn't do dB volume and has less than 4 volume levels. Falling back to software volume control.");
+                    suitable = FALSE;
+                }
             }
 
             if (suitable) {
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index f796ef1..312e56b 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -1328,28 +1328,36 @@ int pa__init(pa_module*m) {
                 suitable = TRUE;
             }
 
-            if (snd_mixer_selem_get_capture_dB_range(u->mixer_elem, &u->hw_dB_min, &u->hw_dB_max) < 0)
-                pa_log_info("Mixer doesn't support dB information.");
-            else {
+            if (suitable) {
+                if (snd_mixer_selem_get_capture_dB_range(u->mixer_elem, &u->hw_dB_min, &u->hw_dB_max) < 0)
+                    pa_log_info("Mixer doesn't support dB information.");
+                else {
 #ifdef HAVE_VALGRIND_MEMCHECK_H
-                VALGRIND_MAKE_MEM_DEFINED(&u->hw_dB_min, sizeof(u->hw_dB_min));
-                VALGRIND_MAKE_MEM_DEFINED(&u->hw_dB_max, sizeof(u->hw_dB_max));
+                    VALGRIND_MAKE_MEM_DEFINED(&u->hw_dB_min, sizeof(u->hw_dB_min));
+                    VALGRIND_MAKE_MEM_DEFINED(&u->hw_dB_max, sizeof(u->hw_dB_max));
 #endif
 
-                if (u->hw_dB_min >= u->hw_dB_max)
-                    pa_log_warn("Your kernel driver is broken: it reports a volume range from %0.2f dB to %0.2f dB which makes no sense.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0);
-                else {
-                    pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0);
-                    u->hw_dB_supported = TRUE;
+                    if (u->hw_dB_min >= u->hw_dB_max)
+                        pa_log_warn("Your kernel driver is broken: it reports a volume range from %0.2f dB to %0.2f dB which makes no sense.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0);
+                    else {
+                        pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0);
+                        u->hw_dB_supported = TRUE;
+
+                        if (u->hw_dB_max > 0) {
+                            u->source->base_volume = pa_sw_volume_from_dB(- (double) u->hw_dB_max/100.0);
+                            pa_log_info("Fixing base volume to %0.2f dB", pa_sw_volume_to_dB(u->source->base_volume));
+                        } else
+                            pa_log_info("No particular base volume set, fixing to 0 dB");
+
+                    }
                 }
-            }
 
-            if (suitable &&
-                !u->hw_dB_supported &&
-                u->hw_volume_max - u->hw_volume_min < 3) {
+                if (!u->hw_dB_supported &&
+                    u->hw_volume_max - u->hw_volume_min < 3) {
 
-                pa_log_info("Device has less than 4 volume levels. Falling back to software volume control.");
-                suitable = FALSE;
+                    pa_log_info("Device has less than 4 volume levels. Falling back to software volume control.");
+                    suitable = FALSE;
+                }
             }
 
             if (suitable) {

commit 2ff20ceccb7334b0d491fec119a324cda1045803
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Dec 24 00:58:34 2008 +0100

    Rework handling of the PA_SINK_LATENCY/PA_SOURCE_LATENCY flags

diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 3738776..a4d993c 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -240,7 +240,7 @@ pa_sink* pa_sink_new(
     pa_proplist_setf(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Monitor of %s", dn ? dn : s->name);
     pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_CLASS, "monitor");
 
-    s->monitor_source = pa_source_new(core, &source_data, 0);
+    s->monitor_source = pa_source_new(core, &source_data, PA_SOURCE_LATENCY);
 
     pa_source_new_data_done(&source_data);
 
@@ -836,6 +836,9 @@ pa_usec_t pa_sink_get_latency(pa_sink *s) {
     if (!PA_SINK_IS_OPENED(s->state))
         return 0;
 
+    if (!(s->flags & PA_SINK_LATENCY))
+        return 0;
+
     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) == 0);
 
     return usec;
@@ -1162,7 +1165,8 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
                 size_t sink_nbytes, total_nbytes;
 
                 /* Get the latency of the sink */
-                if (PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
+                if (!(s->flags & PA_SINK_LATENCY) ||
+                    PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
                     usec = 0;
 
                 sink_nbytes = pa_usec_to_bytes(usec, &s->sample_spec);
@@ -1221,7 +1225,8 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
                 size_t nbytes;
 
                 /* Get the latency of the sink */
-                if (PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
+                if (!(s->flags & PA_SINK_LATENCY) ||
+                    PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
                     usec = 0;
 
                 nbytes = pa_usec_to_bytes(usec, &s->sample_spec);
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 5538ced..815ec27 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -501,6 +501,9 @@ pa_usec_t pa_source_get_latency(pa_source *s) {
     if (!PA_SOURCE_IS_OPENED(s->state))
         return 0;
 
+    if (!(s->flags & PA_SOURCE_LATENCY))
+        return 0;
+
     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY, &usec, 0, NULL) == 0);
 
     return usec;

commit aff7768fb1076b53bc8416fdbdcc454e4b52ec41
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 8 21:12:03 2009 +0100

    Add new debuuging API pa_memchunk_dump_to_file()

diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index 9f0f795..414c1c8 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -27,6 +27,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
+#include <stdio.h>
 
 #include <liboil/liboilfuncs.h>
 #include <liboil/liboil.h>
@@ -987,3 +988,29 @@ size_t pa_usec_to_bytes_round_up(pa_usec_t t, const pa_sample_spec *spec) {
 
     return (size_t) u;
 }
+
+void pa_memchunk_dump_to_file(pa_memchunk *c, const char *fn) {
+    FILE *f;
+    void *p;
+
+    pa_assert(c);
+    pa_assert(fn);
+
+    /* Only for debugging purposes */
+
+    f = fopen(fn, "a");
+
+    if (!f) {
+        pa_log_warn("Failed to open '%s': %s", fn, pa_cstrerror(errno));
+        return;
+    }
+
+    p = pa_memblock_acquire(c->memblock);
+
+    if (fwrite((uint8_t*) p + c->index, 1, c->length, f) != c->length)
+        pa_log_warn("Failed to write to '%s': %s", fn, pa_cstrerror(errno));
+
+    pa_memblock_release(c->memblock);
+
+    fclose(f);
+}
diff --git a/src/pulsecore/sample-util.h b/src/pulsecore/sample-util.h
index 2fe2c81..36d19e4 100644
--- a/src/pulsecore/sample-util.h
+++ b/src/pulsecore/sample-util.h
@@ -81,4 +81,6 @@ void pa_sample_clamp(pa_sample_format_t format, void *dst, size_t dstr, const vo
 pa_usec_t pa_bytes_to_usec_round_up(uint64_t length, const pa_sample_spec *spec);
 size_t pa_usec_to_bytes_round_up(pa_usec_t t, const pa_sample_spec *spec);
 
+void pa_memchunk_dump_to_file(pa_memchunk *c, const char *fn);
+
 #endif

commit e5c093897e62245cad56492298f9b9a7ff739351
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 8 21:13:18 2009 +0100

    A few minor cleanups and updates

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 97ddbd8..5b8e64b 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -599,9 +599,9 @@ static int update_sw_params(struct userdata *u) {
             u->hwbuf_unused_frames = (snd_pcm_sframes_t)
                 (PA_LIKELY(b < u->hwbuf_size) ?
                  ((u->hwbuf_size - b) / u->frame_size) : 0);
-
-            fix_tsched_watermark(u);
         }
+
+        fix_tsched_watermark(u);
     }
 
     pa_log_debug("hwbuf_unused_frames=%lu", (unsigned long) u->hwbuf_unused_frames);
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 312e56b..3f0bf7c 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -545,9 +545,9 @@ static int update_sw_params(struct userdata *u) {
             u->hwbuf_unused_frames = (snd_pcm_sframes_t)
                 (PA_LIKELY(b < u->hwbuf_size) ?
                  ((u->hwbuf_size - b) / u->frame_size) : 0);
-
-            fix_tsched_watermark(u);
         }
+
+        fix_tsched_watermark(u);
     }
 
     pa_log_debug("hwbuf_unused_frames=%lu", (unsigned long) u->hwbuf_unused_frames);
diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index 470c622..daf9767 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -73,8 +73,6 @@ struct userdata {
     pa_thread_mq thread_mq;
     pa_rtpoll *rtpoll;
 
-    size_t block_size;
-
     pa_usec_t block_usec;
     pa_usec_t timestamp;
 };
@@ -89,7 +87,13 @@ static const char* const valid_modargs[] = {
     NULL
 };
 
-static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
+static int sink_process_msg(
+        pa_msgobject *o,
+        int code,
+        void *data,
+        int64_t offset,
+        pa_memchunk *chunk) {
+
     struct userdata *u = PA_SINK(o)->userdata;
 
     switch (code) {
@@ -104,7 +108,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             pa_usec_t now;
 
             now = pa_rtclock_usec();
-            *((pa_usec_t*) data) = u->timestamp > now ? u->timestamp - now : 0;
+            *((pa_usec_t*) data) = u->timestamp > now ? u->timestamp - now : 0ULL;
 
             return 0;
         }
@@ -117,10 +121,12 @@ static void sink_update_requested_latency_cb(pa_sink *s) {
     struct userdata *u;
 
     pa_sink_assert_ref(s);
-    u = s->userdata;
-    pa_assert(u);
+    pa_assert_se(u = s->userdata);
 
     u->block_usec = pa_sink_get_requested_latency_within_thread(s);
+
+    if (u->block_usec == (pa_usec_t) -1)
+        u->block_usec = s->thread_info.max_latency;
 }
 
 static void process_rewind(struct userdata *u, pa_usec_t now) {
diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c
index e6437a0..77310ca 100644
--- a/src/modules/module-pipe-source.c
+++ b/src/modules/module-pipe-source.c
@@ -226,10 +226,9 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
-    u = pa_xnew0(struct userdata, 1);
+    m->userdata = u = pa_xnew0(struct userdata, 1);
     u->core = m->core;
     u->module = m;
-    m->userdata = u;
     pa_memchunk_reset(&u->memchunk);
     u->rtpoll = pa_rtpoll_new();
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
@@ -264,7 +263,7 @@ int pa__init(pa_module*m) {
     pa_source_new_data_set_sample_spec(&data, &ss);
     pa_source_new_data_set_channel_map(&data, &map);
 
-    u->source = pa_source_new(m->core, &data, 0);
+    u->source = pa_source_new(m->core, &data, PA_SOURCE_LATENCY);
     pa_source_new_data_done(&data);
 
     if (!u->source) {
diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c
index 21565cc..4ee4688 100644
--- a/src/modules/module-sine.c
+++ b/src/modules/module-sine.c
@@ -41,7 +41,9 @@ PA_MODULE_AUTHOR("Lennart Poettering");
 PA_MODULE_DESCRIPTION("Sine wave generator");
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(FALSE);
-PA_MODULE_USAGE("sink=<sink to connect to> frequency=<frequency in Hz>");
+PA_MODULE_USAGE(
+        "sink=<sink to connect to> "
+        "frequency=<frequency in Hz>");
 
 struct userdata {
     pa_core *core;

commit 9fc726c6d780f63610647014efeffab3a97b8dac
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 8 21:17:58 2009 +0100

    Add new test source module-sine-source

diff --git a/src/Makefile.am b/src/Makefile.am
index b9d0083..bde51eb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -809,6 +809,7 @@ modlibexec_LTLIBRARIES += \
 		module-cli-protocol-tcp.la \
 		module-simple-protocol-tcp.la \
 		module-null-sink.la \
+		module-sine-source.la \
 		module-detect.la \
 		module-volume-restore.la \
 		module-device-restore.la \
@@ -986,6 +987,7 @@ SYMDEF_FILES = \
 		modules/module-tunnel-sink-symdef.h \
 		modules/module-tunnel-source-symdef.h \
 		modules/module-null-sink-symdef.h \
+		modules/module-sine-source-symdef.h \
 		modules/module-esound-sink-symdef.h \
 		modules/module-zeroconf-publish-symdef.h \
 		modules/module-zeroconf-discover-symdef.h \
@@ -1141,6 +1143,10 @@ module_null_sink_la_SOURCES = modules/module-null-sink.c
 module_null_sink_la_LDFLAGS = -module -avoid-version
 module_null_sink_la_LIBADD = $(AM_LIBADD) libpulsecore- at PA_MAJORMINORMICRO@.la libpulsecommon- at PA_MAJORMINORMICRO@.la libpulse.la
 
+module_sine_source_la_SOURCES = modules/module-sine-source.c
+module_sine_source_la_LDFLAGS = -module -avoid-version
+module_sine_source_la_LIBADD = $(AM_LIBADD) libpulsecore- at PA_MAJORMINORMICRO@.la libpulsecommon- at PA_MAJORMINORMICRO@.la libpulse.la
+
 # Couplings
 
 module_combine_la_SOURCES = modules/module-combine.c
diff --git a/src/modules/module-sine-source.c b/src/modules/module-sine-source.c
new file mode 100644
index 0000000..dcc3416
--- /dev/null
+++ b/src/modules/module-sine-source.c
@@ -0,0 +1,335 @@
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2008 Lennart Poettering
+
+  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 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.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+
+#include <pulse/xmalloc.h>
+#include <pulse/timeval.h>
+
+#include <pulsecore/core-error.h>
+#include <pulsecore/source.h>
+#include <pulsecore/module.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/modargs.h>
+#include <pulsecore/log.h>
+#include <pulsecore/thread.h>
+#include <pulsecore/thread-mq.h>
+#include <pulsecore/rtpoll.h>
+#include <pulsecore/rtclock.h>
+
+#include "module-sine-source-symdef.h"
+
+PA_MODULE_AUTHOR("Lennart Poettering");
+PA_MODULE_DESCRIPTION("Sine wave generator source");
+PA_MODULE_VERSION(PACKAGE_VERSION);
+PA_MODULE_LOAD_ONCE(FALSE);
+PA_MODULE_USAGE(
+        "rate=<sample rate> "
+        "source_name=<name for the source> "
+        "frequency=<frequency in Hz>");
+
+#define DEFAULT_SOURCE_NAME "sine_input"
+#define MAX_LATENCY_USEC (PA_USEC_PER_SEC * 2)
+
+struct userdata {
+    pa_core *core;
+    pa_module *module;
+    pa_source *source;
+
+    pa_thread *thread;
+    pa_thread_mq thread_mq;
+    pa_rtpoll *rtpoll;
+
+    pa_memchunk memchunk;
+    size_t peek_index;
+
+    pa_usec_t block_usec; /* how much to push at once */
+    pa_usec_t timestamp;  /* when to push next */
+};
+
+static const char* const valid_modargs[] = {
+    "rate",
+    "source_name",
+    "frequency",
+    NULL
+};
+
+static int source_process_msg(
+        pa_msgobject *o,
+        int code,
+        void *data,
+        int64_t offset,
+        pa_memchunk *chunk) {
+
+    struct userdata *u = PA_SOURCE(o)->userdata;
+
+    switch (code) {
+
+        case PA_SINK_MESSAGE_SET_STATE:
+
+            if (PA_PTR_TO_UINT(data) == PA_SINK_RUNNING)
+                u->timestamp = pa_rtclock_usec();
+
+            break;
+
+        case PA_SOURCE_MESSAGE_GET_LATENCY: {
+            pa_usec_t now, left_to_fill;
+
+            now = pa_rtclock_usec();
+            left_to_fill = u->timestamp > now ? u->timestamp - now : 0ULL;
+
+            *((pa_usec_t*) data) = u->block_usec > left_to_fill ? u->block_usec - left_to_fill : 0ULL;
+
+            return 0;
+        }
+    }
+
+    return pa_source_process_msg(o, code, data, offset, chunk);
+}
+
+static void source_update_requested_latency_cb(pa_source *s) {
+    struct userdata *u;
+
+    pa_source_assert_ref(s);
+    pa_assert_se(u = s->userdata);
+
+    u->block_usec = pa_source_get_requested_latency_within_thread(s);
+
+    if (u->block_usec == (pa_usec_t) -1)
+        u->block_usec = s->thread_info.max_latency;
+
+    pa_log("new block msec = %lu", (unsigned long) (u->block_usec / PA_USEC_PER_MSEC));
+}
+
+static void process_render(struct userdata *u, pa_usec_t now) {
+    pa_assert(u);
+
+    while (u->timestamp < now + u->block_usec) {
+        pa_memchunk chunk;
+        size_t k;
+
+        k = pa_usec_to_bytes_round_up(now + u->block_usec - u->timestamp, &u->source->sample_spec);
+
+        chunk.memblock = u->memchunk.memblock;
+        chunk.index = u->peek_index;
+        chunk.length = PA_MIN(u->memchunk.length - u->peek_index, k);
+
+        pa_log_debug("posting %lu", (unsigned long) chunk.length);
+        pa_source_post(u->source, &chunk);
+        pa_memchunk_dump_to_file(&chunk, "sine");
+
+        u->peek_index += chunk.length;
+        while (u->peek_index >= u->memchunk.length)
+            u->peek_index -= u->memchunk.length;
+
+        u->timestamp += pa_bytes_to_usec(chunk.length, &u->source->sample_spec);
+    }
+}
+
+static void thread_func(void *userdata) {
+    struct userdata *u = userdata;
+
+    pa_assert(u);
+
+    pa_log_debug("Thread starting up");
+
+    pa_thread_mq_install(&u->thread_mq);
+    pa_rtpoll_install(u->rtpoll);
+
+    u->timestamp = pa_rtclock_usec();
+
+    for (;;) {
+        int ret;
+
+        if (PA_SOURCE_IS_OPENED(u->source->thread_info.state)) {
+            pa_usec_t now;
+
+            now = pa_rtclock_usec();
+
+            if (u->timestamp <= now)
+                process_render(u, now);
+
+            pa_rtpoll_set_timer_absolute(u->rtpoll, u->timestamp);
+        } else
+            pa_rtpoll_set_timer_disabled(u->rtpoll);
+
+        /* Hmm, nothing to do. Let's sleep */
+        if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
+            goto fail;
+
+        if (ret == 0)
+            goto finish;
+    }
+
+fail:
+    /* If this was no regular exit from the loop we have to continue
+     * processing messages until we received PA_MESSAGE_SHUTDOWN */
+    pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
+    pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
+
+finish:
+    pa_log_debug("Thread shutting down");
+}
+
+static void calc_sine(float *f, size_t l, double freq) {
+    size_t i;
+
+    l /= sizeof(float);
+
+    for (i = 0; i < l; i++)
+        f[i] = (float) sin((double) i/(double)l*M_PI*2*freq)/2;
+}
+
+int pa__init(pa_module*m) {
+    struct userdata *u;
+    pa_modargs *ma;
+    pa_source_new_data data;
+    uint32_t frequency;
+    pa_sample_spec ss;
+    void *p;
+
+    pa_assert(m);
+
+    if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
+        pa_log("failed to parse module arguments.");
+        goto fail;
+    }
+
+    ss.format = PA_SAMPLE_FLOAT32;
+    ss.channels = 1;
+    ss.rate = 44100;
+
+    if (pa_modargs_get_value_u32(ma, "rate", &ss.rate) < 0 || ss.rate <= 1) {
+        pa_log("Invalid rate specification");
+        goto fail;
+    }
+
+    frequency = 440;
+    if (pa_modargs_get_value_u32(ma, "frequency", &frequency) < 0 || frequency < 1 || frequency > ss.rate/2) {
+        pa_log("Invalid frequency specification");
+        goto fail;
+    }
+
+    m->userdata = u = pa_xnew0(struct userdata, 1);
+    u->core = m->core;
+    u->module = m;
+    u->rtpoll = pa_rtpoll_new();
+    pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
+
+    u->peek_index = 0;
+    pa_memchunk_reset(&u->memchunk);
+    u->memchunk.memblock = pa_memblock_new(m->core->mempool, (size_t) -1);
+    u->memchunk.length = pa_frame_align(pa_memblock_get_length(u->memchunk.memblock), &ss);
+
+    p = pa_memblock_acquire(u->memchunk.memblock);
+    calc_sine(p, u->memchunk.length,
+              (double) frequency * (double) pa_bytes_to_usec(u->memchunk.length, &ss) / (double) PA_USEC_PER_SEC);
+    pa_memblock_release(u->memchunk.memblock);
+
+    pa_source_new_data_init(&data);
+    data.driver = __FILE__;
+    data.module = m;
+    pa_source_new_data_set_name(&data, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME));
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Sine source at %u Hz", (unsigned) frequency);
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, "abstract");
+    pa_proplist_setf(data.proplist, "sine.hz", "%u", frequency);
+    pa_source_new_data_set_sample_spec(&data, &ss);
+
+    u->source = pa_source_new(m->core, &data, PA_SOURCE_LATENCY);
+    pa_source_new_data_done(&data);
+
+    if (!u->source) {
+        pa_log("Failed to create source.");
+        goto fail;
+    }
+
+    u->source->parent.process_msg = source_process_msg;
+    u->source->update_requested_latency = source_update_requested_latency_cb;
+    u->source->userdata = u;
+
+    pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
+    pa_source_set_rtpoll(u->source, u->rtpoll);
+
+    pa_source_set_latency_range(u->source, (pa_usec_t) -1, MAX_LATENCY_USEC);
+    u->block_usec = u->source->thread_info.max_latency;
+
+    if (!(u->thread = pa_thread_new(thread_func, u))) {
+        pa_log("Failed to create thread.");
+        goto fail;
+    }
+
+    pa_source_put(u->source);
+
+    pa_modargs_free(ma);
+
+    return 0;
+
+fail:
+    if (ma)
+        pa_modargs_free(ma);
+
+    pa__done(m);
+
+    return -1;
+}
+
+void pa__done(pa_module*m) {
+    struct userdata *u;
+
+    pa_assert(m);
+
+    if (!(u = m->userdata))
+        return;
+
+    if (u->source)
+        pa_source_unlink(u->source);
+
+    if (u->thread) {
+        pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
+        pa_thread_free(u->thread);
+    }
+
+    pa_thread_mq_done(&u->thread_mq);
+
+    if (u->source)
+        pa_source_unref(u->source);
+
+    if (u->memchunk.memblock)
+        pa_memblock_unref(u->memchunk.memblock);
+
+    if (u->rtpoll)
+        pa_rtpoll_free(u->rtpoll);
+
+    pa_xfree(u);
+}

commit c2002dcd1f769e0a54976ad2d586a29c9316ffce
Merge: 9fc726c... 7ca0f38...
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 8 21:18:15 2009 +0100

    Merge branch 'master' of ssh://rootserver/home/lennart/git/public/pulseaudio

diff --cc src/Makefile.am
index bde51eb,608e678..dd9035b
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@@ -1140,13 -1176,9 +1178,13 @@@ module_sine_la_LDFLAGS = $(MODULE_LDFLA
  module_sine_la_LIBADD = $(AM_LIBADD) libpulsecore- at PA_MAJORMINORMICRO@.la libpulsecommon- at PA_MAJORMINORMICRO@.la libpulse.la
  
  module_null_sink_la_SOURCES = modules/module-null-sink.c
- module_null_sink_la_LDFLAGS = -module -avoid-version
+ module_null_sink_la_LDFLAGS = $(MODULE_LDFLAGS)
  module_null_sink_la_LIBADD = $(AM_LIBADD) libpulsecore- at PA_MAJORMINORMICRO@.la libpulsecommon- at PA_MAJORMINORMICRO@.la libpulse.la
  
 +module_sine_source_la_SOURCES = modules/module-sine-source.c
 +module_sine_source_la_LDFLAGS = -module -avoid-version
 +module_sine_source_la_LIBADD = $(AM_LIBADD) libpulsecore- at PA_MAJORMINORMICRO@.la libpulsecommon- at PA_MAJORMINORMICRO@.la libpulse.la
 +
  # Couplings
  
  module_combine_la_SOURCES = modules/module-combine.c

commit 5daf141683872a6403e397232688cffeeda32ffa
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 8 23:30:10 2009 +0100

    drop a few warning options, add a few new ones

diff --git a/configure.ac b/configure.ac
index 277ae2a..c24658b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -95,7 +95,7 @@ if test "x$M4" = xno ; then
 fi
 
 dnl Compiler flags
-DESIRED_FLAGS="-Wall -W -Wextra -pedantic -pipe -Wno-long-long -Wvla -Wno-overlength-strings -Wundef -Wformat -Wlogical-op -Wpacked -Wformat-security -Wmissing-include-dirs -Wformat-nonliteral -Wold-style-definition -Wdeclaration-after-statement -Wfloat-equal -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-noreturn -Wshadow -Wendif-labels -Wpointer-arith -Wcast-align -Wwrite-strings -Wno-unused-parameter -ffast-math"
+DESIRED_FLAGS="-Wall -W -Wextra -pedantic -pipe -Wno-long-long -Winline -Wvla -Wno-overlength-strings -Wunsafe-loop-optimizations -Wundef -Wformat=2 -Wlogical-op -Wsign-compare -Wpacked -Wformat-security -Wmissing-include-dirs -Wformat-nonliteral -Wold-style-definition -Wpointer-arith -Winit-self -Wdeclaration-after-statement -Wfloat-equal -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-declarations -Wmissing-noreturn -Wshadow -Wendif-labels -Wcast-align -Wstrict-aliasing=2 -Wwrite-strings -Wno-unused-parameter -ffast-math -Wp,-D_FORTIFY_SOURCE=2 -fno-common -fdiagnostics-show-option"
 
 for flag in $DESIRED_FLAGS ; do
   CC_CHECK_CFLAGS([$flag], [CFLAGS="$CFLAGS $flag"])

commit 7b52840adc2ba1eb045856995c6c430c493c5cf5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 8 23:30:51 2009 +0100

    add a few missing parens

diff --git a/src/pulsecore/endianmacros.h b/src/pulsecore/endianmacros.h
index 1b94de1..85bebd6 100644
--- a/src/pulsecore/endianmacros.h
+++ b/src/pulsecore/endianmacros.h
@@ -39,10 +39,10 @@
 #define PA_INT32_SWAP(x) ((int32_t) bswap_32((uint32_t) x))
 #define PA_UINT32_SWAP(x) ((uint32_t) bswap_32((uint32_t) x))
 #else
-#define PA_INT16_SWAP(x) ( (int16_t) ( ((uint16_t) x >> 8) | ((uint16_t) x << 8) ) )
-#define PA_UINT16_SWAP(x) ( (uint16_t) ( ((uint16_t) x >> 8) | ((uint16_t) x << 8) ) )
-#define PA_INT32_SWAP(x) ( (int32_t) ( ((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 8) | ((((uint32_t) x) >> 8) & 0xFF00) ) )
-#define PA_UINT32_SWAP(x) ( (uint32_t) ( ((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 8) | ((((uint32_t) x) >> 8) & 0xFF00) ) )
+#define PA_INT16_SWAP(x) ( (int16_t) ( ((uint16_t) (x) >> 8) | ((uint16_t) (x) << 8) ) )
+#define PA_UINT16_SWAP(x) ( (uint16_t) ( ((uint16_t) (x) >> 8) | ((uint16_t) (x) << 8) ) )
+#define PA_INT32_SWAP(x) ( (int32_t) ( ((uint32_t) (x) >> 24) | ((uint32_t) (x) << 24) | (((uint32_t) (x) & 0xFF00) << 8) | ((((uint32_t) (x)) >> 8) & 0xFF00) ) )
+#define PA_UINT32_SWAP(x) ( (uint32_t) ( ((uint32_t) (x) >> 24) | ((uint32_t) (x) << 24) | (((uint32_t) (x) & 0xFF00) << 8) | ((((uint32_t) (x)) >> 8) & 0xFF00) ) )
 #endif
 
 static inline float PA_FLOAT32_SWAP(float x) {
@@ -56,13 +56,13 @@ static inline float PA_FLOAT32_SWAP(float x) {
     return t.f;
 }
 
-#define PA_MAYBE_INT16_SWAP(c,x) ((c) ? PA_INT32_SWAP(x) : x)
-#define PA_MAYBE_UINT16_SWAP(c,x) ((c) ? PA_UINT32_SWAP(x) : x)
+#define PA_MAYBE_INT16_SWAP(c,x) ((c) ? PA_INT32_SWAP(x) : (x))
+#define PA_MAYBE_UINT16_SWAP(c,x) ((c) ? PA_UINT32_SWAP(x) : (x))
 
-#define PA_MAYBE_INT32_SWAP(c,x) ((c) ? PA_INT32_SWAP(x) : x)
-#define PA_MAYBE_UINT32_SWAP(c,x) ((c) ? PA_UINT32_SWAP(x) : x)
+#define PA_MAYBE_INT32_SWAP(c,x) ((c) ? PA_INT32_SWAP(x) : (x))
+#define PA_MAYBE_UINT32_SWAP(c,x) ((c) ? PA_UINT32_SWAP(x) : (x))
 
-#define PA_MAYBE_FLOAT32_SWAP(c,x) ((c) ? PA_FLOAT32_SWAP(x) : x)
+#define PA_MAYBE_FLOAT32_SWAP(c,x) ((c) ? PA_FLOAT32_SWAP(x) : (x))
 
 #ifdef WORDS_BIGENDIAN
  #define PA_INT16_FROM_LE(x) PA_INT16_SWAP(x)

commit 98049fbf81fae18707281642f6ae5b23632bd068
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 8 23:31:05 2009 +0100

    make things compile again

diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index 414c1c8..bce3092 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -28,6 +28,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <errno.h>
 
 #include <liboil/liboilfuncs.h>
 #include <liboil/liboil.h>
@@ -35,6 +36,7 @@
 #include <pulse/timeval.h>
 
 #include <pulsecore/log.h>
+#include <pulsecore/core-error.h>
 #include <pulsecore/macro.h>
 #include <pulsecore/g711.h>
 
@@ -478,7 +480,6 @@ size_t pa_mix(
 
         case PA_SAMPLE_FLOAT32RE: {
             unsigned channel = 0;
-            float linear[PA_CHANNELS_MAX];
 
             calc_linear_float_stream_volumes(streams, nstreams, volume, spec);
 

commit c850aa0c5b5e856618f11021a3e2a338c625de67
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jan 10 02:53:57 2009 +0100

    Add new pa_reduce() and pa_gcd() functions

diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index dde34d7..6f31566 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -2487,3 +2487,27 @@ pa_bool_t pa_in_valgrind(void) {
     return b > 1;
 }
 #endif
+
+unsigned pa_gcd(unsigned a, unsigned b) {
+
+    while (b > 0) {
+        unsigned t = b;
+        b = a % b;
+        a = t;
+    }
+
+    return a;
+}
+
+void pa_reduce(unsigned *num, unsigned *den) {
+
+    unsigned gcd = pa_gcd(*num, *den);
+
+    if (gcd <= 0)
+        return;
+
+    *num /= gcd;
+    *den /= gcd;
+
+    pa_assert(pa_gcd(*num, *den) == 1);
+}
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index fd6ee89..d9fad11 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -206,4 +206,7 @@ static inline pa_bool_t pa_in_valgrind(void) {
 }
 #endif
 
+unsigned pa_gcd(unsigned a, unsigned b);
+void pa_reduce(unsigned *num, unsigned *den);
+
 #endif

commit 4e8ada521affb62d8d95a21270371e40853599fb
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jan 10 02:55:57 2009 +0100

    show maximum usable slot size

diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index d9e1bf1..1d7f455 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -711,11 +711,12 @@ pa_mempool* pa_mempool_new(pa_bool_t shared, size_t size) {
         return NULL;
     }
 
-    pa_log_debug("Using %s memory pool with %u slots of size %s each, total size is %s",
+    pa_log_debug("Using %s memory pool with %u slots of size %s each, total size is %s, maximum usable slot size is %lu",
                  p->memory.shared ? "shared" : "private",
                  p->n_blocks,
                  pa_bytes_snprint(t1, sizeof(t1), (unsigned) p->block_size),
-                 pa_bytes_snprint(t2, sizeof(t2), (unsigned) (p->n_blocks * p->block_size)));
+                 pa_bytes_snprint(t2, sizeof(t2), (unsigned) (p->n_blocks * p->block_size)),
+                 (unsigned long) pa_mempool_block_size_max(p));
 
     memset(&p->stat, 0, sizeof(p->stat));
     pa_atomic_store(&p->n_init, 0);

commit 8a3dc57df2c90f9f27325998033db996b8fa5cfb
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jan 10 03:33:10 2009 +0100

    make module-sine-source actually work

diff --git a/src/modules/module-sine-source.c b/src/modules/module-sine-source.c
index dcc3416..358514a 100644
--- a/src/modules/module-sine-source.c
+++ b/src/modules/module-sine-source.c
@@ -129,7 +129,7 @@ static void source_update_requested_latency_cb(pa_source *s) {
     if (u->block_usec == (pa_usec_t) -1)
         u->block_usec = s->thread_info.max_latency;
 
-    pa_log("new block msec = %lu", (unsigned long) (u->block_usec / PA_USEC_PER_MSEC));
+    pa_log_debug("new block msec = %lu", (unsigned long) (u->block_usec / PA_USEC_PER_MSEC));
 }
 
 static void process_render(struct userdata *u, pa_usec_t now) {
@@ -147,7 +147,6 @@ static void process_render(struct userdata *u, pa_usec_t now) {
 
         pa_log_debug("posting %lu", (unsigned long) chunk.length);
         pa_source_post(u->source, &chunk);
-        pa_memchunk_dump_to_file(&chunk, "sine");
 
         u->peek_index += chunk.length;
         while (u->peek_index >= u->memchunk.length)
@@ -208,7 +207,7 @@ static void calc_sine(float *f, size_t l, double freq) {
     l /= sizeof(float);
 
     for (i = 0; i < l; i++)
-        f[i] = (float) sin((double) i/(double)l*M_PI*2*freq)/2;
+        *(f++) = (float) 0.5f * sin((double) i*M_PI*2*freq / (double) l);
 }
 
 int pa__init(pa_module*m) {
@@ -218,6 +217,8 @@ int pa__init(pa_module*m) {
     uint32_t frequency;
     pa_sample_spec ss;
     void *p;
+    unsigned n, d;
+    size_t l;
 
     pa_assert(m);
 
@@ -249,12 +250,22 @@ int pa__init(pa_module*m) {
 
     u->peek_index = 0;
     pa_memchunk_reset(&u->memchunk);
-    u->memchunk.memblock = pa_memblock_new(m->core->mempool, (size_t) -1);
-    u->memchunk.length = pa_frame_align(pa_memblock_get_length(u->memchunk.memblock), &ss);
+
+    n = ss.rate;
+    d = frequency;
+    pa_reduce(&n, &d);
+
+    l = pa_mempool_block_size_max(m->core->mempool) / pa_frame_size(&ss);
+
+    l /= n;
+    if (l <= 0) l = 1;
+    l *= n;
+
+    u->memchunk.length = l * pa_frame_size(&ss);
+    u->memchunk.memblock = pa_memblock_new(m->core->mempool, u->memchunk.length);
 
     p = pa_memblock_acquire(u->memchunk.memblock);
-    calc_sine(p, u->memchunk.length,
-              (double) frequency * (double) pa_bytes_to_usec(u->memchunk.length, &ss) / (double) PA_USEC_PER_SEC);
+    calc_sine(p, u->memchunk.length, pa_bytes_to_usec(u->memchunk.length, &ss) * frequency / PA_USEC_PER_SEC);
     pa_memblock_release(u->memchunk.memblock);
 
     pa_source_new_data_init(&data);

commit b6804eefea4697d594210502b19f8370771e2a22
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jan 10 03:33:27 2009 +0100

    Make sure we don't drop any data on the client side

diff --git a/src/utils/pacat.c b/src/utils/pacat.c
index ea736e2..b1e0d1f 100644
--- a/src/utils/pacat.c
+++ b/src/utils/pacat.c
@@ -139,17 +139,16 @@ static void stream_read_callback(pa_stream *s, size_t length, void *userdata) {
     assert(length > 0);
 
     if (buffer) {
-        fprintf(stderr, _("Buffer overrun, dropping incoming data\n"));
-        if (pa_stream_drop(s) < 0) {
-            fprintf(stderr, _("pa_stream_drop() failed: %s\n"), pa_strerror(pa_context_errno(context)));
-            quit(1);
-        }
-        return;
+        buffer = pa_xrealloc(buffer, buffer_length + length);
+        memcpy((uint8_t*) buffer + buffer_length, data, length);
+        buffer_length += length;
+    } else {
+        buffer = pa_xmalloc(length);
+        memcpy(buffer, data, length);
+        buffer_length = length;
+        buffer_index = 0;
     }
 
-    buffer = pa_xmalloc(buffer_length = length);
-    memcpy(buffer, data, length);
-    buffer_index = 0;
     pa_stream_drop(s);
 }
 

commit 947a8289432ef6e31f7ddd04b6351334a6ff7a63
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jan 12 19:33:38 2009 +0100

    fix version check

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index fa3e3f8..6cf5c46 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -2678,7 +2678,7 @@ static void sink_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sin
         pa_tagstruct_put_usec(t, pa_sink_get_requested_latency(sink));
     }
 
-    if (c->version >= 14)
+    if (c->version >= 15)
         pa_tagstruct_put_volume(t, sink->base_volume);
 }
 
@@ -2712,7 +2712,7 @@ static void source_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_s
         pa_tagstruct_put_usec(t, pa_source_get_requested_latency(source));
     }
 
-    if (c->version >= 14)
+    if (c->version >= 15)
         pa_tagstruct_put_volume(t, source->base_volume);
 }
 

commit b9e96e00cf56d2bc979b986926c77df04db9f6ff
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jan 12 19:34:12 2009 +0100

    for record streams fill in the latency as the fragsize

diff --git a/src/utils/pacat.c b/src/utils/pacat.c
index b1e0d1f..2d88e7f 100644
--- a/src/utils/pacat.c
+++ b/src/utils/pacat.c
@@ -278,6 +278,7 @@ static void context_state_callback(pa_context *c, void *userdata) {
                 buffer_attr.minreq = (uint32_t) process_time;
                 buffer_attr.maxlength = (uint32_t) -1;
                 buffer_attr.prebuf = (uint32_t) -1;
+                buffer_attr.fragsize = (uint32_t) latency;
                 flags |= PA_STREAM_ADJUST_LATENCY;
             }
 

commit d94d39d6350c8831925c69b01d752ee438367820
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jan 12 19:44:08 2009 +0100

    read base volume only in proto 15

diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c
index 5b905b7..8056a5a 100644
--- a/src/pulse/introspect.c
+++ b/src/pulse/introspect.c
@@ -172,7 +172,7 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, u
                 (o->context->version >= 13 &&
                  (pa_tagstruct_get_proplist(t, i.proplist) < 0 ||
                   pa_tagstruct_get_usec(t, &i.configured_latency) < 0)) ||
-                (o->context->version >= 14 &&
+                (o->context->version >= 15 &&
                  pa_tagstruct_get_volume(t, &i.base_volume) < 0)) {
 
                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
@@ -296,7 +296,7 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command,
                 (o->context->version >= 13 &&
                  (pa_tagstruct_get_proplist(t, i.proplist) < 0 ||
                   pa_tagstruct_get_usec(t, &i.configured_latency) < 0)) ||
-                (o->context->version >= 14 &&
+                (o->context->version >= 15 &&
                  pa_tagstruct_get_volume(t, &i.base_volume) < 0)) {
 
                 pa_context_fail(o->context, PA_ERR_PROTOCOL);

commit aff72437a6d56739e8ea7a34c746999b8f852529
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jan 12 19:44:21 2009 +0100

    Fix suspending of all sinks/sources
    
    pasuspender issues a SUSPEND_ALL requests for suspending all
    sinks/sources at once. This has been broken due to an ill-placed sanity
    checked.

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 6cf5c46..3c1e576 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -3968,7 +3968,7 @@ static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa
     }
 
     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
-    CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
+    CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name) || *name == 0, tag, PA_ERR_INVALID);
     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
     CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
     CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
@@ -3977,6 +3977,8 @@ static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa
 
         if (idx == PA_INVALID_INDEX && name && !*name) {
 
+            pa_log_debug("%s all sinks", b ? "Suspending" : "Resuming");
+
             if (pa_sink_suspend_all(c->protocol->core, b) < 0) {
                 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
                 return;
@@ -4002,6 +4004,8 @@ static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa
 
         if (idx == PA_INVALID_INDEX && name && !*name) {
 
+            pa_log_debug("%s all sources", b ? "Suspending" : "Resuming");
+
             if (pa_source_suspend_all(c->protocol->core, b) < 0) {
                 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
                 return;

commit 949de8156efbab1a2fb103ec414eaf983d7fa1c0
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jan 12 19:46:17 2009 +0100

    Extend command name lookup tables to cover complete protocol
    
    Makes it easier to debug things.

diff --git a/src/pulsecore/pdispatch.c b/src/pulsecore/pdispatch.c
index 00df0f7..a5b33d6 100644
--- a/src/pulsecore/pdispatch.c
+++ b/src/pulsecore/pdispatch.c
@@ -40,34 +40,35 @@
 
 #include "pdispatch.h"
 
-/*#define DEBUG_OPCODES */
+/* #define DEBUG_OPCODES */
 
 #ifdef DEBUG_OPCODES
 
 static const char *command_names[PA_COMMAND_MAX] = {
+    /* Generic commands */
     [PA_COMMAND_ERROR] = "ERROR",
     [PA_COMMAND_TIMEOUT] = "TIMEOUT",
     [PA_COMMAND_REPLY] = "REPLY",
+
+    /* CLIENT->SERVER */
     [PA_COMMAND_CREATE_PLAYBACK_STREAM] = "CREATE_PLAYBACK_STREAM",
     [PA_COMMAND_DELETE_PLAYBACK_STREAM] = "DELETE_PLAYBACK_STREAM",
     [PA_COMMAND_CREATE_RECORD_STREAM] = "CREATE_RECORD_STREAM",
     [PA_COMMAND_DELETE_RECORD_STREAM] = "DELETE_RECORD_STREAM",
     [PA_COMMAND_AUTH] = "AUTH",
-    [PA_COMMAND_REQUEST] = "REQUEST",
     [PA_COMMAND_EXIT] = "EXIT",
     [PA_COMMAND_SET_CLIENT_NAME] = "SET_CLIENT_NAME",
     [PA_COMMAND_LOOKUP_SINK] = "LOOKUP_SINK",
     [PA_COMMAND_LOOKUP_SOURCE] = "LOOKUP_SOURCE",
     [PA_COMMAND_DRAIN_PLAYBACK_STREAM] = "DRAIN_PLAYBACK_STREAM",
-    [PA_COMMAND_PLAYBACK_STREAM_KILLED] = "PLAYBACK_STREAM_KILLED",
-    [PA_COMMAND_RECORD_STREAM_KILLED] = "RECORD_STREAM_KILLED",
     [PA_COMMAND_STAT] = "STAT",
-    [PA_COMMAND_GET_PLAYBACK_LATENCY] = "PLAYBACK_LATENCY",
+    [PA_COMMAND_GET_PLAYBACK_LATENCY] = "GET_PLAYBACK_LATENCY",
     [PA_COMMAND_CREATE_UPLOAD_STREAM] = "CREATE_UPLOAD_STREAM",
     [PA_COMMAND_DELETE_UPLOAD_STREAM] = "DELETE_UPLOAD_STREAM",
     [PA_COMMAND_FINISH_UPLOAD_STREAM] = "FINISH_UPLOAD_STREAM",
     [PA_COMMAND_PLAY_SAMPLE] = "PLAY_SAMPLE",
     [PA_COMMAND_REMOVE_SAMPLE] = "REMOVE_SAMPLE",
+
     [PA_COMMAND_GET_SERVER_INFO] = "GET_SERVER_INFO",
     [PA_COMMAND_GET_SINK_INFO] = "GET_SINK_INFO",
     [PA_COMMAND_GET_SINK_INFO_LIST] = "GET_SINK_INFO_LIST",
@@ -84,15 +85,87 @@ static const char *command_names[PA_COMMAND_MAX] = {
     [PA_COMMAND_GET_SOURCE_OUTPUT_INFO] = "GET_SOURCE_OUTPUT_INFO",
     [PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST] = "GET_SOURCE_OUTPUT_INFO_LIST",
     [PA_COMMAND_SUBSCRIBE] = "SUBSCRIBE",
-    [PA_COMMAND_SUBSCRIBE_EVENT] = "SUBSCRIBE_EVENT",
+
     [PA_COMMAND_SET_SINK_VOLUME] = "SET_SINK_VOLUME",
     [PA_COMMAND_SET_SINK_INPUT_VOLUME] = "SET_SINK_INPUT_VOLUME",
     [PA_COMMAND_SET_SOURCE_VOLUME] = "SET_SOURCE_VOLME",
+
+    [PA_COMMAND_SET_SINK_MUTE] = "SET_SINK_MUTE",
+    [PA_COMMAND_SET_SOURCE_MUTE] = "SET_SOURCE_MUTE",
+
     [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = "TRIGGER_PLAYBACK_STREAM",
     [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = "FLUSH_PLAYBACK_STREAM",
     [PA_COMMAND_CORK_PLAYBACK_STREAM] = "CORK_PLAYBACK_STREAM",
+
+    [PA_COMMAND_SET_DEFAULT_SINK] = "SET_DEFAULT_SINK",
+    [PA_COMMAND_SET_DEFAULT_SOURCE] = "SET_DEFAULT_SOURCE",
+
+    [PA_COMMAND_SET_PLAYBACK_STREAM_NAME] = "SET_PLAYBACK_STREAM_NAME",
+    [PA_COMMAND_SET_RECORD_STREAM_NAME] = "SET_RECORD_STREAM_NAME",
+
+    [PA_COMMAND_KILL_CLIENT] = "KILL_CLIENT",
+    [PA_COMMAND_KILL_SINK_INPUT] = "KILL_SINK_INPUT",
+    [PA_COMMAND_KILL_SOURCE_OUTPUT] = "SOURCE_OUTPUT",
+
+    [PA_COMMAND_LOAD_MODULE] = "LOAD_MODULE",
+    [PA_COMMAND_UNLOAD_MODULE] = "UNLOAD_MODULE",
+
+    [PA_COMMAND_ADD_AUTOLOAD] = "ADD_AUTOLOAD",
+    [PA_COMMAND_REMOVE_AUTOLOAD] = "REMOVE_AUTOLOAD",
     [PA_COMMAND_GET_AUTOLOAD_INFO] = "GET_AUTOLOAD_INFO",
     [PA_COMMAND_GET_AUTOLOAD_INFO_LIST] = "GET_AUTOLOAD_INFO_LIST",
+
+    [PA_COMMAND_GET_RECORD_LATENCY] = "GET_RECORD_LATENCY",
+    [PA_COMMAND_CORK_RECORD_STREAM] = "CORK_RECORD_STREAM",
+    [PA_COMMAND_FLUSH_RECORD_STREAM] = "FLUSH_RECORD_STREAM",
+    [PA_COMMAND_PREBUF_PLAYBACK_STREAM] = "PREBUF_PLAYBACK_STREAM",
+
+    /* SERVER->CLIENT */
+    [PA_COMMAND_REQUEST] = "REQUEST",
+    [PA_COMMAND_OVERFLOW] = "OVERFLOW",
+    [PA_COMMAND_UNDERFLOW] = "UNDERFLOW",
+    [PA_COMMAND_PLAYBACK_STREAM_KILLED] = "PLAYBACK_STREAM_KILLED",
+    [PA_COMMAND_RECORD_STREAM_KILLED] = "RECORD_STREAM_KILLED",
+    [PA_COMMAND_SUBSCRIBE_EVENT] = "SUBSCRIBE_EVENT",
+
+    /* A few more client->server commands */
+
+    /* Supported since protocol v10 (0.9.5) */
+    [PA_COMMAND_MOVE_SINK_INPUT] = "MOVE_SINK_INPUT",
+    [PA_COMMAND_MOVE_SOURCE_OUTPUT] = "MOVE_SOURCE_OUTPUT",
+
+    /* Supported since protocol v11 (0.9.7) */
+    [PA_COMMAND_SET_SINK_INPUT_MUTE] = "SET_SINK_INPUT_MUTE",
+
+    [PA_COMMAND_SUSPEND_SINK] = "SUSPEND_SINK",
+    [PA_COMMAND_SUSPEND_SOURCE] = "SUSPEND_SOURCE",
+
+    /* Supported since protocol v12 (0.9.8) */
+    [PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR] = "SET_PLAYBACK_STREAM_BUFFER_ATTR",
+    [PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR] = "SET_RECORD_STREAM_BUFFER_ATTR",
+
+    [PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE] = "UPDATE_PLAYBACK_STREAM_SAMPLE_RATE",
+    [PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE] = "UPDATE_RECORD_STREAM_SAMPLE_RATE",
+
+    /* SERVER->CLIENT */
+    [PA_COMMAND_PLAYBACK_STREAM_SUSPENDED] = "PLAYBACK_STREAM_SUSPENDED",
+    [PA_COMMAND_RECORD_STREAM_SUSPENDED] = "RECORD_STREAM_SUSPENDED",
+    [PA_COMMAND_PLAYBACK_STREAM_MOVED] = "PLAYBACK_STREAM_MOVED",
+    [PA_COMMAND_RECORD_STREAM_MOVED] = "RECORD_STREAM_MOVED",
+
+    /* Supported since protocol v13 (0.9.11) */
+    [PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST] = "UPDATE_RECORD_STREAM_PROPLIST",
+    [PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST] = "UPDATE_RECORD_STREAM_PROPLIST",
+    [PA_COMMAND_UPDATE_CLIENT_PROPLIST] = "UPDATE_CLIENT_PROPLIST",
+    [PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST] = "REMOVE_RECORD_STREAM_PROPLIST",
+    [PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST] = "REMOVE_PLAYBACK_STREAM_PROPLIST",
+    [PA_COMMAND_REMOVE_CLIENT_PROPLIST] = "REMOVE_CLIENT_PROPLIST",
+
+    /* SERVER->CLIENT */
+    [PA_COMMAND_STARTED] = "STARTED",
+
+    /* Supported since protocol v14 (0.9.12) */
+    [PA_COMMAND_EXTENSION] = "EXTENSION"
 };
 
 #endif
@@ -213,11 +286,12 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_creds *creds,
 #ifdef DEBUG_OPCODES
 {
     char t[256];
-    char const *p;
-    if (!(p = command_names[command]))
+    char const *p = NULL;
+
+    if (command >= PA_COMMAND_MAX || !(p = command_names[command]))
         pa_snprintf((char*) (p = t), sizeof(t), "%u", command);
 
-    pa_log("Recieved opcode <%s>", p);
+    pa_log("[%p] Recieved opcode <%s>", pd, p);
 }
 #endif
 

commit b8e6aae08ee21d839ce8ebac6505a78c5ddcd8f5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jan 12 19:48:44 2009 +0100

    add new API function pa_memchunk_sine()
    
    Ease generation of sine signals. Try to make the repeatable sine
    memblock fit into a single mempool slot.

diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index bce3092..3be08ef 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -39,6 +39,7 @@
 #include <pulsecore/core-error.h>
 #include <pulsecore/macro.h>
 #include <pulsecore/g711.h>
+#include <pulsecore/core-util.h>
 
 #include "sample-util.h"
 #include "endianmacros.h"
@@ -1015,3 +1016,36 @@ void pa_memchunk_dump_to_file(pa_memchunk *c, const char *fn) {
 
     fclose(f);
 }
+
+static void calc_sine(float *f, size_t l, double freq) {
+    size_t i;
+
+    l /= sizeof(float);
+
+    for (i = 0; i < l; i++)
+        *(f++) = (float) 0.5f * sin((double) i*M_PI*2*freq / (double) l);
+}
+
+void pa_memchunk_sine(pa_memchunk *c, pa_mempool *pool, unsigned rate, unsigned freq) {
+    size_t l;
+    unsigned gcd, n;
+    void *p;
+
+    pa_memchunk_reset(c);
+
+    gcd = pa_gcd(rate, freq);
+    n = rate / gcd;
+
+    l = pa_mempool_block_size_max(pool) / sizeof(float);
+
+    l /= n;
+    if (l <= 0) l = 1;
+    l *= n;
+
+    c->length = l * sizeof(float);
+    c->memblock = pa_memblock_new(pool, c->length);
+
+    p = pa_memblock_acquire(c->memblock);
+    calc_sine(p, c->length, freq * l / rate);
+    pa_memblock_release(c->memblock);
+}
diff --git a/src/pulsecore/sample-util.h b/src/pulsecore/sample-util.h
index 36d19e4..2230aaf 100644
--- a/src/pulsecore/sample-util.h
+++ b/src/pulsecore/sample-util.h
@@ -83,4 +83,6 @@ size_t pa_usec_to_bytes_round_up(pa_usec_t t, const pa_sample_spec *spec);
 
 void pa_memchunk_dump_to_file(pa_memchunk *c, const char *fn);
 
+void pa_memchunk_sine(pa_memchunk *c, pa_mempool *pool, unsigned rate, unsigned freq);
+
 #endif

commit f67066b36237f0095d9fbdaf6111b7428465f7a4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jan 12 19:49:50 2009 +0100

    Port sine modules to pa_memchunk_sine()

diff --git a/src/modules/module-sine-source.c b/src/modules/module-sine-source.c
index 358514a..be95cc3 100644
--- a/src/modules/module-sine-source.c
+++ b/src/modules/module-sine-source.c
@@ -141,11 +141,11 @@ static void process_render(struct userdata *u, pa_usec_t now) {
 
         k = pa_usec_to_bytes_round_up(now + u->block_usec - u->timestamp, &u->source->sample_spec);
 
-        chunk.memblock = u->memchunk.memblock;
-        chunk.index = u->peek_index;
-        chunk.length = PA_MIN(u->memchunk.length - u->peek_index, k);
+        chunk = u->memchunk;
+        chunk.index += u->peek_index;
+        chunk.length = PA_MIN(chunk.length - u->peek_index, k);
 
-        pa_log_debug("posting %lu", (unsigned long) chunk.length);
+/*         pa_log_debug("posting %lu", (unsigned long) chunk.length); */
         pa_source_post(u->source, &chunk);
 
         u->peek_index += chunk.length;
@@ -216,9 +216,6 @@ int pa__init(pa_module*m) {
     pa_source_new_data data;
     uint32_t frequency;
     pa_sample_spec ss;
-    void *p;
-    unsigned n, d;
-    size_t l;
 
     pa_assert(m);
 
@@ -249,24 +246,7 @@ int pa__init(pa_module*m) {
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
 
     u->peek_index = 0;
-    pa_memchunk_reset(&u->memchunk);
-
-    n = ss.rate;
-    d = frequency;
-    pa_reduce(&n, &d);
-
-    l = pa_mempool_block_size_max(m->core->mempool) / pa_frame_size(&ss);
-
-    l /= n;
-    if (l <= 0) l = 1;
-    l *= n;
-
-    u->memchunk.length = l * pa_frame_size(&ss);
-    u->memchunk.memblock = pa_memblock_new(m->core->mempool, u->memchunk.length);
-
-    p = pa_memblock_acquire(u->memchunk.memblock);
-    calc_sine(p, u->memchunk.length, pa_bytes_to_usec(u->memchunk.length, &ss) * frequency / PA_USEC_PER_SEC);
-    pa_memblock_release(u->memchunk.memblock);
+    pa_memchunk_sine(&u->memchunk, m->core->mempool, ss.rate, frequency);
 
     pa_source_new_data_init(&data);
     data.driver = __FILE__;
diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c
index 4ee4688..3b0dc35 100644
--- a/src/modules/module-sine.c
+++ b/src/modules/module-sine.c
@@ -49,7 +49,7 @@ struct userdata {
     pa_core *core;
     pa_module *module;
     pa_sink_input *sink_input;
-    pa_memblock *memblock;
+    pa_memchunk memchunk;
     size_t peek_index;
 };
 
@@ -66,9 +66,11 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
     pa_assert_se(u = i->userdata);
     pa_assert(chunk);
 
-    chunk->memblock = pa_memblock_ref(u->memblock);
-    chunk->length = pa_memblock_get_length(u->memblock) - u->peek_index;
-    chunk->index = u->peek_index;
+    *chunk = u->memchunk;
+    pa_memblock_ref(chunk->memblock);
+
+    chunk->index += u->peek_index;
+    chunk->length -= u->peek_index;
 
     u->peek_index = 0;
 
@@ -76,19 +78,17 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
 }
 
 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
-    size_t l;
     struct userdata *u;
 
     pa_sink_input_assert_ref(i);
     pa_assert_se(u = i->userdata);
 
-    l = pa_memblock_get_length(u->memblock);
-    nbytes %= l;
+    nbytes %= u->memchunk.length;
 
     if (u->peek_index >= nbytes)
         u->peek_index -= nbytes;
     else
-        u->peek_index = l + u->peek_index - nbytes;
+        u->peek_index = u->memchunk.length + u->peek_index - nbytes;
 }
 
 static void sink_input_kill_cb(pa_sink_input *i) {
@@ -118,22 +118,12 @@ static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t s
         pa_sink_input_request_rewind(i, 0, FALSE, TRUE);
 }
 
-static void calc_sine(float *f, size_t l, double freq) {
-    size_t i;
-
-    l /= sizeof(float);
-
-    for (i = 0; i < l; i++)
-        f[i] = (float) sin((double) i/(double)l*M_PI*2*freq)/2;
-}
-
 int pa__init(pa_module*m) {
     pa_modargs *ma = NULL;
     struct userdata *u;
     pa_sink *sink;
     pa_sample_spec ss;
     uint32_t frequency;
-    void *p;
     pa_sink_input_new_data data;
 
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
@@ -141,14 +131,7 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
-    m->userdata = u = pa_xnew0(struct userdata, 1);
-    u->core = m->core;
-    u->module = m;
-    u->sink_input = NULL;
-    u->memblock = NULL;
-    u->peek_index = 0;
-
-    if (!(sink = pa_namereg_get(m->core, pa_modargs_get_value(ma, "sink", NULL), PA_NAMEREG_SINK, 1))) {
+    if (!(sink = pa_namereg_get(m->core, pa_modargs_get_value(ma, "sink", NULL), PA_NAMEREG_SINK, TRUE))) {
         pa_log("No such sink.");
         goto fail;
     }
@@ -163,19 +146,22 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
-    u->memblock = pa_memblock_new(m->core->mempool, pa_bytes_per_second(&ss));
-    p = pa_memblock_acquire(u->memblock);
-    calc_sine(p, pa_memblock_get_length(u->memblock), (double) frequency);
-    pa_memblock_release(u->memblock);
+    m->userdata = u = pa_xnew0(struct userdata, 1);
+    u->core = m->core;
+    u->module = m;
+    u->sink_input = NULL;
+
+    u->peek_index = 0;
+    pa_memchunk_sine(&u->memchunk, m->core->mempool, ss.rate, frequency);
 
     pa_sink_input_new_data_init(&data);
-    data.sink = sink;
     data.driver = __FILE__;
+    data.module = m;
+    data.sink = sink;
     pa_proplist_setf(data.proplist, PA_PROP_MEDIA_NAME, "%u Hz Sine", frequency);
     pa_proplist_sets(data.proplist, PA_PROP_MEDIA_ROLE, "abstract");
     pa_proplist_setf(data.proplist, "sine.hz", "%u", frequency);
     pa_sink_input_new_data_set_sample_spec(&data, &ss);
-    data.module = m;
 
     u->sink_input = pa_sink_input_new(m->core, &data, 0);
     pa_sink_input_new_data_done(&data);
@@ -215,8 +201,8 @@ void pa__done(pa_module*m) {
         pa_sink_input_unref(u->sink_input);
     }
 
-    if (u->memblock)
-        pa_memblock_unref(u->memblock);
+    if (u->memchunk.memblock)
+        pa_memblock_unref(u->memchunk.memblock);
 
     pa_xfree(u);
 }

commit 2ecf4c310fc8c439670311767e319537f0fdac45
Merge: f67066b... cf3abcd...
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jan 12 20:01:59 2009 +0100

    Merge commit 'origin/master-tx'


-- 
hooks/post-receive
PulseAudio Sound Server



More information about the pulseaudio-commits mailing list