[pulseaudio-discuss] [PATCH] module-tunnel-sink-new: add a rewrite of module-tunnel using libpulse

Tanu Kaskinen tanu.kaskinen at linux.intel.com
Wed Aug 21 06:42:00 PDT 2013


On Wed, 2013-08-21 at 13:58 +0200, Alexander Couzens wrote:
> Old module-tunnel shares duplicated functionality with libpulse because
> it is implementing pulse protocol again. It is also not
> as much tested as libpulse it.
> 
> Signed-off-by: Alexander Couzens <lynxis at fe80.eu>
> ---
>  src/Makefile.am                      |   6 +
>  src/modules/module-tunnel-sink-new.c | 546 +++++++++++++++++++++++++++++++++++
>  2 files changed, 552 insertions(+)
>  create mode 100644 src/modules/module-tunnel-sink-new.c

Still some small issues, but they are trivial enough for me to fix them
myself. Patch applied, thank you!

> +static void thread_func(void *userdata) {
> +    struct userdata *u = userdata;
> +    pa_proplist *proplist;
> +    pa_assert(u);
> +
> +    pa_log_debug("Thread starting up");
> +    pa_thread_mq_install(&u->thread_mq);
> +
> +    proplist = tunnel_new_proplist(u);
> +    u->context = pa_context_new_with_proplist(u->thread_mainloop_api,
> +                                              "PulseAudio",
> +                                              proplist);
> +    pa_proplist_free(proplist);
> +
> +    if (!u->context) {
> +        pa_log("Failed to create libpulse context");
> +        goto fail;
> +    }
> +
> +    pa_context_set_state_callback(u->context, context_state_cb, u);
> +    if (pa_context_connect(u->context,
> +                           u->remote_server,
> +                           PA_CONTEXT_NOAUTOSPAWN,
> +                           NULL) < 0) {
> +        pa_log("Failed to connect libpulse context");
> +        goto fail;
> +    }
> +
> +    for (;;) {
> +        int ret;
> +        const void *p;
> +        pa_memchunk memchunk;
> +
> +        size_t writable = 0;
> +
> +        if (pa_mainloop_iterate(u->thread_mainloop, 1, &ret) < 0) {
> +            if (ret == 0)
> +                goto finish;
> +            else
> +                goto fail;
> +        }
> +
> +        if (PA_UNLIKELY(u->sink->thread_info.rewind_requested))
> +            pa_sink_process_rewind(u->sink, 0);
> +
> +        if (u->connected &&
> +                pa_stream_get_state(u->stream) == PA_STREAM_READY &&
> +                PA_SINK_IS_LINKED(u->sink->thread_info.state)) {
> +            /* TODO: use IS_RUNNING and cork the stream when sink is not running */

The stream should be corked only if the sink is suspended. The sink can
be idle or running, and in both cases the stream should stay uncorked.

> +static void stream_state_cb(pa_stream *stream, void *userdata) {
> +    struct userdata *u = userdata;
> +
> +    pa_assert(u);
> +
> +    switch (pa_stream_get_state(stream)) {
> +        case PA_STREAM_FAILED:
> +            pa_log_error("Stream failed.");
> +            u->connected = false;
> +            u->thread_mainloop_api->quit(u->thread_mainloop_api, TUNNEL_THREAD_FAILED_MAINLOOP);
> +            break;
> +        case PA_STREAM_TERMINATED:
> +            pa_log_debug("Stream terminated.");
> +            break;
> +        case PA_STREAM_READY:
> +            /* only call our requested_latency_cb when request_latency changed between PA_CONNECTING -> PA_STREAM_READY
> +             * otherwhise we would deny servers response to bufferattr (which defines latency) */

Comments should be wrapped at 80 characters.

> +            if (u->update_stream_bufferattr_after_connect)
> +                sink_update_requested_latency_cb(u->sink);

There should be an else section that updates the sink max_request to
match the tlength that the server assigned.

> +static void sink_update_requested_latency_cb(pa_sink *s) {
> +    struct userdata *u;
> +    pa_operation *operation;
> +    size_t nbytes;
> +    pa_usec_t block_usec;
> +    pa_buffer_attr bufferattr;
> +
> +    pa_sink_assert_ref(s);
> +    pa_assert_se(u = s->userdata);
> +
> +    block_usec = pa_sink_get_requested_latency_within_thread(s);
> +    if (block_usec == (pa_usec_t) -1)
> +        block_usec = s->thread_info.max_latency;
> +
> +    nbytes = pa_usec_to_bytes(block_usec, &s->sample_spec);
> +    pa_sink_set_max_request_within_thread(s, nbytes);
> +
> +    if (u->stream) {
> +        switch (pa_stream_get_state(u->stream)) {
> +        case PA_STREAM_READY:

One level of indentation is missing.

-- 
Tanu



More information about the pulseaudio-discuss mailing list