From 65b787d00010ee59d823ec081c82116f2400ecf0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 30 Mar 2009 18:46:12 +0200 Subject: notify clients about tlength changes --- src/pulse/context.c | 4 ++- src/pulse/internal.h | 3 ++ src/pulse/stream.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/pulse/stream.h | 9 ++++- 4 files changed, 105 insertions(+), 3 deletions(-) (limited to 'src/pulse') diff --git a/src/pulse/context.c b/src/pulse/context.c index 00dffc25..7c86a435 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -99,7 +99,9 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_EXTENSION] = pa_command_extension, [PA_COMMAND_PLAYBACK_STREAM_EVENT] = pa_command_stream_event, [PA_COMMAND_RECORD_STREAM_EVENT] = pa_command_stream_event, - [PA_COMMAND_CLIENT_EVENT] = pa_command_client_event + [PA_COMMAND_CLIENT_EVENT] = pa_command_client_event, + [PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED] = pa_command_stream_buffer_attr, + [PA_COMMAND_RECORD_BUFFER_ATTR_CHANGED] = pa_command_stream_buffer_attr }; static void context_free(pa_context *c); diff --git a/src/pulse/internal.h b/src/pulse/internal.h index 9646d8a6..c08bd26a 100644 --- a/src/pulse/internal.h +++ b/src/pulse/internal.h @@ -185,6 +185,8 @@ struct pa_stream { void *started_userdata; pa_stream_event_cb_t event_callback; void *event_userdata; + pa_stream_notify_cb_t buffer_attr_callback; + void *buffer_attr_userdata; }; typedef void (*pa_operation_cb_t)(void); @@ -213,6 +215,7 @@ void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, uint32_t tag, p void pa_command_stream_started(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); void pa_command_stream_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); void pa_command_client_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +void pa_command_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t callback, void *userdata); void pa_operation_done(pa_operation *o); diff --git a/src/pulse/stream.c b/src/pulse/stream.c index 48e3b08e..bb53b19d 100644 --- a/src/pulse/stream.c +++ b/src/pulse/stream.c @@ -72,6 +72,8 @@ static void reset_callbacks(pa_stream *s) { s->started_userdata = NULL; s->event_callback = NULL; s->event_userdata = NULL; + s->buffer_attr_callback = NULL; + s->buffer_attr_userdata = NULL; } pa_stream *pa_stream_new_with_proplist( @@ -396,7 +398,7 @@ void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, uint32_t tag, p const char *dn; pa_bool_t suspended; uint32_t di; - pa_usec_t usec; + pa_usec_t usec = 0; uint32_t maxlength = 0, fragsize = 0, minreq = 0, tlength = 0, prebuf = 0; pa_assert(pd); @@ -486,6 +488,80 @@ finish: pa_context_unref(c); } +void pa_command_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_context *c = userdata; + pa_stream *s; + uint32_t channel; + pa_usec_t usec = 0; + uint32_t maxlength = 0, fragsize = 0, minreq = 0, tlength = 0, prebuf = 0; + + pa_assert(pd); + pa_assert(command == PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED || command == PA_COMMAND_RECORD_BUFFER_ATTR_CHANGED); + pa_assert(t); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + pa_context_ref(c); + + if (c->version < 15) { + pa_context_fail(c, PA_ERR_PROTOCOL); + goto finish; + } + + if (pa_tagstruct_getu32(t, &channel) < 0) { + pa_context_fail(c, PA_ERR_PROTOCOL); + goto finish; + } + + if (command == PA_COMMAND_RECORD_STREAM_MOVED) { + if (pa_tagstruct_getu32(t, &maxlength) < 0 || + pa_tagstruct_getu32(t, &fragsize) < 0 || + pa_tagstruct_get_usec(t, &usec) < 0) { + pa_context_fail(c, PA_ERR_PROTOCOL); + goto finish; + } + } else { + if (pa_tagstruct_getu32(t, &maxlength) < 0 || + pa_tagstruct_getu32(t, &tlength) < 0 || + pa_tagstruct_getu32(t, &prebuf) < 0 || + pa_tagstruct_getu32(t, &minreq) < 0 || + pa_tagstruct_get_usec(t, &usec) < 0) { + pa_context_fail(c, PA_ERR_PROTOCOL); + goto finish; + } + } + + if (!pa_tagstruct_eof(t)) { + pa_context_fail(c, PA_ERR_PROTOCOL); + goto finish; + } + + if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED ? c->playback_streams : c->record_streams, channel))) + goto finish; + + if (s->state != PA_STREAM_READY) + goto finish; + + if (s->direction == PA_STREAM_RECORD) + s->timing_info.configured_source_usec = usec; + else + s->timing_info.configured_sink_usec = usec; + + s->buffer_attr.maxlength = maxlength; + s->buffer_attr.fragsize = fragsize; + s->buffer_attr.tlength = tlength; + s->buffer_attr.prebuf = prebuf; + s->buffer_attr.minreq = minreq; + + request_auto_timing_update(s, TRUE); + + if (s->buffer_attr_callback) + s->buffer_attr_callback(s, s->buffer_attr_userdata); + +finish: + pa_context_unref(c); +} + void pa_command_stream_suspended(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_context *c = userdata; pa_stream *s; @@ -1798,6 +1874,20 @@ void pa_stream_set_event_callback(pa_stream *s, pa_stream_event_cb_t cb, void *u s->event_userdata = userdata; } +void pa_stream_set_buffer_attr_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) { + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); + + if (pa_detect_fork()) + return; + + if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED) + return; + + s->buffer_attr_callback = cb; + s->buffer_attr_userdata = userdata; +} + void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; int success = 1; diff --git a/src/pulse/stream.h b/src/pulse/stream.h index e80bc65d..8e99a753 100644 --- a/src/pulse/stream.h +++ b/src/pulse/stream.h @@ -512,6 +512,13 @@ void pa_stream_set_suspended_callback(pa_stream *p, pa_stream_notify_cb_t cb, vo * control event is received.\since 0.9.15 */ void pa_stream_set_event_callback(pa_stream *p, pa_stream_event_cb_t cb, void *userdata); +/** Set the callback function that is called whenver the buffer + * attributes on the server side change. Please note that the buffer + * attributes can change when moving a stream to a different + * sink/source too, hence if you use this callback you should use + * pa_stream_set_moved_callback() as well. \since 0.9.15 */ +void pa_stream_set_buffer_attr_callback(pa_stream *p, pa_stream_notify_cb_t cb, void *userdata); + /** Pause (or resume) playback of this stream temporarily. Available on both playback and recording streams. */ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, void *userdata); @@ -530,7 +537,7 @@ pa_operation* pa_stream_prebuf(pa_stream *s, pa_stream_success_cb_t cb, void *us * temporarily. Available for playback streams only. */ pa_operation* pa_stream_trigger(pa_stream *s, pa_stream_success_cb_t cb, void *userdata); -/** Rename the stream.*/ +/** Rename the stream. */ pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_success_cb_t cb, void *userdata); /** Return the current playback/recording time. This is based on the -- cgit