[Spice-devel] [spice-server v3 09/10] sound: Turn {Playback, Record}ChannelClient into GObjects

Christophe Fergeau cfergeau at redhat.com
Thu Jan 26 11:13:20 UTC 2017


This is in preparation for making them inherit from RedChannelClient.
Doing it in one go would result in a very huge commit, so this commit
starts by turning these into GObjects, while still using a
DummyChannelClient instance for sending the data.

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

Signed-off-by: Christophe Fergeau <cfergeau at redhat.com>
---
 server/sound.c | 325 +++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 210 insertions(+), 115 deletions(-)

diff --git a/server/sound.c b/server/sound.c
index b629377..7738de4 100644
--- a/server/sound.c
+++ b/server/sound.c
@@ -83,14 +83,17 @@ typedef struct SpicePlaybackState PlaybackChannel;
 typedef struct SpiceRecordState RecordChannel;
 
 typedef void (*snd_channel_on_message_done_proc)(SndChannelClient *client);
-typedef void (*snd_channel_cleanup_channel_proc)(SndChannelClient *client);
 
-#define SND_CHANNEL_CLIENT(obj) (&(obj)->base)
+#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 {
-    int refs;
-
+    GObject parent;
     RedChannelClient *channel_client;
 
     int active;
@@ -104,9 +107,14 @@ struct SndChannelClient {
     RedPipeItem persistent_pipe_item;
 
     snd_channel_on_message_done_proc on_message_done;
-    snd_channel_cleanup_channel_proc cleanup;
 };
 
+typedef struct SndChannelClientClass {
+    GObjectClass parent_class;
+} SndChannelClientClass;
+
+G_DEFINE_TYPE(SndChannelClient, snd_channel_client, G_TYPE_OBJECT)
+
 
 enum {
     RED_PIPE_ITEM_PERSISTENT = RED_PIPE_ITEM_TYPE_CHANNEL_BASE,
@@ -129,8 +137,13 @@ struct AudioFrameContainer
     AudioFrame items[NUM_AUDIO_FRAMES];
 };
 
+#define TYPE_PLAYBACK_CHANNEL_CLIENT playback_channel_client_get_type()
+#define PLAYBACK_CHANNEL_CLIENT(obj) \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_PLAYBACK_CHANNEL_CLIENT, PlaybackChannelClient))
+GType playback_channel_client_get_type(void) G_GNUC_CONST;
+
 struct PlaybackChannelClient {
-    SndChannelClient base;
+    SndChannelClient parent;
 
     AudioFrameContainer *frames;
     AudioFrame *free_frames;
@@ -142,6 +155,13 @@ struct PlaybackChannelClient {
     uint8_t  encode_buf[SND_CODEC_MAX_COMPRESSED_BYTES];
 };
 
+typedef struct PlaybackChannelClientClass {
+    SndChannelClientClass parent_class;
+} PlaybackChannelClientClass;
+
+G_DEFINE_TYPE(PlaybackChannelClient, playback_channel_client, TYPE_SND_CHANNEL_CLIENT)
+
+
 typedef struct SpiceVolumeState {
     uint16_t *volume;
     uint8_t volume_nchannels;
@@ -202,8 +222,13 @@ typedef struct RecordChannelClass {
 G_DEFINE_TYPE(RecordChannel, record_channel, TYPE_SND_CHANNEL)
 
 
+#define TYPE_RECORD_CHANNEL_CLIENT record_channel_client_get_type()
+#define RECORD_CHANNEL_CLIENT(obj) \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_RECORD_CHANNEL_CLIENT, RecordChannelClient))
+GType record_channel_client_get_type(void) G_GNUC_CONST;
+
 struct RecordChannelClient {
-    SndChannelClient base;
+    SndChannelClient parent;
     uint32_t samples[RECORD_SAMPLES_SIZE];
     uint32_t write_pos;
     uint32_t read_pos;
@@ -214,22 +239,41 @@ struct RecordChannelClient {
     uint8_t  decode_buf[SND_CODEC_MAX_FRAME_BYTES];
 };
 
+typedef struct RecordChannelClientClass {
+    SndChannelClientClass parent_class;
+} RecordChannelClientClass;
+
+G_DEFINE_TYPE(RecordChannelClient, record_channel_client, TYPE_SND_CHANNEL_CLIENT)
+
+
 /* A list of all Spice{Playback,Record}State objects */
 static SndChannel *snd_channels;
 
 static void snd_playback_start(SndChannel *channel);
 static void snd_record_start(SndChannel *channel);
-static void snd_playback_alloc_frames(PlaybackChannelClient *playback);
 static void snd_send(SndChannelClient * client);
 
-static SndChannelClient *snd_channel_unref(SndChannelClient *client)
+enum {
+    PROP0,
+    PROP_CHANNEL_CLIENT
+};
+
+static void
+snd_channel_client_set_property(GObject *object,
+                                guint property_id,
+                                const GValue *value,
+                                GParamSpec *pspec)
 {
-    if (!--client->refs) {
-        spice_printerr("SndChannelClient=%p freed", client);
-        free(client);
-        return NULL;
+    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);
     }
-    return client;
 }
 
 static SndChannelClient *snd_channel_client_from_dummy(RedChannelClient *dummy)
@@ -238,6 +282,7 @@ static SndChannelClient *snd_channel_client_from_dummy(RedChannelClient *dummy)
 
     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;
 }
@@ -263,10 +308,9 @@ static void snd_disconnect_channel(SndChannelClient *client)
     spice_debug("SndChannelClient=%p rcc=%p type=%d",
                  client, client->channel_client, type);
     channel = SND_CHANNEL(red_channel);
-    client->cleanup(client);
     red_channel_client_disconnect(channel->connection->channel_client);
     channel->connection->channel_client = NULL;
-    snd_channel_unref(client);
+    g_object_unref(client);
     channel->connection = NULL;
 }
 
@@ -290,10 +334,6 @@ static void snd_playback_on_message_done(SndChannelClient *client)
     }
 }
 
