[PATCH v2 14/18] stream: Add pa_stream_set_volume_channel_map()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The purpose is explained in the function documentation in stream.h.
---
 src/map-file         |  1 +
 src/pulse/internal.h |  1 +
 src/pulse/stream.c   | 28 +++++++++++++++++++++++++---
 src/pulse/stream.h   | 31 +++++++++++++++++++++++++++++++
 4 files changed, 58 insertions(+), 3 deletions(-)

diff --git a/src/map-file b/src/map-file
index fbad1a4..8283a03 100644
--- a/src/map-file
+++ b/src/map-file
@@ -321,6 +321,7 @@ pa_stream_set_started_callback;
 pa_stream_set_state_callback;
 pa_stream_set_suspended_callback;
 pa_stream_set_underflow_callback;
+pa_stream_set_volume_channel_map;
 pa_stream_set_write_callback;
 pa_stream_trigger;
 pa_stream_unref;
diff --git a/src/pulse/internal.h b/src/pulse/internal.h
index c5084d5..1577e8c 100644
--- a/src/pulse/internal.h
+++ b/src/pulse/internal.h
@@ -144,6 +144,7 @@ struct pa_stream {
 
     pa_sample_spec sample_spec;
     pa_channel_map channel_map;
+    bool channel_map_is_set;
     uint8_t n_formats;
     pa_format_info *req_formats[PA_MAX_FORMATS];
     pa_format_info *format;
diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 8e35c29..5b0cce7 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;
@@ -116,9 +116,10 @@ static pa_stream *pa_stream_new_with_proplist_internal(
     else
         pa_sample_spec_init(&s->sample_spec);
 
-    if (map)
+    if (map) {
         s->channel_map = *map;
-    else
+        s->channel_map_is_set = true;
+    } else
         pa_channel_map_init(&s->channel_map);
 
     s->n_formats = 0;
@@ -913,6 +914,27 @@ finish:
     pa_context_unref(c);
 }
 
+int pa_stream_set_volume_channel_map(pa_stream *s, const pa_channel_map *map) {
+    pa_assert(s);
+    pa_assert(map);
+    pa_assert(pa_channel_map_valid(map));
+
+    if (s->state != PA_STREAM_UNCONNECTED) {
+        pa_log_debug("Stream state is not unconnected.");
+        return -PA_ERR_BADSTATE;
+    }
+
+    if (s->channel_map_is_set && !pa_channel_map_equal(map, &s->channel_map)) {
+        pa_log_debug("Channel map is already set for the stream, changing it is not allowed.");
+        return -PA_ERR_INVALID;
+    }
+
+    s->channel_map = *map;
+    s->channel_map_is_set = true;
+
+    return 0;
+}
+
 static void invalidate_indexes(pa_stream *s, bool r, bool w) {
     pa_assert(s);
     pa_assert(PA_REFCNT_VALUE(s) >= 1);
diff --git a/src/pulse/stream.h b/src/pulse/stream.h
index a6785ec..9821ab8 100644
--- a/src/pulse/stream.h
+++ b/src/pulse/stream.h
@@ -418,6 +418,37 @@ 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 volume channel map. The stream volume is passed to
+ * pa_stream_connect_playback() or pa_stream_connect_record(), but those
+ * functions don't have a parameter for specifying the channel map for the
+ * volume. That's usually not an issue, because normally when creating the
+ * stream object, the stream channel map is passed already at that time.
+ * However, with pa_stream_new_extended() it's possible that no channel map is
+ * specified, in case the client wants the server to decide the stream channel
+ * map. In that situation the server still needs to know how the client
+ * intended the volume to be interpreted, i.e. the server needs a channel map
+ * for the volume (unless the volume has only one channel, in which case that
+ * volume is applied to all channels and no channel map information is needed
+ * from the client).
+ *
+ * This function exists to handle the specific case where all these conditions
+ * apply (in other cases this function does not need to be called):
+ *
+ *  1) The client creates the stream using pa_stream_new_extended().
+ *  2) The client doesn't specify a channel map for the stream (so the server
+ *     will decide the stream channel map).
+ *  3) The client specifies a volume for the stream.
+ *  4) The specified volume has more than one channel.
+ *
+ * This function must be called before calling pa_stream_connect_playback() or
+ * pa_stream_connect_record(). Returns a negative error code on failure.
+ *
+ * \since 5.0 */
+int pa_stream_set_volume_channel_map(
+        pa_stream *s, /**< The stream for which to set the volume channel map. */
+        const pa_channel_map *map /**< The volume channel map. */
+);
+
 /** 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
-- 
1.8.3.1



[Index of Archives]     [Linux Audio Users]     [AMD Graphics]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux