summaryrefslogtreecommitdiffstats
path: root/src/pulse
diff options
context:
space:
mode:
Diffstat (limited to 'src/pulse')
-rw-r--r--src/pulse/context.c4
-rw-r--r--src/pulse/def.h2
-rw-r--r--src/pulse/internal.h3
-rw-r--r--src/pulse/stream.c92
-rw-r--r--src/pulse/stream.h9
5 files changed, 106 insertions, 4 deletions
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/def.h b/src/pulse/def.h
index 9418e96f..9928f9bd 100644
--- a/src/pulse/def.h
+++ b/src/pulse/def.h
@@ -624,7 +624,7 @@ typedef struct pa_timing_info {
/**< The configured latency for the sink. \since 0.9.11 */
pa_usec_t configured_source_usec;
- /**< The configured latency for * the source. \since 0.9.11 */
+ /**< The configured latency for the source. \since 0.9.11 */
int64_t since_underrun;
/**< Bytes that were handed to the sink since the last underrun
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