[Spice-devel] [spice-server v2 09/10] sound: Turn {Playback, Record}ChannelClient into GObjects
Frediano Ziglio
fziglio at redhat.com
Thu Jan 26 07:55:03 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>
IMO this patch is too artificial, I would merge to 10/10
Frediano
> ---
> server/sound.c | 326
> +++++++++++++++++++++++++++++++++++++--------------------
> 1 file changed, 210 insertions(+), 116 deletions(-)
>
> diff --git a/server/sound.c b/server/sound.c
> index d0cfbf1..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,49 +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);
> - reds_stream_free(stream);
> - 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.
> @@ -729,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|
> @@ -788,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) {
> @@ -985,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;
> @@ -1015,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;
> }
> @@ -1118,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) {
> @@ -1136,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) {
> @@ -1180,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));
> }
>
> @@ -1190,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;
> @@ -1244,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
> @@ -1289,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) {
> @@ -1363,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,
> @@ -1379,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;
> @@ -1588,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);
> @@ -1602,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;
> @@ -1613,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;
> +}
More information about the Spice-devel
mailing list