[Spice-commits] server/sound.c

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Jun 27 15:00:03 UTC 2018


 server/sound.c |   62 ++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 53 insertions(+), 9 deletions(-)

New commits:
commit a7a16504c917513b1508335dd043cbfeacc47eb7
Author: Christophe Fergeau <cfergeau at redhat.com>
Date:   Wed Jun 27 16:55:08 2018 +0200

    sound: Don't mute recording when client reconnects
    
    When a new record channel is added, the code relies on a snd_send() call
    in record_channel_client_constructed() to send RECORD_START to the
    client. However, at this point, snd_send() is non-functional because
    the red_channel_client_pipe_add() call it makes is a no-op because
    prepare_pipe_add() makes a connection check through
    red_channel_client_is_connected() queueing the item. This connection
    check returns FALSE at ::constructed() time as the channel client will
    only become connected towards the end of
    red_channel_client_initable_init() which runs after the object
    instantiation is complete.
    
    This causes a bug where starting recording and then
    disconnecting/reconnecting the client does not successfully reenable
    recording. This is a regression introduced by commit d8dc09
    'sound: Convert SndChannelClient to RedChannelClient'
    
    This commit solves this issue by making PlaybackChannelClient and
    RecordChannelClient implement GInitable, and move the code interacting
    with the client in their _initable_init() function, as at this point the
    objects will be able to send data.
    
    https://bugzilla.redhat.com/show_bug.cgi?id=1549132
    
    Signed-off-by: Christophe Fergeau <cfergeau at redhat.com>
    Acked-by: Frediano Ziglio <fziglio at redhat.com>

diff --git a/server/sound.c b/server/sound.c
index dd726576..ba7b4d4b 100644
--- a/server/sound.c
+++ b/server/sound.c
@@ -105,6 +105,11 @@ typedef struct SndChannelClientClass {
     RedChannelClientClass parent_class;
 } SndChannelClientClass;
 
+static void playback_channel_client_initable_interface_init(GInitableIface *iface);
+static void record_channel_client_initable_interface_init(GInitableIface *iface);
+static GInitableIface *playback_channel_client_parent_initable_iface;
+static GInitableIface *record_channel_client_parent_initable_iface;
+
 G_DEFINE_TYPE(SndChannelClient, snd_channel_client, RED_TYPE_CHANNEL_CLIENT)
 
 
@@ -151,8 +156,9 @@ typedef struct PlaybackChannelClientClass {
     SndChannelClientClass parent_class;
 } PlaybackChannelClientClass;
 
