[pulseaudio-discuss] [PATCH 27/30] stream: Add pa_stream_set_initial_routing()
Tanu Kaskinen
tanu.kaskinen at linux.intel.com
Thu Jan 16 07:02:53 PST 2014
---
src/map-file | 1 +
src/pulse/internal.h | 2 ++
src/pulse/stream.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++----
src/pulse/stream.h | 30 +++++++++++++++++++++++++++---
4 files changed, 76 insertions(+), 7 deletions(-)
diff --git a/src/map-file b/src/map-file
index 92d6c4b..3a39253 100644
--- a/src/map-file
+++ b/src/map-file
@@ -311,6 +311,7 @@ pa_stream_ref;
pa_stream_set_buffer_attr;
pa_stream_set_buffer_attr_callback;
pa_stream_set_event_callback;
+pa_stream_set_initial_routing;
pa_stream_set_latency_update_callback;
pa_stream_set_monitor_stream;
pa_stream_set_moved_callback;
diff --git a/src/pulse/internal.h b/src/pulse/internal.h
index c5084d5..350130d 100644
--- a/src/pulse/internal.h
+++ b/src/pulse/internal.h
@@ -165,6 +165,8 @@ struct pa_stream {
uint32_t device_index;
char *device_name;
+ char **initial_routing_nodes;
+ unsigned n_initial_routing_nodes;
/* playback */
pa_memblock *write_memblock;
diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 7d77a0e..c67cee7 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -102,7 +102,7 @@ static pa_stream *pa_stream_new_with_proplist_internal(
PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
PA_CHECK_VALIDITY_RETURN_NULL(c, name || (p && pa_proplist_contains(p, PA_PROP_MEDIA_NAME)), PA_ERR_INVALID);
- s = pa_xnew(pa_stream, 1);
+ s = pa_xnew0(pa_stream, 1);
PA_REFCNT_INIT(s);
s->context = c;
s->mainloop = c->mainloop;
@@ -312,6 +312,10 @@ static void stream_free(pa_stream *s) {
if (s->format)
pa_format_info_free(s->format);
+ for (i = 0; i < s->n_initial_routing_nodes; i++)
+ pa_xfree(s->initial_routing_nodes[i]);
+
+ pa_xfree(s->initial_routing_nodes);
pa_xfree(s->device_name);
pa_xfree(s);
}
@@ -949,6 +953,38 @@ static void invalidate_indexes(pa_stream *s, bool r, bool w) {
request_auto_timing_update(s, true);
}
+int pa_stream_set_initial_routing(pa_stream *s, const char * const *nodes, unsigned n_nodes) {
+ unsigned i;
+
+ pa_assert(s);
+ pa_assert(nodes || n_nodes == 0);
+
+ PA_CHECK_VALIDITY(s->context, !pa_detect_fork(), PA_ERR_FORKED);
+ PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE);
+ PA_CHECK_VALIDITY(s->context, s->direct_on_input == PA_INVALID_INDEX, PA_ERR_INVALID);
+ PA_CHECK_VALIDITY(s->context, s->context->version >= 30, PA_ERR_NOTSUPPORTED);
+
+ for (i = 0; i < s->n_initial_routing_nodes; i++)
+ pa_xfree(s->initial_routing_nodes[i]);
+
+ pa_xfree(s->initial_routing_nodes);
+ s->n_initial_routing_nodes = n_nodes;
+
+ if (n_nodes == 0) {
+ s->initial_routing_nodes = NULL;
+ return 0;
+ }
+
+ s->initial_routing_nodes = pa_xnew(char *, n_nodes);
+
+ for (i = 0; i < n_nodes; i++) {
+ pa_assert(nodes[i]);
+ s->initial_routing_nodes[i] = pa_xstrdup(nodes[i]);
+ }
+
+ return 0;
+}
+
static void auto_timing_update_callback(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) {
pa_stream *s = userdata;
@@ -1227,6 +1263,7 @@ static int create_stream(
PA_CHECK_VALIDITY(s->context, !volume || s->n_formats || (pa_sample_spec_valid(&s->sample_spec) && volume->channels == s->sample_spec.channels), PA_ERR_INVALID);
PA_CHECK_VALIDITY(s->context, !sync_stream || (direction == PA_STREAM_PLAYBACK && sync_stream->direction == PA_STREAM_PLAYBACK), PA_ERR_INVALID);
PA_CHECK_VALIDITY(s->context, (flags & (PA_STREAM_ADJUST_LATENCY|PA_STREAM_EARLY_REQUESTS)) != (PA_STREAM_ADJUST_LATENCY|PA_STREAM_EARLY_REQUESTS), PA_ERR_INVALID);
+ PA_CHECK_VALIDITY(s->context, !dev || s->n_initial_routing_nodes == 0, PA_ERR_INVALID);
pa_stream_ref(s);
@@ -1258,7 +1295,7 @@ static int create_stream(
true);
}
- if (!dev)
+ if (!dev && s->direct_on_input == PA_INVALID_INDEX && s->n_initial_routing_nodes == 0)
dev = s->direction == PA_STREAM_PLAYBACK ? s->context->conf->default_sink : s->context->conf->default_source;
t = pa_tagstruct_command(
@@ -1373,8 +1410,12 @@ static int create_stream(
pa_tagstruct_put_boolean(t, flags & (PA_STREAM_PASSTHROUGH));
}
- if (s->context->version >= 30)
- pa_tagstruct_putu32(t, 0); /* n_initial_routing_nodes */
+ if (s->context->version >= 30) {
+ pa_tagstruct_putu32(t, s->n_initial_routing_nodes);
+
+ for (i = 0; i < s->n_initial_routing_nodes; i++)
+ pa_tagstruct_puts(t, s->initial_routing_nodes[i]);
+ }
pa_pstream_send_tagstruct(s->context->pstream, t);
pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s, NULL);
@@ -2887,6 +2928,7 @@ int pa_stream_set_monitor_stream(pa_stream *s, uint32_t sink_input_idx) {
PA_CHECK_VALIDITY(s->context, !pa_detect_fork(), PA_ERR_FORKED);
PA_CHECK_VALIDITY(s->context, sink_input_idx != PA_INVALID_INDEX, PA_ERR_INVALID);
PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE);
+ PA_CHECK_VALIDITY(s->context, s->n_initial_routing_nodes == 0, PA_ERR_INVALID);
PA_CHECK_VALIDITY(s->context, s->context->version >= 13, PA_ERR_NOTSUPPORTED);
s->direct_on_input = sink_input_idx;
diff --git a/src/pulse/stream.h b/src/pulse/stream.h
index a6785ec..46b7984 100644
--- a/src/pulse/stream.h
+++ b/src/pulse/stream.h
@@ -418,6 +418,22 @@ int pa_stream_is_suspended(pa_stream *s);
* not, and a negative value on error. \since 0.9.11 */
int pa_stream_is_corked(pa_stream *s);
+/** Set the initial routing for the stream. \a nodes is an array of node names
+ * and \a n_nodes is the array size. This must be called before connecting the
+ * stream.
+ *
+ * It is strongly recommended to not use this function, unless some specific
+ * initial routing has been explicitly requested by the user. Leaving the
+ * routing unspecified allows the server to apply automatic routing logic.
+ *
+ * You may not use both this function and pa_stream_set_monitor_stream() on the
+ * same stream.
+ *
+ * Returns a negative error code on failure.
+ *
+ * \since 6.0 */
+int pa_stream_set_initial_routing(pa_stream *s, const char * const *nodes, unsigned n_nodes);
+
/** Connect the stream to a sink. It is strongly recommended to pass
* NULL in both \a dev and \a volume and not to set either
* PA_STREAM_START_MUTED nor PA_STREAM_START_UNMUTED -- unless these
@@ -430,6 +446,8 @@ int pa_stream_is_corked(pa_stream *s);
* reconfigure audio devices to make other sinks/sources or
* capabilities available to be able to accept the stream.
*
+ * If you use pa_stream_set_initial_routing(), then \a dev must be NULL.
+ *
* Before 0.9.20 it was not defined whether the \a volume parameter was
* interpreted relative to the sink's current volume or treated as
* an absolute device volume. Since 0.9.20 it is an absolute volume when
@@ -444,7 +462,9 @@ int pa_stream_connect_playback(
const pa_cvolume *volume /**< Initial volume, or NULL for default */,
pa_stream *sync_stream /**< Synchronize this stream with the specified one, or NULL for a standalone stream */);
-/** Connect the stream to a source. */
+/** Connect the stream to a source.
+ *
+ * If you use pa_stream_set_initial_routing(), then \a dev must be NULL. */
int pa_stream_connect_record(
pa_stream *s /**< The stream to connect to a source */ ,
const char *dev /**< Name of the source to connect to, or NULL for default */,
@@ -781,8 +801,12 @@ pa_operation *pa_stream_proplist_remove(pa_stream *s, const char *const keys[],
/** For record streams connected to a monitor source: monitor only a
* very specific sink input of the sink. This function needs to be
- * called before pa_stream_connect_record() is called. \since
- * 0.9.11 */
+ * called before pa_stream_connect_record() is called.
+ *
+ * You may not use both this function and pa_stream_set_initial_routing() on
+ * the same stream.
+ *
+ * \since 0.9.11 */
int pa_stream_set_monitor_stream(pa_stream *s, uint32_t sink_input_idx);
/** Return the sink input index previously set with
--
1.8.3.1
More information about the pulseaudio-discuss
mailing list