[Spice-devel] [spice-gtk PATCH v4 2/6] audio: restore stream data from pulse

Victor Toso victortoso at redhat.com
Mon Mar 30 04:09:11 PDT 2015


Using ext-stream-restore we can get the last stream data of the
application. This is helpful to spice-pulse in order to provide this
values in case of volume-sync between client and guest.
---
 gtk/spice-pulse.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/gtk/spice-pulse.c b/gtk/spice-pulse.c
index 6b27c97..81a5588 100644
--- a/gtk/spice-pulse.c
+++ b/gtk/spice-pulse.c
@@ -25,6 +25,7 @@
 
 #include <pulse/glib-mainloop.h>
 #include <pulse/pulseaudio.h>
+#include <pulse/ext-stream-restore.h>
 
 #define SPICE_PULSE_GET_PRIVATE(obj)                                  \
     (G_TYPE_INSTANCE_GET_PRIVATE((obj), SPICE_TYPE_PULSE, SpicePulsePrivate))
@@ -788,6 +789,52 @@ static gboolean connect_channel(SpiceAudio *audio, SpiceChannel *channel)
     return FALSE;
 }
 
+static void stream_restore_read_cb(pa_context *context,
+                                   const pa_ext_stream_restore_info *info,
+                                   int eol,
+                                   void *userdata)
+{
+    SpicePulsePrivate *p = SPICE_PULSE(userdata)->priv;
+    gint i;
+    gchar *sink_name;
+    gchar *source_name;
+    struct stream *pstream = NULL;
+
+    if (eol)
+        return;
+
+    sink_name = g_strconcat("sink-input-by-application-name:",
+                            g_get_application_name(), NULL);
+    source_name = g_strconcat("source-output-by-application-name:",
+                              g_get_application_name(), NULL);
+
+    if (g_strcmp0(info->name, sink_name) == 0) {
+        pstream = &p->playback;
+    } else if (g_strcmp0(info->name, source_name) == 0) {
+        pstream = &p->record;
+    } else {
+        /* This is not the stream you are looking for. */
+        goto cleanup;
+    }
+
+    if (info->channel_map.channels == 0) {
+        SPICE_DEBUG("%s - Number of channels stored is zero. Ignore.", __func__);
+        goto cleanup;
+    }
+
+    pstream->mute = (info->mute) ? TRUE : FALSE;
+    pstream->nchannels = info->channel_map.channels;
+    pstream->volume = g_new(guint16, pstream->nchannels);
+    for (i = 0; i < pstream->nchannels; i++) {
+        pstream->volume[i] = (guint16) info->volume.values[i];
+        SPICE_DEBUG("%s - volume[%d] %u", __func__, i, pstream->volume[i]);
+    }
+
+cleanup:
+    g_free(sink_name);
+    g_free(source_name);
+}
+
 static void sink_input_info_cb(pa_context *context,
                                const pa_sink_input_info *info,
                                int eol,
@@ -915,6 +962,19 @@ static void context_state_callback(pa_context *c, void *userdata)
         break;
 
     case PA_CONTEXT_READY: {
+        if (p->playback.nchannels == 0 || p->record.nchannels == 0) {
+            pa_operation *op;
+            op = pa_ext_stream_restore_read(p->context,
+                                            stream_restore_read_cb,
+                                            pulse);
+            if (op) {
+                pa_operation_unref(op);
+            } else {
+                spice_warning("Restoring stream data failed: %s",
+                              pa_strerror(pa_context_errno(p->context)));
+            }
+        }
+
         if (!p->record.stream && p->record.started)
             create_record(SPICE_PULSE(userdata));
 
-- 
2.1.0



More information about the Spice-devel mailing list