[Spice-devel] [spice-server 17/17] sound: Convert SndChannelClient to RedChannelClient

Christophe Fergeau cfergeau at redhat.com
Wed Jan 11 08:48:31 UTC 2017


SndChannelClient is now inheriting from GObject, and has switched
from using its own code for sending data to using RedChannelClient.
This commit makes it directly inherit from RedChannelClient rather than
having a channel_client field. This allows to get rid of the whole
DummyChannel/DummyChannelClient code.

Based on a patch from Frediano Ziglio <fziglio at redhat.com>

Signed-off-by: Christophe Fergeau <cfergeau at redhat.com>
---
 server/Makefile.am            |   2 -
 server/dummy-channel-client.c | 140 -----------------------
 server/dummy-channel-client.h |  65 -----------
 server/sound.c                | 258 +++++++++++++++++-------------------------
 4 files changed, 103 insertions(+), 362 deletions(-)
 delete mode 100644 server/dummy-channel-client.c
 delete mode 100644 server/dummy-channel-client.h

diff --git a/server/Makefile.am b/server/Makefile.am
index 90ff779..1442bf1 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -104,8 +104,6 @@ libserver_la_SOURCES =				\
 	red-channel-client-private.h		\
 	red-client.c				\
 	red-client.h				\
-	dummy-channel-client.c			\
-	dummy-channel-client.h			\
 	red-common.h				\
 	dispatcher.c				\
 	dispatcher.h				\
