Blame SOURCES/0023-sound-Don-t-mute-recording-when-client-reconnects.patch

fc8cd1
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2527eb
From: Christophe Fergeau <cfergeau@redhat.com>
2527eb
Date: Fri, 25 May 2018 11:12:40 +0200
fc8cd1
Subject: [spice-server] sound: Don't mute recording when client reconnects
2527eb
2527eb
When a new record channel is added, the code relies on a snd_send() call
2527eb
in record_channel_client_constructed() to send RECORD_START to the
2527eb
client. However, at this point, snd_send() is non-functional because
2527eb
the red_channel_client_pipe_add() call it makes is a no-op because
2527eb
prepare_pipe_add() makes a connection check through
2527eb
red_channel_client_is_connected() queueing the item. This connection
2527eb
check returns FALSE at ::constructed() time as the channel client will
2527eb
only become connected towards the end of
2527eb
red_channel_client_initable_init() which runs after the object
2527eb
instantiation is complete.
2527eb
2527eb
This commit solves this issue by making PlaybackChannelClient and
2527eb
RecordChannelClient implement GInitable, and move the code interacting
2527eb
with the client in their _initable_init() function, as at this point the
2527eb
objects will be able to send data.
2527eb
2527eb
This causes a bug where starting recording and then
2527eb
disconnecting/reconnecting the client does not successfully reenable
2527eb
recording. This is a regression introduced by commit d8dc09
2527eb
'sound: Convert SndChannelClient to RedChannelClient'
2527eb
2527eb
https://bugzilla.redhat.com/show_bug.cgi?id=1549132
2527eb
2527eb
Signed-off-by: Christophe Fergeau <cfergeau@redhat.com>
2527eb
Acked-by: Victor Toso <victortoso@redhat.com>
2527eb
---
2527eb
 server/sound.c | 120 ++++++++++++++++++++++++++++++++++---------------
2527eb
 1 file changed, 83 insertions(+), 37 deletions(-)
2527eb
2527eb
diff --git a/server/sound.c b/server/sound.c
2527eb
index 9073626..8c6cf8a 100644
2527eb
--- a/server/sound.c
2527eb
+++ b/server/sound.c
2527eb
@@ -103,6 +103,11 @@ typedef struct SndChannelClientClass {
2527eb
     RedChannelClientClass parent_class;
2527eb
 } SndChannelClientClass;
2527eb
 
2527eb
+static void playback_channel_client_initable_interface_init(GInitableIface *iface);
2527eb
+static void record_channel_client_initable_interface_init(GInitableIface *iface);
2527eb
+static GInitableIface *playback_channel_client_parent_initable_iface;
2527eb
+static GInitableIface *record_channel_client_parent_initable_iface;
2527eb
+
2527eb
 G_DEFINE_TYPE(SndChannelClient, snd_channel_client, RED_TYPE_CHANNEL_CLIENT)
2527eb
 
2527eb
 
2527eb
@@ -149,7 +154,9 @@ typedef struct PlaybackChannelClientClass {
2527eb
     SndChannelClientClass parent_class;
2527eb
 } PlaybackChannelClientClass;
2527eb
 
2527eb
-G_DEFINE_TYPE(PlaybackChannelClient, playback_channel_client, TYPE_SND_CHANNEL_CLIENT)
2527eb
+G_DEFINE_TYPE_WITH_CODE(PlaybackChannelClient, playback_channel_client, TYPE_SND_CHANNEL_CLIENT,
2527eb
+                        G_IMPLEMENT_INTERFACE(G_TYPE_INITABLE, playback_channel_client_initable_interface_init))
2527eb
+ 
2527eb
 
2527eb
 