-static void snd_record_on_message_done(SndChannelClient *client)
-{
-}
-
 static int snd_record_handle_write(RecordChannelClient *record_client, size_t size, void *message)
 {
     SpiceMsgcRecordPacket *packet;
@@ -355,7 +395,7 @@ 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 = SPICE_CONTAINEROF(snd_client, RecordChannelClient, base);
+    RecordChannelClient *record_client = RECORD_CHANNEL_CLIENT(snd_client);
 
     switch (type) {
     case SPICE_MSGC_RECORD_DATA:
@@ -648,48 +688,6 @@ static int playback_send_mode(PlaybackChannelClient *playback_client)
     return TRUE;
 }
 
-static int snd_channel_config_socket(RedChannelClient *rcc);
-
-static SndChannelClient *__new_channel(SndChannel *channel, int size, uint32_t channel_id,
-                                       RedClient *red_client,
-                                       RedsStream *stream,
-                                       snd_channel_on_message_done_proc on_message_done,
-                                       snd_channel_cleanup_channel_proc cleanup,
-                                       uint32_t *common_caps, int num_common_caps,
-                                       uint32_t *caps, int num_caps)
-{
-    SndChannelClient *client;
-
-    spice_assert(size >= sizeof(*client));
-    client = spice_malloc0(size);
-    client->refs = 1;
-    client->on_message_done = on_message_done;
-    client->cleanup = cleanup;
-
-    client->channel_client =
-        dummy_channel_client_create(RED_CHANNEL(channel), red_client, stream,
-                                    num_common_caps, common_caps, num_caps, caps);
-    if (!client->channel_client) {
-        goto error2;
-    }
-
-    /* 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);
-
-    if (!snd_channel_config_socket(RED_CHANNEL_CLIENT(client->channel_client))) {
-        goto error2;
-    }
-
-    return client;
-
-error2:
-    free(client);
-    return NULL;
-}
-
 /* This function is called when the "persistent" item is removed from the
  * queue. Note that there is not free call as the item is allocated into
  * SndChannelClient.
@@ -728,7 +726,7 @@ 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 = SPICE_CONTAINEROF(client, PlaybackChannelClient, base);
+    PlaybackChannelClient *playback_client = PLAYBACK_CHANNEL_CLIENT(client);
 
     client->command &= SND_PLAYBACK_MODE_MASK|SND_PLAYBACK_PCM_MASK|
                        SND_CTRL_MASK|SND_VOLUME_MUTE_MASK|
@@ -787,7 +785,7 @@ 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 = SPICE_CONTAINEROF(client, RecordChannelClient, base);
+    RecordChannelClient *record_client = RECORD_CHANNEL_CLIENT(client);
 
     client->command &= SND_CTRL_MASK|SND_VOLUME_MUTE_MASK|SND_MIGRATE_MASK;
     while (client->command) {
@@ -984,7 +982,7 @@ SPICE_GNUC_VISIBLE void spice_server_playback_stop(SpicePlaybackInstance *sin)
     sin->st->channel.active = 0;
     if (!client)
         return;
-    PlaybackChannelClient *playback_client = SPICE_CONTAINEROF(client, PlaybackChannelClient, base);
+    PlaybackChannelClient *playback_client = PLAYBACK_CHANNEL_CLIENT(client);
     spice_assert(client->active);
     reds_enable_mm_time(snd_channel_get_server(client));
     client->active = FALSE;
@@ -1014,7 +1012,7 @@ SPICE_GNUC_VISIBLE void spice_server_playback_get_buffer(SpicePlaybackInstance *
     if (!client) {
         return;
     }
-    PlaybackChannelClient *playback_client = SPICE_CONTAINEROF(client, PlaybackChannelClient, base);
+    PlaybackChannelClient *playback_client = PLAYBACK_CHANNEL_CLIENT(client);
     if (!playback_client->free_frames) {
         return;
     }
@@ -1117,10 +1115,12 @@ static void on_new_playback_channel_client(SndChannel *channel, SndChannelClient
     }
 }
 
-static void snd_playback_cleanup(SndChannelClient *client)
+static void
+playback_channel_client_finalize(GObject *object)
 {
-    PlaybackChannelClient *playback_client = SPICE_CONTAINEROF(client, PlaybackChannelClient, base);
     int i;
+    PlaybackChannelClient *playback_client = PLAYBACK_CHANNEL_CLIENT(object);
+    SndChannelClient *client = SND_CHANNEL_CLIENT(playback_client);
 
     // free frames, unref them
     for (i = 0; i < NUM_AUDIO_FRAMES; ++i) {
@@ -1135,41 +1135,42 @@ static void snd_playback_cleanup(SndChannelClient *client)
     }
 
     snd_codec_destroy(&playback_client->codec);
+
+    G_OBJECT_CLASS(playback_channel_client_parent_class)->finalize(object);
 }
 
-static void snd_set_playback_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)
+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);
     SndChannel *channel = SND_CHANNEL(red_channel);
-    PlaybackChannelClient *playback_client;
 
-    snd_disconnect_channel(channel->connection);
+    G_OBJECT_CLASS(playback_channel_client_parent_class)->constructed(object);
 
-    if (!(playback_client = (PlaybackChannelClient *)__new_channel(channel,
-                                                                   sizeof(*playback_client),
-                                                                   SPICE_CHANNEL_PLAYBACK,
-                                                                   client,
-                                                                   stream,
-                                                                   snd_playback_on_message_done,
-                                                                   snd_playback_cleanup,
-                                                                   common_caps, num_common_caps,
-                                                                   caps, num_caps))) {
-        return;
+    if (!snd_channel_config_socket(RED_CHANNEL_CLIENT(client->channel_client))) {
+        g_warning("failed to set sound channel socket parameters");
     }
 
-    snd_playback_alloc_frames(playback_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);
 
-    int client_can_celt = red_channel_client_test_remote_cap(playback_client->base.channel_client,
+    SND_CHANNEL_CLIENT(playback_client)->on_message_done = snd_playback_on_message_done;
+
+    RedChannelClient *rcc = client->channel_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(playback_client->base.channel_client,
+    int client_can_opus = red_channel_client_test_remote_cap(rcc,
                                           SPICE_PLAYBACK_CAP_OPUS);
     int playback_compression =
         reds_config_get_playback_compression(red_channel_get_server(red_channel));
     int desired_mode = snd_desired_audio_mode(playback_compression, channel->frequency,
                                               client_can_celt, client_can_opus);
-    playback_client->mode = SPICE_AUDIO_DATA_MODE_RAW;
     if (desired_mode != SPICE_AUDIO_DATA_MODE_RAW) {
         if (snd_codec_create(&playback_client->codec, desired_mode, channel->frequency,
                              SND_CODEC_ENCODE) == SND_CODEC_OK) {
@@ -1179,7 +1180,7 @@ static void snd_set_playback_peer(RedChannel *red_channel, RedClient *client, Re
         }
     }
 
-    if (!red_client_during_migrate_at_target(client)) {
+    if (!red_client_during_migrate_at_target(red_client)) {
         on_new_playback_channel_client(channel, SND_CHANNEL_CLIENT(playback_client));
     }
 
@@ -1189,6 +1190,28 @@ static void snd_set_playback_peer(RedChannel *red_channel, RedClient *client, Re
     snd_send(channel->connection);
 }
 
+static void snd_set_playback_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);
+    PlaybackChannelClient *playback_client;
+
+    snd_disconnect_channel(channel->connection);
+
+    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);
+    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
+     */
+}
+
 static void snd_record_migrate_channel_client(RedChannelClient *rcc)
 {
     SndChannel *channel;
@@ -1243,7 +1266,7 @@ static void snd_record_start(SndChannel *channel)
     channel->active = 1;
     if (!client)
         return;
-    RecordChannelClient *record_client = SPICE_CONTAINEROF(client, RecordChannelClient, base);
+    RecordChannelClient *record_client = RECORD_CHANNEL_CLIENT(client);
     spice_assert(!client->active);
     record_client->read_pos = record_client->write_pos = 0;   //todo: improve by
                                                               //stream generation
@@ -1288,7 +1311,7 @@ SPICE_GNUC_VISIBLE uint32_t spice_server_record_get_samples(SpiceRecordInstance
 
     if (!client)
         return 0;
-    RecordChannelClient *record_client = SPICE_CONTAINEROF(client, RecordChannelClient, base);
+    RecordChannelClient *record_client = RECORD_CHANNEL_CLIENT(client);
     spice_assert(client->active);
 
     if (record_client->write_pos < RECORD_SAMPLES_SIZE / 2) {
@@ -1362,10 +1385,41 @@ static void on_new_record_channel_client(SndChannel *channel, SndChannelClient *
     }
 }
 
-static void snd_record_cleanup(SndChannelClient *client)
+static void
+record_channel_client_finalize(GObject *object)
 {
-    RecordChannelClient *record_client = SPICE_CONTAINEROF(client, RecordChannelClient, base);
+    RecordChannelClient *record_client = RECORD_CHANNEL_CLIENT(object);
+
     snd_codec_destroy(&record_client->codec);
+
+    G_OBJECT_CLASS(record_channel_client_parent_class)->finalize(object);
+}
+
+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);
+    SndChannel *channel = SND_CHANNEL(red_channel);
+
+    G_OBJECT_CLASS(record_channel_client_parent_class)->constructed(object);
+
+    if (!snd_channel_config_socket(RED_CHANNEL_CLIENT(client->channel_client))) {
+        g_warning("failed to set sound channel socket parameters");
+    }
+
+    /* 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);
 }
 
 static void snd_set_record_peer(RedChannel *red_channel, RedClient *client, RedsStream *stream,
@@ -1378,27 +1432,16 @@ static void snd_set_record_peer(RedChannel *red_channel, RedClient *client, Reds
 
     snd_disconnect_channel(channel->connection);
 
-    if (!(record_client = (RecordChannelClient *)__new_channel(channel,
-                                                               sizeof(*record_client),
-                                                               SPICE_CHANNEL_RECORD,
-                                                               client,
-                                                               stream,
-                                                               snd_record_on_message_done,
-                                                               snd_record_cleanup,
-                                                               common_caps, num_common_caps,
-                                                               caps, num_caps))) {
-        return;
-    }
-
-    record_client->mode = SPICE_AUDIO_DATA_MODE_RAW;
-
-    on_new_record_channel_client(channel, SND_CHANNEL_CLIENT(record_client));
-    if (channel->active) {
-        snd_record_start(channel);
-    }
-    snd_send(channel->connection);
+    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);
+    g_warn_if_fail(record_client != NULL);
 }
 
+
 static void snd_playback_migrate_channel_client(RedChannelClient *rcc)
 {
     SndChannel *channel;
@@ -1587,9 +1630,10 @@ 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;
-            int client_can_celt = red_channel_client_test_remote_cap(playback->base.channel_client,
+            RedChannelClient *rcc = SND_CHANNEL_CLIENT(playback)->channel_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(playback->base.channel_client,
+            int client_can_opus = red_channel_client_test_remote_cap(rcc,
                                     SPICE_PLAYBACK_CAP_OPUS);
             int desired_mode = snd_desired_audio_mode(on, now->frequency,
                                                       client_can_opus, client_can_celt);
@@ -1601,6 +1645,36 @@ void snd_set_playback_compression(int on)
     }
 }
 
+static void
+snd_channel_client_class_init(SndChannelClientClass *klass)
+{
+    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
+snd_channel_client_init(SndChannelClient *self)
+{
+}
+
+static void
+playback_channel_client_class_init(PlaybackChannelClientClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS(klass);
+    object_class->constructed = playback_channel_client_constructed;
+    object_class->finalize = playback_channel_client_finalize;
+}
+
 static void snd_playback_alloc_frames(PlaybackChannelClient *playback)
 {
     int i;
@@ -1612,3 +1686,24 @@ static void snd_playback_alloc_frames(PlaybackChannelClient *playback)
         snd_playback_free_frame(playback, &playback->frames->items[i]);
     }
 }
+
+static void
+playback_channel_client_init(PlaybackChannelClient *playback)
+{
+    playback->mode = SPICE_AUDIO_DATA_MODE_RAW;
+    snd_playback_alloc_frames(playback);
+}
+
+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;
+}
+
+static void
+record_channel_client_init(RecordChannelClient *record)
+{
+    record->mode = SPICE_AUDIO_DATA_MODE_RAW;
+}
-- 
2.9.3



More information about the Spice-devel mailing list