diff --git a/server/dummy-channel-client.c b/server/dummy-channel-client.c
deleted file mode 100644
index 4efaa31..0000000
--- a/server/dummy-channel-client.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
-   Copyright (C) 2009-2015 Red Hat, Inc.
-
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   This library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "dummy-channel-client.h"
-#include "red-channel.h"
-#include "red-client.h"
-
-static void dummy_channel_client_initable_interface_init(GInitableIface *iface);
-
-G_DEFINE_TYPE_WITH_CODE(DummyChannelClient, dummy_channel_client, RED_TYPE_CHANNEL_CLIENT,
-                        G_IMPLEMENT_INTERFACE(G_TYPE_INITABLE,
-                                              dummy_channel_client_initable_interface_init))
-
-#define DUMMY_CHANNEL_CLIENT_PRIVATE(o) \
-    (G_TYPE_INSTANCE_GET_PRIVATE((o), TYPE_DUMMY_CHANNEL_CLIENT, DummyChannelClientPrivate))
-
-struct DummyChannelClientPrivate
-{
-    gboolean connected;
-};
-
-static gboolean dummy_channel_client_initable_init(GInitable *initable,
-                                                   GCancellable *cancellable,
-                                                   GError **error)
-{
-    GError *local_error = NULL;
-    RedChannelClient *rcc = RED_CHANNEL_CLIENT(initable);
-    RedClient *client = red_channel_client_get_client(rcc);
-    RedChannel *channel = red_channel_client_get_channel(rcc);
-
-    red_channel_add_client(channel, rcc);
-    if (!red_client_add_channel(client, rcc, &local_error)) {
-        red_channel_remove_client(channel, rcc);
-    }
-
-    if (local_error) {
-        g_warning("Failed to create channel client: %s", local_error->message);
-        g_propagate_error(error, local_error);
-    }
-    return local_error == NULL;
-}
-
-static void dummy_channel_client_initable_interface_init(GInitableIface *iface)
-{
-    iface->init = dummy_channel_client_initable_init;
-}
-
-static gboolean dummy_channel_client_is_connected(RedChannelClient *rcc)
-{
-    return DUMMY_CHANNEL_CLIENT(rcc)->priv->connected;
-}
-
-static void dummy_channel_client_disconnect(RedChannelClient *rcc)
-{
-    DummyChannelClient *self = DUMMY_CHANNEL_CLIENT(rcc);
-    RedChannel *channel = red_channel_client_get_channel(rcc);
-    GList *link;
-    uint32_t type, id;
-
-    if (channel && (link = g_list_find(red_channel_get_clients(channel), rcc))) {
-        g_object_get(channel, "channel-type", &type, "id", &id, NULL);
-        spice_printerr("rcc=%p (channel=%p type=%d id=%d)", rcc, channel,
-                       type, id);
-        red_channel_remove_client(channel, link->data);
-    }
-    self->priv->connected = FALSE;
-}
-
-static void
-dummy_channel_client_class_init(DummyChannelClientClass *klass)
-{
-    RedChannelClientClass *cc_class = RED_CHANNEL_CLIENT_CLASS(klass);
-
-    g_type_class_add_private(klass, sizeof(DummyChannelClientPrivate));
-
-    cc_class->is_connected = dummy_channel_client_is_connected;
-    cc_class->disconnect = dummy_channel_client_disconnect;
-}
-
-static void
-dummy_channel_client_init(DummyChannelClient *self)
-{
-    self->priv = DUMMY_CHANNEL_CLIENT_PRIVATE(self);
-
-    self->priv->connected = TRUE;
-}
-
-RedChannelClient* dummy_channel_client_create(RedChannel *channel,
-                                              RedClient  *client,
-                                              RedsStream *stream,
-                                              int num_common_caps,
-                                              uint32_t *common_caps,
-                                              int num_caps, uint32_t *caps)
-{
-    RedChannelClient *rcc;
-    GArray *common_caps_array = NULL, *caps_array = NULL;
-
-    if (common_caps) {
-        common_caps_array = g_array_sized_new(FALSE, FALSE, sizeof (*common_caps),
-                                              num_common_caps);
-        g_array_append_vals(common_caps_array, common_caps, num_common_caps);
-    }
-    if (caps) {
-        caps_array = g_array_sized_new(FALSE, FALSE, sizeof (*caps), num_caps);
-        g_array_append_vals(caps_array, caps, num_caps);
-    }
-
-    rcc = g_initable_new(TYPE_DUMMY_CHANNEL_CLIENT,
-                         NULL, NULL,
-                         "channel", channel,
-                         "client", client,
-                         "stream", stream,
-                         "caps", caps_array,
-                         "common-caps", common_caps_array,
-                         NULL);
-
-    if (caps_array)
-        g_array_unref(caps_array);
-    if (common_caps_array)
-        g_array_unref(common_caps_array);
-
-    return rcc;
-}
diff --git a/server/dummy-channel-client.h b/server/dummy-channel-client.h
deleted file mode 100644
index 54e0e6c..0000000
--- a/server/dummy-channel-client.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-   Copyright (C) 2009-2015 Red Hat, Inc.
-
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   This library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with this library; if not, see <http://www.gnu.org/licenses/>.
-   */
-#ifndef __DUMMY_CHANNEL_CLIENT_H__
-#define __DUMMY_CHANNEL_CLIENT_H__
-
-#include <glib-object.h>
-
-#include "red-channel-client.h"
-
-G_BEGIN_DECLS
-
-#define TYPE_DUMMY_CHANNEL_CLIENT dummy_channel_client_get_type()
-
-#define DUMMY_CHANNEL_CLIENT(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_DUMMY_CHANNEL_CLIENT, DummyChannelClient))
-#define DUMMY_CHANNEL_CLIENT_CLASS(klass) \
-    (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_DUMMY_CHANNEL_CLIENT, DummyChannelClientClass))
-#define IS_DUMMY_CHANNEL_CLIENT(obj) \
-    (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_DUMMY_CHANNEL_CLIENT))
-#define IS_DUMMY_CHANNEL_CLIENT_CLASS(klass) \
-    (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_DUMMY_CHANNEL_CLIENT))
-#define DUMMY_CHANNEL_CLIENT_GET_CLASS(obj) \
-    (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_DUMMY_CHANNEL_CLIENT, DummyChannelClientClass))
-
-typedef struct DummyChannelClient DummyChannelClient;
-typedef struct DummyChannelClientClass DummyChannelClientClass;
-typedef struct DummyChannelClientPrivate DummyChannelClientPrivate;
-
-struct DummyChannelClient
-{
-    RedChannelClient parent;
-
-    DummyChannelClientPrivate *priv;
-};
-
-struct DummyChannelClientClass
-{
-    RedChannelClientClass parent_class;
-};
-
-GType dummy_channel_client_get_type(void) G_GNUC_CONST;
-
-RedChannelClient *dummy_channel_client_create(RedChannel *channel,
-                                              RedClient  *client,
-                                              RedsStream *stream,
-                                              int num_common_caps, uint32_t *common_caps,
-                                              int num_caps, uint32_t *caps);
-
-G_END_DECLS
-
-#endif /* __DUMMY_CHANNEL_CLIENT_H__ */
diff --git a/server/sound.c b/server/sound.c
index d397bfb..899eecf 100644
--- a/server/sound.c
+++ b/server/sound.c
@@ -31,13 +31,10 @@
 
 #include "spice.h"
 #include "red-common.h"