2527eb
 typedef struct SpiceVolumeState {
2527eb
@@ -207,6 +214,7 @@ typedef struct RecordChannelClass {
2527eb
 } RecordChannelClass;
2527eb
 
2527eb
 G_DEFINE_TYPE(RecordChannel, record_channel, TYPE_SND_CHANNEL)
2527eb
+ 
2527eb
 
2527eb
 
2527eb
 #define TYPE_RECORD_CHANNEL_CLIENT record_channel_client_get_type()
2527eb
@@ -230,7 +238,8 @@ typedef struct RecordChannelClientClass {
2527eb
     SndChannelClientClass parent_class;
2527eb
 } RecordChannelClientClass;
2527eb
 
2527eb
-G_DEFINE_TYPE(RecordChannelClient, record_channel_client, TYPE_SND_CHANNEL_CLIENT)
2527eb
+G_DEFINE_TYPE_WITH_CODE(RecordChannelClient, record_channel_client, TYPE_SND_CHANNEL_CLIENT,
2527eb
+                        G_IMPLEMENT_INTERFACE(G_TYPE_INITABLE, record_channel_client_initable_interface_init))
2527eb
 
2527eb
 
2527eb
 /* A list of all Spice{Playback,Record}State objects */
2527eb
@@ -1044,7 +1053,6 @@ playback_channel_client_constructed(GObject *object)
2527eb
     RedChannelClient *rcc = RED_CHANNEL_CLIENT(playback_client);
2527eb
     RedChannel *red_channel = red_channel_client_get_channel(rcc);
2527eb
     SndChannel *channel = SND_CHANNEL(red_channel);
2527eb
-    RedClient *red_client = red_channel_client_get_client(rcc);
2527eb
     SndChannelClient *scc = SND_CHANNEL_CLIENT(playback_client);
2527eb
 
2527eb
     G_OBJECT_CLASS(playback_channel_client_parent_class)->constructed(object);
2527eb
@@ -1070,18 +1078,6 @@ playback_channel_client_constructed(GObject *object)
2527eb
 
2527eb
     spice_debug("playback client %p using mode %s", playback_client,
2527eb
                 spice_audio_data_mode_to_string(playback_client->mode));
2527eb
-
2527eb
-    if (!red_client_during_migrate_at_target(red_client)) {
2527eb
-        snd_set_command(scc, SND_PLAYBACK_MODE_MASK);
2527eb
-        if (channel->volume.volume_nchannels) {
2527eb
-            snd_set_command(scc, SND_VOLUME_MUTE_MASK);
2527eb
-        }
2527eb
-    }
2527eb
-
2527eb
-    if (channel->active) {
2527eb
-        playback_channel_client_start(scc);
2527eb
-    }
2527eb
-    snd_send(scc);
2527eb
 }
2527eb
 
2527eb
 static void snd_set_peer(RedChannel *red_channel, RedClient *client, RedsStream *stream,
2527eb
@@ -1250,27 +1246,6 @@ record_channel_client_finalize(GObject *object)
2527eb
     G_OBJECT_CLASS(record_channel_client_parent_class)->finalize(object);
2527eb
 }
2527eb
 
2527eb
-static void
2527eb
-record_channel_client_constructed(GObject *object)
2527eb
-{
2527eb
-    RecordChannelClient *record_client = RECORD_CHANNEL_CLIENT(object);
2527eb
-    RedChannel *red_channel = red_channel_client_get_channel(RED_CHANNEL_CLIENT(record_client));
2527eb
-    SndChannel *channel = SND_CHANNEL(red_channel);
2527eb
-    SndChannelClient *scc = SND_CHANNEL_CLIENT(record_client);
2527eb
-
2527eb
-    G_OBJECT_CLASS(record_channel_client_parent_class)->constructed(object);
2527eb
-
2527eb
-    if (channel->volume.volume_nchannels) {
2527eb
-        snd_set_command(scc, SND_VOLUME_MUTE_MASK);
2527eb
-    }
2527eb
-
2527eb
-    if (channel->active) {
2527eb
-        record_channel_client_start(scc);
2527eb
-    }
2527eb
-    snd_send(scc);
2527eb
-}
2527eb
-
2527eb
-
2527eb
 static void snd_set_record_peer(RedChannel *red_channel, RedClient *client, RedsStream *stream,
2527eb
                                 G_GNUC_UNUSED int migration,
2527eb
                                 RedChannelCapabilities *caps)
2527eb
@@ -1478,6 +1453,43 @@ snd_channel_client_init(SndChannelClient *self)
2527eb
 {
2527eb
 }
2527eb
 