-G_DEFINE_TYPE(PlaybackChannelClient, playback_channel_client, TYPE_SND_CHANNEL_CLIENT)
-
+G_DEFINE_TYPE_WITH_CODE(PlaybackChannelClient, playback_channel_client, TYPE_SND_CHANNEL_CLIENT,
+                        G_IMPLEMENT_INTERFACE(G_TYPE_INITABLE,
+                                              playback_channel_client_initable_interface_init))
 
 typedef struct SpiceVolumeState {
     uint16_t *volume;
@@ -232,7 +238,9 @@ typedef struct RecordChannelClientClass {
     SndChannelClientClass parent_class;
 } RecordChannelClientClass;
 
-G_DEFINE_TYPE(RecordChannelClient, record_channel_client, TYPE_SND_CHANNEL_CLIENT)
+G_DEFINE_TYPE_WITH_CODE(RecordChannelClient, record_channel_client, TYPE_SND_CHANNEL_CLIENT,
+                        G_IMPLEMENT_INTERFACE(G_TYPE_INITABLE,
+                                              record_channel_client_initable_interface_init))
 
 
 /* A list of all Spice{Playback,Record}State objects */
@@ -1043,7 +1051,6 @@ playback_channel_client_constructed(GObject *object)
     RedChannelClient *rcc = RED_CHANNEL_CLIENT(playback_client);
     RedChannel *red_channel = red_channel_client_get_channel(rcc);
     SndChannel *channel = SND_CHANNEL(red_channel);
-    RedClient *red_client = red_channel_client_get_client(rcc);
     SndChannelClient *scc = SND_CHANNEL_CLIENT(playback_client);
 
     G_OBJECT_CLASS(playback_channel_client_parent_class)->constructed(object);
@@ -1069,6 +1076,22 @@ playback_channel_client_constructed(GObject *object)
 
     spice_debug("playback client %p using mode %s", playback_client,
                 spice_audio_data_mode_to_string(playback_client->mode));
+}
+
+static gboolean playback_channel_client_initable_init(GInitable *initable,
+                                                      GCancellable *cancellable,
+                                                      GError **error)
+{
+    gboolean success;
+    RedClient *red_client = red_channel_client_get_client(RED_CHANNEL_CLIENT(initable));
+    SndChannelClient *scc = SND_CHANNEL_CLIENT(initable);
+    RedChannel *red_channel = red_channel_client_get_channel(RED_CHANNEL_CLIENT(initable));
+    SndChannel *channel = SND_CHANNEL(red_channel);
+
+    success = playback_channel_client_parent_initable_iface->init(initable, cancellable, error);
+    if (!success) {
+        return FALSE;
+    }
 
     if (!red_client_during_migrate_at_target(red_client)) {
         snd_set_command(scc, SND_PLAYBACK_MODE_MASK);
@@ -1081,6 +1104,15 @@ playback_channel_client_constructed(GObject *object)
         playback_channel_client_start(scc);
     }
     snd_send(scc);
+
+    return TRUE;
+}
+
+static void playback_channel_client_initable_interface_init(GInitableIface *iface)
+{
+    playback_channel_client_parent_initable_iface = g_type_interface_peek_parent(iface);
+
+    iface->init = playback_channel_client_initable_init;
 }
 
 static void snd_set_peer(RedChannel *red_channel, RedClient *client, RedStream *stream,
@@ -1249,15 +1281,20 @@ record_channel_client_finalize(GObject *object)
     G_OBJECT_CLASS(record_channel_client_parent_class)->finalize(object);
 }
 
-static void
-record_channel_client_constructed(GObject *object)
+static gboolean record_channel_client_initable_init(GInitable *initable,
+                                                    GCancellable *cancellable,
+                                                    GError **error)
 {
-    RecordChannelClient *record_client = RECORD_CHANNEL_CLIENT(object);
+    gboolean success;
+    RecordChannelClient *record_client = RECORD_CHANNEL_CLIENT(initable);
     RedChannel *red_channel = red_channel_client_get_channel(RED_CHANNEL_CLIENT(record_client));
     SndChannel *channel = SND_CHANNEL(red_channel);
     SndChannelClient *scc = SND_CHANNEL_CLIENT(record_client);
 
-    G_OBJECT_CLASS(record_channel_client_parent_class)->constructed(object);
+    success = record_channel_client_parent_initable_iface->init(initable, cancellable, error);
+    if (!success) {
+        return FALSE;
+    }
 
     if (channel->volume.volume_nchannels) {
         snd_set_command(scc, SND_VOLUME_MUTE_MASK);
@@ -1267,8 +1304,16 @@ record_channel_client_constructed(GObject *object)
         record_channel_client_start(scc);
     }
     snd_send(scc);
+
+    return TRUE;
 }
 
+static void record_channel_client_initable_interface_init(GInitableIface *iface)
+{
+    record_channel_client_parent_initable_iface = g_type_interface_peek_parent(iface);
+
+    iface->init = record_channel_client_initable_init;
+}
 
 static void snd_set_record_peer(RedChannel *red_channel, RedClient *client, RedStream *stream,
                                 G_GNUC_UNUSED int migration,
@@ -1508,7 +1553,6 @@ static void
 record_channel_client_class_init(RecordChannelClientClass *klass)
 {
     GObjectClass *object_class = G_OBJECT_CLASS(klass);
-    object_class->constructed = record_channel_client_constructed;
     object_class->finalize = record_channel_client_finalize;
 }
 


More information about the Spice-commits mailing list