-#include "dummy-channel-client.h"
 #include "main-channel.h"
 #include "reds.h"
 #include "red-qxl.h"
 #include "red-channel-client.h"
-/* FIXME: for now, allow sound channel access to private RedChannelClient data */
-#include "red-channel-client-private.h"
 #include "red-client.h"
 #include "sound.h"
 #include "main-channel-client.h"
@@ -84,17 +81,15 @@ typedef struct SpiceRecordState RecordChannel;
 
 typedef void (*snd_channel_on_message_done_proc)(SndChannelClient *client);
 
+
 #define TYPE_SND_CHANNEL_CLIENT snd_channel_client_get_type()
 #define SND_CHANNEL_CLIENT(obj) \
     (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_SND_CHANNEL_CLIENT, SndChannelClient))
-#define IS_SND_CHANNEL_CLIENT(obj) \
-    (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SND_CHANNEL_CLIENT))
 GType snd_channel_client_get_type(void) G_GNUC_CONST;
 
 /* Connects an audio client to a Spice client */
 struct SndChannelClient {
-    GObject parent;
-    RedChannelClient *channel_client;
+    RedChannelClient parent;
 
     int active;
     int client_active;
@@ -110,10 +105,10 @@ struct SndChannelClient {
 };
 
 typedef struct SndChannelClientClass {
-    GObjectClass parent_class;
+    RedChannelClientClass parent_class;
 } SndChannelClientClass;
 
-G_DEFINE_TYPE(SndChannelClient, snd_channel_client, G_TYPE_OBJECT)
+G_DEFINE_TYPE(SndChannelClient, snd_channel_client, RED_TYPE_CHANNEL_CLIENT)
 
 
 enum {
@@ -253,65 +248,10 @@ static void snd_playback_start(SndChannel *channel);
 static void snd_record_start(SndChannel *channel);
 static void snd_send(SndChannelClient * client);
 
-enum {
-    PROP0,
-    PROP_CHANNEL_CLIENT
-};
-
-static void
-snd_channel_client_set_property(GObject *object,
-                                guint property_id,
-                                const GValue *value,
-                                GParamSpec *pspec)
-{
-    SndChannelClient *self = SND_CHANNEL_CLIENT(object);
-
-    switch (property_id)
-    {
-        case PROP_CHANNEL_CLIENT:
-            self->channel_client = g_value_dup_object(value);
-            break;
-        default:
-            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
-    }
-}
-
-static SndChannelClient *snd_channel_client_from_dummy(RedChannelClient *dummy)
-{
-    SndChannelClient *sound_client;
-
-    g_assert(IS_DUMMY_CHANNEL_CLIENT(dummy));
-    sound_client =  g_object_get_data(G_OBJECT(dummy), "sound-channel-client");
-    g_assert(IS_SND_CHANNEL_CLIENT(sound_client));
-
-    return sound_client;
-}
-
 static RedsState* snd_channel_get_server(SndChannelClient *client)
 {
     g_return_val_if_fail(client != NULL, NULL);
-    return red_channel_get_server(red_channel_client_get_channel(client->channel_client));
-}
-
-static void snd_disconnect_channel(SndChannelClient *client)
-{
-    SndChannel *channel;
-    RedChannel *red_channel;
-    uint32_t type;
-
-    if (!client || !red_channel_client_is_connected(client->channel_client)) {
-        spice_debug("not connected");
-        return;
-    }
-    red_channel = red_channel_client_get_channel(client->channel_client);
-    g_object_get(red_channel, "channel-type", &type, NULL);
-    spice_debug("SndChannelClient=%p rcc=%p type=%d",
-                 client, client->channel_client, type);
-    channel = SND_CHANNEL(red_channel);
-    red_channel_client_disconnect(channel->connection->channel_client);
-    channel->connection->channel_client = NULL;
-    g_object_unref(client);
-    channel->connection = NULL;
+    return red_channel_get_server(red_channel_client_get_channel(RED_CHANNEL_CLIENT(client)));
 }
 
 static void snd_playback_free_frame(PlaybackChannelClient *playback_client, AudioFrame *frame)
@@ -394,8 +334,7 @@ playback_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, uint16_t ty
 static int
 record_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, uint16_t type, void *message)
 {
-    SndChannelClient *snd_client = snd_channel_client_from_dummy(rcc);
-    RecordChannelClient *record_client = RECORD_CHANNEL_CLIENT(snd_client);
+    RecordChannelClient *record_client = RECORD_CHANNEL_CLIENT(rcc);
 
     switch (type) {
     case SPICE_MSGC_RECORD_DATA:
@@ -439,7 +378,7 @@ record_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, uint16_t type
 
 static int snd_channel_send_migrate(SndChannelClient *client)
 {
-    RedChannelClient *rcc = client->channel_client;
+    RedChannelClient *rcc = RED_CHANNEL_CLIENT(client);
     SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
     SpiceMsgMigrate migrate;
 
@@ -460,7 +399,7 @@ static int snd_send_volume(SndChannelClient *client, uint32_t cap, int msg)
 {
     SpiceMsgAudioVolume *vol;
     uint8_t c;
-    RedChannelClient *rcc = client->channel_client;
+    RedChannelClient *rcc = RED_CHANNEL_CLIENT(client);
     SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
     SndChannel *channel = SND_CHANNEL(red_channel_client_get_channel(rcc));
     SpiceVolumeState *st = &channel->volume;
@@ -491,7 +430,7 @@ static int snd_playback_send_volume(PlaybackChannelClient *playback_client)
 static int snd_send_mute(SndChannelClient *client, uint32_t cap, int msg)
 {
     SpiceMsgAudioMute mute;
-    RedChannelClient *rcc = client->channel_client;
+    RedChannelClient *rcc = RED_CHANNEL_CLIENT(client);
     SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
     SndChannel *channel = SND_CHANNEL(red_channel_client_get_channel(rcc));
     SpiceVolumeState *st = &channel->volume;
@@ -516,8 +455,7 @@ static int snd_playback_send_mute(PlaybackChannelClient *playback_client)
 
 static int snd_playback_send_latency(PlaybackChannelClient *playback_client)
 {
-    SndChannelClient *client = SND_CHANNEL_CLIENT(playback_client);
-    RedChannelClient *rcc = client->channel_client;
+    RedChannelClient *rcc = RED_CHANNEL_CLIENT(playback_client);
     SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
     SpiceMsgPlaybackLatency latency_msg;
 
@@ -532,8 +470,7 @@ static int snd_playback_send_latency(PlaybackChannelClient *playback_client)
 
 static int snd_playback_send_start(PlaybackChannelClient *playback_client)
 {
-    SndChannelClient *client = (SndChannelClient *)playback_client;
-    RedChannelClient *rcc = client->channel_client;
+    RedChannelClient *rcc = RED_CHANNEL_CLIENT(playback_client);
     SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
     SpiceMsgPlaybackStart start;
 
@@ -551,8 +488,7 @@ static int snd_playback_send_start(PlaybackChannelClient *playback_client)
 
 static int snd_playback_send_stop(PlaybackChannelClient *playback_client)
 {
-    SndChannelClient *client = (SndChannelClient *)playback_client;
-    RedChannelClient *rcc = client->channel_client;
+    RedChannelClient *rcc = RED_CHANNEL_CLIENT(playback_client);
 
     red_channel_client_init_send_data(rcc, SPICE_MSG_PLAYBACK_STOP);
 
@@ -573,8 +509,7 @@ static int snd_playback_send_ctl(PlaybackChannelClient *playback_client)
 
 static int snd_record_send_start(RecordChannelClient *record_client)
 {
-    SndChannelClient *client = (SndChannelClient *)record_client;
-    RedChannelClient *rcc = client->channel_client;
+    RedChannelClient *rcc = RED_CHANNEL_CLIENT(record_client);
     SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
     SpiceMsgRecordStart start;
 
@@ -592,8 +527,7 @@ static int snd_record_send_start(RecordChannelClient *record_client)
 
 static int snd_record_send_stop(RecordChannelClient *record_client)
 {
-    SndChannelClient *client = (SndChannelClient *)record_client;
-    RedChannelClient *rcc = client->channel_client;
+    RedChannelClient *rcc = RED_CHANNEL_CLIENT(record_client);
 
     red_channel_client_init_send_data(rcc, SPICE_MSG_RECORD_STOP);
 
@@ -635,8 +569,7 @@ static int snd_record_send_migrate(RecordChannelClient *record_client)
 
 static int snd_playback_send_write(PlaybackChannelClient *playback_client)
 {
-    SndChannelClient *client = (SndChannelClient *)playback_client;
-    RedChannelClient *rcc = client->channel_client;
+    RedChannelClient *rcc = RED_CHANNEL_CLIENT(playback_client);
     SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
     AudioFrame *frame;
     SpiceMsgPlaybackPacket msg;
@@ -661,7 +594,7 @@ static int snd_playback_send_write(PlaybackChannelClient *playback_client)
                                     snd_codec_frame_size(playback_client->codec) * sizeof(frame->samples[0]),
                                     playback_client->encode_buf, &n) != SND_CODEC_OK) {
             spice_printerr("encode failed");
-            snd_disconnect_channel(client);
+            red_channel_client_disconnect(rcc);
             return FALSE;
         }
         spice_marshaller_add_by_ref_full(m, playback_client->encode_buf, n,
@@ -674,8 +607,7 @@ static int snd_playback_send_write(PlaybackChannelClient *playback_client)
 
 static int playback_send_mode(PlaybackChannelClient *playback_client)
 {
-    SndChannelClient *client = (SndChannelClient *)playback_client;
-    RedChannelClient *rcc = client->channel_client;
+    RedChannelClient *rcc = RED_CHANNEL_CLIENT(playback_client);
     SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
     SpiceMsgPlaybackMode mode;
 
@@ -712,7 +644,7 @@ static void snd_persistent_pipe_item_free(struct RedPipeItem *item)
 
 static void snd_send(SndChannelClient * client)
 {
-    RedChannelClient *rcc = client->channel_client;
+    RedChannelClient *rcc = RED_CHANNEL_CLIENT(client);
 
     if (!client || !red_channel_client_pipe_is_empty(rcc) || !client->command) {
         return;
@@ -725,8 +657,8 @@ static void snd_send(SndChannelClient * client)
 
 static void playback_channel_send_item(RedChannelClient *rcc, G_GNUC_UNUSED RedPipeItem *item)
 {
-    SndChannelClient *client = snd_channel_client_from_dummy(rcc);
-    PlaybackChannelClient *playback_client = PLAYBACK_CHANNEL_CLIENT(client);
+    PlaybackChannelClient *playback_client = PLAYBACK_CHANNEL_CLIENT(rcc);
+    SndChannelClient *client = SND_CHANNEL_CLIENT(rcc);
 
     client->command &= SND_PLAYBACK_MODE_MASK|SND_PLAYBACK_PCM_MASK|
                        SND_CTRL_MASK|SND_VOLUME_MUTE_MASK|
@@ -784,8 +716,8 @@ static void playback_channel_send_item(RedChannelClient *rcc, G_GNUC_UNUSED RedP
 
 static void record_channel_send_item(RedChannelClient *rcc, G_GNUC_UNUSED RedPipeItem *item)
 {
-    SndChannelClient *client = snd_channel_client_from_dummy(rcc);
-    RecordChannelClient *record_client = RECORD_CHANNEL_CLIENT(client);
+    RecordChannelClient *record_client = RECORD_CHANNEL_CLIENT(rcc);
+    SndChannelClient *client = SND_CHANNEL_CLIENT(rcc);
 
     client->command &= SND_CTRL_MASK|SND_VOLUME_MUTE_MASK|SND_MIGRATE_MASK;
     while (client->command) {
@@ -877,7 +809,7 @@ static void snd_channel_on_disconnect(RedChannelClient *rcc)
 static uint8_t*
 snd_channel_client_alloc_recv_buf(RedChannelClient *rcc, uint16_t type, uint32_t size)
 {
-    SndChannelClient *client = snd_channel_client_from_dummy(rcc);
+    SndChannelClient *client = SND_CHANNEL_CLIENT(rcc);
     // If message is too big allocate one, this should never happen
     if (size > sizeof(client->receive_buf)) {
         return spice_malloc(size);
@@ -889,7 +821,7 @@ static void
 snd_channel_client_release_recv_buf(RedChannelClient *rcc, uint16_t type, uint32_t size,
                                     uint8_t *msg)
 {
-    SndChannelClient *client = snd_channel_client_from_dummy(rcc);
+    SndChannelClient *client = SND_CHANNEL_CLIENT(rcc);
     if (msg != client->receive_buf) {
         free(msg);
     }
@@ -907,8 +839,8 @@ static void snd_disconnect_channel_client(RedChannelClient *rcc)
 
     spice_debug("channel-type=%d", type);
     if (channel->connection) {
-        spice_assert(channel->connection->channel_client == rcc);
-        snd_disconnect_channel(channel->connection);
+        spice_assert(RED_CHANNEL_CLIENT(channel->connection) == rcc);
+        red_channel_client_disconnect(rcc);
     }
 }
 
@@ -1065,9 +997,9 @@ void snd_set_playback_latency(RedClient *client, uint32_t latency)
         uint32_t type;
         g_object_get(RED_CHANNEL(now), "channel-type", &type, NULL);
         if (type == SPICE_CHANNEL_PLAYBACK && now->connection &&
-            red_channel_client_get_client(now->connection->channel_client) == client) {
+            red_channel_client_get_client(RED_CHANNEL_CLIENT(now->connection)) == client) {
 
-            if (red_channel_client_test_remote_cap(now->connection->channel_client,
+            if (red_channel_client_test_remote_cap(RED_CHANNEL_CLIENT(now->connection),
                 SPICE_PLAYBACK_CAP_LATENCY)) {
                 PlaybackChannelClient* playback = (PlaybackChannelClient*)now->connection;
 
@@ -1143,24 +1075,15 @@ static void
 playback_channel_client_constructed(GObject *object)
 {
     PlaybackChannelClient *playback_client = PLAYBACK_CHANNEL_CLIENT(object);
-    SndChannelClient *client = SND_CHANNEL_CLIENT(playback_client);
-    RedChannel *red_channel = red_channel_client_get_channel(client->channel_client);
-    RedClient *red_client = red_channel_client_get_client(client->channel_client);
+    RedChannel *red_channel = red_channel_client_get_channel(RED_CHANNEL_CLIENT(playback_client));
+    RedClient *client = red_channel_client_get_client(RED_CHANNEL_CLIENT(playback_client));
     SndChannel *channel = SND_CHANNEL(red_channel);
 
     G_OBJECT_CLASS(playback_channel_client_parent_class)->constructed(object);
 
-    snd_channel_config_socket(RED_CHANNEL_CLIENT(client->channel_client));
-
-    /* SndChannelClient is not yet a RedChannelClient, but we still need to go from our
-     * RedChannelClient implementation (DummyChannelClient) to the SndChannelClient instance
-     * in various vfuncs
-     */
-    g_object_set_data(G_OBJECT(client->channel_client), "sound-channel-client", client);
-
     SND_CHANNEL_CLIENT(playback_client)->on_message_done = snd_playback_on_message_done;
 
-    RedChannelClient *rcc = client->channel_client;
+    RedChannelClient *rcc = RED_CHANNEL_CLIENT(playback_client);
     int client_can_celt = red_channel_client_test_remote_cap(rcc,
                                           SPICE_PLAYBACK_CAP_CELT_0_5_1);
     int client_can_opus = red_channel_client_test_remote_cap(rcc,
@@ -1178,14 +1101,14 @@ playback_channel_client_constructed(GObject *object)
         }
     }
 
-    if (!red_client_during_migrate_at_target(red_client)) {
+    if (!red_client_during_migrate_at_target(client)) {
         on_new_playback_channel_client(channel, SND_CHANNEL_CLIENT(playback_client));
     }
 
     if (channel->active) {
         snd_playback_start(channel);
     }
-    snd_send(channel->connection);
+    snd_send(SND_CHANNEL_CLIENT(playback_client));
 }
 
 static void snd_set_playback_peer(RedChannel *red_channel, RedClient *client, RedsStream *stream,
@@ -1194,20 +1117,43 @@ static void snd_set_playback_peer(RedChannel *red_channel, RedClient *client, Re
                                   int num_caps, uint32_t *caps)
 {
     SndChannel *channel = SND_CHANNEL(red_channel);
+    GArray *common_caps_array = NULL, *caps_array = NULL;
     PlaybackChannelClient *playback_client;
 
-    snd_disconnect_channel(channel->connection);
+    if (channel->connection) {
+        red_channel_client_disconnect(RED_CHANNEL_CLIENT(channel->connection));
+        channel->connection = NULL;
+    }
 
-    RedChannelClient *rcc =
-        dummy_channel_client_create(red_channel, client, stream,
-                                    num_common_caps, common_caps,
-                                    num_caps, caps);
-    playback_client = g_object_new(TYPE_PLAYBACK_CHANNEL_CLIENT, "channel-client", rcc, NULL);
-    g_object_unref(rcc);
+    if (common_caps) {
+        common_caps_array = g_array_sized_new(FALSE, FALSE, sizeof (*common_caps),
+                                              num_common_caps);
+        g_array_append_vals(common_caps_array, common_caps, num_common_caps);
+    }
+    if (caps) {
+        caps_array = g_array_sized_new(FALSE, FALSE, sizeof (*caps), num_caps);
+        g_array_append_vals(caps_array, caps, num_caps);
+    }
+
+    playback_client = g_initable_new(TYPE_PLAYBACK_CHANNEL_CLIENT,
+                                     NULL, NULL,
+                                     "channel", channel,
+                                     "client", client,
+                                     "stream", stream,
+                                     "caps", caps_array,
+                                     "common-caps", common_caps_array,
+                                     NULL);
     g_warn_if_fail(playback_client != NULL);
     /* FIXME: stream used to be destroyed (reds_stream_free) on failure to create the initable,
      * is it still the case
      */
+
+    if (caps_array) {
+        g_array_unref(caps_array);
+    }
+    if (common_caps_array) {
+        g_array_unref(common_caps_array);
+    }
 }
 
 static void snd_record_migrate_channel_client(RedChannelClient *rcc)
@@ -1219,7 +1165,7 @@ static void snd_record_migrate_channel_client(RedChannelClient *rcc)
     spice_assert(channel);
 
     if (channel->connection) {
-        spice_assert(channel->connection->channel_client == rcc);
+        spice_assert(RED_CHANNEL_CLIENT(channel->connection) == rcc);
         snd_set_command(channel->connection, SND_MIGRATE_MASK);
         snd_send(channel->connection);
     }
@@ -1262,8 +1208,9 @@ static void snd_record_start(SndChannel *channel)
     SndChannelClient *client = channel->connection;
 
     channel->active = 1;
-    if (!client)
+    if (!client) {
         return;
+    }
     RecordChannelClient *record_client = RECORD_CHANNEL_CLIENT(client);
     spice_assert(!client->active);
     record_client->read_pos = record_client->write_pos = 0;   //todo: improve by
@@ -1332,7 +1279,7 @@ static uint32_t snd_get_best_rate(SndChannelClient *client, uint32_t cap_opus)
 {
     int client_can_opus = TRUE;
     if (client) {
-        client_can_opus = red_channel_client_test_remote_cap(client->channel_client, cap_opus);
+        client_can_opus = red_channel_client_test_remote_cap(RED_CHANNEL_CLIENT(client), cap_opus);
     }
 
     if (client_can_opus && snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_OPUS, SND_CODEC_ANY_FREQUENCY))
@@ -1397,46 +1344,60 @@ static void
 record_channel_client_constructed(GObject *object)
 {
     RecordChannelClient *record_client = RECORD_CHANNEL_CLIENT(object);
-    SndChannelClient *client = SND_CHANNEL_CLIENT(record_client);
-    RedChannel *red_channel = red_channel_client_get_channel(client->channel_client);
+    RedChannel *red_channel = red_channel_client_get_channel(RED_CHANNEL_CLIENT(record_client));
     SndChannel *channel = SND_CHANNEL(red_channel);
 
     G_OBJECT_CLASS(record_channel_client_parent_class)->constructed(object);
 
-    snd_channel_config_socket(RED_CHANNEL_CLIENT(client->channel_client));
-
-    /* SndChannelClient is not yet a RedChannelClient, but we still need to go from our
-     * RedChannelClient implementation (DummyChannelClient) to the SndChannelClient instance
-     * in various vfuncs
-     */
-    g_object_set_data(G_OBJECT(client->channel_client), "sound-channel-client", client);
-
     on_new_record_channel_client(channel, SND_CHANNEL_CLIENT(record_client));
     if (channel->active) {
         snd_record_start(channel);
     }
-    snd_send(channel->connection);
+    snd_send(SND_CHANNEL_CLIENT(record_client));
 }
 
+
 static void snd_set_record_peer(RedChannel *red_channel, RedClient *client, RedsStream *stream,
                                 G_GNUC_UNUSED int migration,
                                 int num_common_caps, uint32_t *common_caps,
                                 int num_caps, uint32_t *caps)
 {
     SndChannel *channel = SND_CHANNEL(red_channel);
+    GArray *common_caps_array = NULL, *caps_array = NULL;
     RecordChannelClient *record_client;
 
-    snd_disconnect_channel(channel->connection);
+    if (channel->connection) {
+        red_channel_client_disconnect(RED_CHANNEL_CLIENT(channel->connection));
+        channel->connection = NULL;
+    }
 
-    RedChannelClient *rcc =
-        dummy_channel_client_create(red_channel, client, stream,
-                                    num_common_caps, common_caps,
-                                    num_caps, caps);
-    record_client = g_object_new(TYPE_RECORD_CHANNEL_CLIENT, "channel-client", rcc, NULL);
-    g_object_unref(rcc);
+    if (common_caps) {
+        common_caps_array = g_array_sized_new(FALSE, FALSE, sizeof (*common_caps),
+                                              num_common_caps);
+        g_array_append_vals(common_caps_array, common_caps, num_common_caps);
+    }
+    if (caps) {
+        caps_array = g_array_sized_new(FALSE, FALSE, sizeof (*caps), num_caps);
+        g_array_append_vals(caps_array, caps, num_caps);
+    }
+
+    record_client = g_initable_new(TYPE_RECORD_CHANNEL_CLIENT,
+                                   NULL, NULL,
+                                   "channel", channel,
+                                   "client", client,
+                                   "stream", stream,
+                                   "caps", caps_array,
+                                   "common-caps", common_caps_array,
+                                   NULL);
     g_warn_if_fail(record_client != NULL);
-}
 
+    if (caps_array) {
+        g_array_unref(caps_array);
+    }
+    if (common_caps_array) {
+        g_array_unref(common_caps_array);
+    }
+}
 
 static void snd_playback_migrate_channel_client(RedChannelClient *rcc)
 {
@@ -1448,7 +1409,7 @@ static void snd_playback_migrate_channel_client(RedChannelClient *rcc)
     spice_debug(NULL);
 
     if (channel->connection) {
-        spice_assert(channel->connection->channel_client == rcc);
+        spice_assert(RED_CHANNEL_CLIENT(channel->connection) == rcc);
         snd_set_command(channel->connection, SND_MIGRATE_MASK);
         snd_send(channel->connection);
     }
@@ -1600,7 +1561,6 @@ static void snd_detach_common(SndChannel *channel)
     RedsState *reds = red_channel_get_server(RED_CHANNEL(channel));
 
     remove_channel(channel);
-    snd_disconnect_channel(channel->connection);
     reds_unregister_channel(reds, RED_CHANNEL(channel));
     free(channel->volume.volume);
     channel->volume.volume = NULL;
@@ -1626,7 +1586,7 @@ void snd_set_playback_compression(int on)
         g_object_get(RED_CHANNEL(now), "channel-type", &type, NULL);
         if (type == SPICE_CHANNEL_PLAYBACK && now->connection) {
             PlaybackChannelClient* playback = (PlaybackChannelClient*)now->connection;
-            RedChannelClient *rcc = SND_CHANNEL_CLIENT(playback)->channel_client;
+            RedChannelClient *rcc = RED_CHANNEL_CLIENT(playback);
             int client_can_celt = red_channel_client_test_remote_cap(rcc,
                                     SPICE_PLAYBACK_CAP_CELT_0_5_1);
             int client_can_opus = red_channel_client_test_remote_cap(rcc,
@@ -1642,20 +1602,8 @@ void snd_set_playback_compression(int on)
 }
 
 static void
-snd_channel_client_class_init(SndChannelClientClass *klass)
+snd_channel_client_class_init(SndChannelClientClass *self)
 {
-    GObjectClass *object_class = G_OBJECT_CLASS(klass);
-    GParamSpec *spec;
-
-    object_class->set_property = snd_channel_client_set_property;
-
-    spec = g_param_spec_object("channel-client", "channel-client",
-                               "Associated dummy RedChannelClient",
-                               RED_TYPE_CHANNEL_CLIENT,
-                               G_PARAM_STATIC_STRINGS
-                               | G_PARAM_WRITABLE
-                               | G_PARAM_CONSTRUCT_ONLY);
-    g_object_class_install_property(object_class, PROP_CHANNEL_CLIENT, spec);
 }
 
 static void
-- 
2.9.3



More information about the Spice-devel mailing list