2527eb
+static gboolean playback_channel_client_initable_init(GInitable *initable,
2527eb
+                                                      GCancellable *cancellable,
2527eb
+                                                      GError **error)
2527eb
+{
2527eb
+    gboolean success;
2527eb
+    RedClient *red_client = red_channel_client_get_client(RED_CHANNEL_CLIENT(initable));
2527eb
+    SndChannelClient *scc = SND_CHANNEL_CLIENT(initable);
2527eb
+    RedChannel *red_channel = red_channel_client_get_channel(RED_CHANNEL_CLIENT(initable));
2527eb
+    SndChannel *channel = SND_CHANNEL(red_channel);
2527eb
+
2527eb
+    success = playback_channel_client_parent_initable_iface->init(initable, cancellable, error);
2527eb
+    if (!success) {
2527eb
+        return FALSE;
2527eb
+    }
2527eb
+
2527eb
+    if (!red_client_during_migrate_at_target(red_client)) {
2527eb
+        snd_set_command(scc, SND_PLAYBACK_MODE_MASK);
2527eb
+        if (channel->volume.volume_nchannels) {
2527eb
+            snd_set_command(scc, SND_VOLUME_MUTE_MASK);
2527eb
+        }
2527eb
+    }
2527eb
+
2527eb
+    if (channel->active) {
2527eb
+        playback_channel_client_start(scc);
2527eb
+    }
2527eb
+    snd_send(SND_CHANNEL_CLIENT(initable));
2527eb
+
2527eb
+    return TRUE;
2527eb
+}
2527eb
+
2527eb
+static void playback_channel_client_initable_interface_init(GInitableIface *iface)
2527eb
+{
2527eb
+    playback_channel_client_parent_initable_iface = g_type_interface_peek_parent (iface);
2527eb
+
2527eb
+    iface->init = playback_channel_client_initable_init;
2527eb
+}
2527eb
+
2527eb
 static void
2527eb
 playback_channel_client_class_init(PlaybackChannelClientClass *klass)
2527eb
 {
2527eb
@@ -1505,11 +1517,45 @@ playback_channel_client_init(PlaybackChannelClient *playback)
2527eb
     snd_playback_alloc_frames(playback);
2527eb
 }
2527eb
 
2527eb
+static gboolean record_channel_client_initable_init(GInitable *initable,
2527eb
+                                                    GCancellable *cancellable,
2527eb
+                                                    GError **error)
2527eb
+{
2527eb
+    gboolean success;
2527eb
+    RecordChannelClient *record_client = RECORD_CHANNEL_CLIENT(initable);
2527eb
+    RedChannel *red_channel = red_channel_client_get_channel(RED_CHANNEL_CLIENT(record_client));
2527eb
+    SndChannel *channel = SND_CHANNEL(red_channel);
2527eb
+    SndChannelClient *scc = SND_CHANNEL_CLIENT(record_client);
2527eb
+
2527eb
+    success = record_channel_client_parent_initable_iface->init(initable, cancellable, error);
2527eb
+    if (!success) {
2527eb
+        return FALSE;
2527eb
+    }
2527eb
+
2527eb
+    if (channel->volume.volume_nchannels) {
2527eb
+        snd_set_command(scc, SND_VOLUME_MUTE_MASK);
2527eb
+    }
2527eb
+
2527eb
+    if (channel->active) {
2527eb
+        record_channel_client_start(scc);
2527eb
+    }
2527eb
+    snd_send(SND_CHANNEL_CLIENT(initable));
2527eb
+
2527eb
+    return TRUE;
2527eb
+}
2527eb
+
2527eb
+static void record_channel_client_initable_interface_init(GInitableIface *iface)
2527eb
+{
2527eb
+    record_channel_client_parent_initable_iface = g_type_interface_peek_parent (iface);
2527eb
+
2527eb
+    iface->init = record_channel_client_initable_init;
2527eb
+}
2527eb
+
2527eb
+
2527eb
 static void
2527eb
 record_channel_client_class_init(RecordChannelClientClass *klass)
2527eb
 {
2527eb
     GObjectClass *object_class = G_OBJECT_CLASS(klass);
2527eb
-    object_class->constructed = record_channel_client_constructed;
2527eb
     object_class->finalize = record_channel_client_finalize;
2527eb
 }
2527eb