[Spice-devel] [PATCH spice-server v2 7/8] Convert RedChannel heirarchy to GObject
Frediano Ziglio
fziglio at redhat.com
Mon Oct 10 16:48:06 UTC 2016
> Subject: [Spice-devel] [PATCH spice-server v2 7/8] Convert RedChannel heirarchy to GObject
>
Small spell, it's "hierarchy".
> From: Jonathon Jongsma <jjongsma at redhat.com>
>
> FIXME: this commit appears to introduce a vdagent-related crash in
> vdi_port_read_one_msg_from_device(). sin->st is NULL.
If this is still true I would fix it.
> ---
> server/Makefile.am | 2 +
> server/common-graphics-channel.c | 109 ++++--
> server/common-graphics-channel.h | 39 ++-
> server/cursor-channel.c | 80 +++--
> server/cursor-channel.h | 31 +-
> server/dcc-send.c | 11 +-
> server/dcc.c | 1 +
> server/dcc.h | 2 +-
> server/display-channel-private.h | 76 +++++
> server/display-channel.c | 261 +++++++++++----
> server/display-channel.h | 127 +++----
> server/dummy-channel-client.c | 17 +-
> server/dummy-channel.c | 58 ++++
> server/dummy-channel.h | 61 ++++
> server/inputs-channel.c | 263 +++++++++------
> server/inputs-channel.h | 30 +-
> server/main-channel-client.c | 65 ++--
> server/main-channel-client.h | 5 +-
> server/main-channel.c | 196 +++++++----
> server/main-channel.h | 44 ++-
> server/red-channel-client-private.h | 19 ++
> server/red-channel-client.c | 179 ++++++----
> server/red-channel-client.h | 6 +-
> server/red-channel.c | 645
> ++++++++++++++++++++++++------------
> server/red-channel.h | 180 +++++-----
> server/red-parse-qxl.h | 2 +
> server/red-qxl.c | 21 +-
> server/red-replay-qxl.c | 2 +-
> server/red-worker.c | 27 +-
> server/red-worker.h | 2 -
> server/reds-private.h | 3 +-
> server/reds.c | 66 ++--
> server/smartcard.c | 127 +++++--
> server/sound.c | 43 ++-
> server/spicevmc.c | 429 ++++++++++++++++++------
> server/stream.c | 4 +-
> server/stream.h | 3 -
> 37 files changed, 2192 insertions(+), 1044 deletions(-)
> create mode 100644 server/display-channel-private.h
> create mode 100644 server/dummy-channel.c
> create mode 100644 server/dummy-channel.h
I imagined this DummyChannel* would be viral... already in
my TODO list.
>
> diff --git a/server/Makefile.am b/server/Makefile.am
> index 036abcd..c809330 100644
> --- a/server/Makefile.am
> +++ b/server/Makefile.am
> @@ -102,6 +102,8 @@ libserver_la_SOURCES = \
> red-channel-client.c \
> red-channel-client.h \
> red-channel-client-private.h \
> + dummy-channel.c \
> + dummy-channel.h \
> dummy-channel-client.c \
> dummy-channel-client.h \
> red-common.h \
> diff --git a/server/common-graphics-channel.c
> b/server/common-graphics-channel.c
> index 6871540..d8ee9dd 100644
> --- a/server/common-graphics-channel.c
> +++ b/server/common-graphics-channel.c
> @@ -29,6 +29,10 @@
>
> #define CHANNEL_RECEIVE_BUF_SIZE 1024
>
> +G_DEFINE_ABSTRACT_TYPE(CommonGraphicsChannel, common_graphics_channel,
> RED_TYPE_CHANNEL)
> +
> +#define GRAPHICS_CHANNEL_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o),
> TYPE_COMMON_GRAPHICS_CHANNEL, CommonGraphicsChannelPrivate))
> +
> struct CommonGraphicsChannelPrivate
> {
> QXLInstance *qxl;
> @@ -44,7 +48,7 @@ struct CommonGraphicsChannelPrivate
> static uint8_t *common_alloc_recv_buf(RedChannelClient *rcc, uint16_t type,
> uint32_t size)
> {
> RedChannel *channel = red_channel_client_get_channel(rcc);
> - CommonGraphicsChannel *common = SPICE_CONTAINEROF(channel,
> CommonGraphicsChannel, base);
> + CommonGraphicsChannel *common = COMMON_GRAPHICS_CHANNEL(channel);
>
> /* SPICE_MSGC_MIGRATE_DATA is the only client message whose size is
> dynamic */
> if (type == SPICE_MSGC_MIGRATE_DATA) {
> @@ -66,6 +70,48 @@ static void common_release_recv_buf(RedChannelClient *rcc,
> uint16_t type, uint32
> }
> }
>
> +
> +enum {
> + PROP0,
> + PROP_QXL
> +};
> +
I remember I had some patches to remove this field... in my TODO list...
> +static void
> +common_graphics_channel_get_property(GObject *object,
> + guint property_id,
> + GValue *value,
> + GParamSpec *pspec)
> +{
> + CommonGraphicsChannel *self = COMMON_GRAPHICS_CHANNEL(object);
> +
> + switch (property_id)
> + {
> + case PROP_QXL:
> + g_value_set_pointer(value, self->priv->qxl);
> + break;
> + default:
> + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
> + }
> +}
> +
> +static void
> +common_graphics_channel_set_property(GObject *object,
> + guint property_id,
> + const GValue *value,
> + GParamSpec *pspec)
> +{
> + CommonGraphicsChannel *self = COMMON_GRAPHICS_CHANNEL(object);
> +
> + switch (property_id)
> + {
> + case PROP_QXL:
> + self->priv->qxl = g_value_get_pointer(value);
> + break;
> + default:
> + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
> + }
> +}
> +
> int common_channel_config_socket(RedChannelClient *rcc)
> {
> RedClient *client = red_channel_client_get_client(rcc);
> @@ -107,39 +153,36 @@ int common_channel_config_socket(RedChannelClient *rcc)
> return TRUE;
> }
>
> -CommonGraphicsChannel* common_graphics_channel_new(RedsState *server,
> - QXLInstance *qxl,
> - const
> SpiceCoreInterfaceInternal *core,
> - int size, uint32_t
> channel_type,
> - int migration_flags,
> - ChannelCbs *channel_cbs,
> -
> channel_handle_parsed_proc
> handle_parsed)
> +
> +static void
> +common_graphics_channel_class_init(CommonGraphicsChannelClass *klass)
> +{
> + GObjectClass *object_class = G_OBJECT_CLASS(klass);
> + RedChannelClass *channel_class = RED_CHANNEL_CLASS(klass);
> +
> + g_type_class_add_private(klass, sizeof(CommonGraphicsChannelPrivate));
> +
> + object_class->get_property = common_graphics_channel_get_property;
> + object_class->set_property = common_graphics_channel_set_property;
> +
> + channel_class->config_socket = common_channel_config_socket;
> + channel_class->alloc_recv_buf = common_alloc_recv_buf;
> + channel_class->release_recv_buf = common_release_recv_buf;
> +
> + g_object_class_install_property(object_class,
> + PROP_QXL,
> + g_param_spec_pointer("qxl",
> + "qxl",
> + "QXLInstance for
> this channel",
> + G_PARAM_READWRITE |
> +
> G_PARAM_CONSTRUCT_ONLY
> |
> +
> G_PARAM_STATIC_STRINGS));
> +}
> +
> +static void
> +common_graphics_channel_init(CommonGraphicsChannel *self)
> {
> - RedChannel *channel = NULL;
> - CommonGraphicsChannel *common;
> -
> - spice_return_val_if_fail(channel_cbs, NULL);
> - spice_return_val_if_fail(!channel_cbs->alloc_recv_buf, NULL);
> - spice_return_val_if_fail(!channel_cbs->release_recv_buf, NULL);
> -
> - if (!channel_cbs->config_socket)
> - channel_cbs->config_socket = common_channel_config_socket;
> - channel_cbs->alloc_recv_buf = common_alloc_recv_buf;
> - channel_cbs->release_recv_buf = common_release_recv_buf;
> -
> - channel = red_channel_create_parser(size, server,
> - core, channel_type,
> - qxl->id, TRUE /* handle_acks */,
> -
> spice_get_client_channel_parser(channel_type,
> NULL),
> - handle_parsed,
> - channel_cbs,
> - migration_flags);
> - spice_return_val_if_fail(channel, NULL);
> -
> - common = COMMON_GRAPHICS_CHANNEL(channel);
> - common->priv = g_new0(CommonGraphicsChannelPrivate, 1);
> - common->priv->qxl = qxl;
> - return common;
> + self->priv = GRAPHICS_CHANNEL_PRIVATE(self);
> }
>
> void common_graphics_channel_set_during_target_migrate(CommonGraphicsChannel
> *self, gboolean value)
> diff --git a/server/common-graphics-channel.h
> b/server/common-graphics-channel.h
> index c6c3f48..6961375 100644
> --- a/server/common-graphics-channel.h
> +++ b/server/common-graphics-channel.h
> @@ -18,21 +18,42 @@
> #ifndef _COMMON_GRAPHICS_CHANNEL_H
> #define _COMMON_GRAPHICS_CHANNEL_H
>
> +#include <glib-object.h>
> +
> #include "red-channel.h"
> -#include "red-worker.h"
> +#include "red-channel-client.h"
> +
> +G_BEGIN_DECLS
>
> int common_channel_config_socket(RedChannelClient *rcc);
>
> #define COMMON_CLIENT_TIMEOUT (NSEC_PER_SEC * 30)
>
> +#define TYPE_COMMON_GRAPHICS_CHANNEL common_graphics_channel_get_type()
> +
> +#define COMMON_GRAPHICS_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),
> TYPE_COMMON_GRAPHICS_CHANNEL, CommonGraphicsChannel))
> +#define COMMON_GRAPHICS_CHANNEL_CLASS(klass)
> (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_COMMON_GRAPHICS_CHANNEL,
> CommonGraphicsChannelClass))
> +#define COMMON_IS_GRAPHICS_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),
> TYPE_COMMON_GRAPHICS_CHANNEL))
> +#define COMMON_IS_GRAPHICS_CHANNEL_CLASS(klass)
> (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_COMMON_GRAPHICS_CHANNEL))
> +#define COMMON_GRAPHICS_CHANNEL_GET_CLASS(obj)
> (G_TYPE_INSTANCE_GET_CLASS((obj), TYPE_COMMON_GRAPHICS_CHANNEL,
> CommonGraphicsChannelClass))
> +
> +typedef struct CommonGraphicsChannel CommonGraphicsChannel;
> +typedef struct CommonGraphicsChannelClass CommonGraphicsChannelClass;
> typedef struct CommonGraphicsChannelPrivate CommonGraphicsChannelPrivate;
> -typedef struct CommonGraphicsChannel {
> - RedChannel base; // Must be the first thing
> +
> +struct CommonGraphicsChannel
> +{
> + RedChannel parent;
>
> CommonGraphicsChannelPrivate *priv;
> -} CommonGraphicsChannel;
> +};
> +
> +struct CommonGraphicsChannelClass
> +{
> + RedChannelClass parent_class;
> +};
>
> -#define COMMON_GRAPHICS_CHANNEL(Channel) ((CommonGraphicsChannel*)(Channel))
> +GType common_graphics_channel_get_type(void) G_GNUC_CONST;
>
> void common_graphics_channel_set_during_target_migrate(CommonGraphicsChannel
> *self, gboolean value);
> gboolean
> common_graphics_channel_get_during_target_migrate(CommonGraphicsChannel
> *self);
> @@ -76,12 +97,6 @@ static inline void red_pipes_add_verb(RedChannel *channel,
> uint16_t verb)
> red_channel_apply_clients_data(channel, red_pipe_add_verb_proxy,
> GUINT_TO_POINTER(verb));
> }
>
> -CommonGraphicsChannel* common_graphics_channel_new(RedsState *server,
> - QXLInstance *qxl,
> - const
> SpiceCoreInterfaceInternal *core,
> - int size, uint32_t
> channel_type,
> - int migration_flags,
> - ChannelCbs *channel_cbs,
> -
> channel_handle_parsed_proc
> handle_parsed);
> +G_END_DECLS
>
> #endif /* _COMMON_GRAPHICS_CHANNEL_H */
> diff --git a/server/cursor-channel.c b/server/cursor-channel.c
> index f796c8c..cf19c7f 100644
> --- a/server/cursor-channel.c
> +++ b/server/cursor-channel.c
> @@ -26,8 +26,7 @@
> #include "cursor-channel.h"
> #include "cursor-channel-client.h"
> #include "reds.h"
> -
> -#define CURSOR_CHANNEL(channel) ((CursorChannel*)(channel))
> +#include "red-qxl.h"
>
> typedef struct CursorChannelClient CursorChannelClient;
>
> @@ -50,8 +49,12 @@ typedef struct RedCursorPipeItem {
> CursorItem *cursor_item;
> } RedCursorPipeItem;
>
> -typedef struct CursorChannelPrivate CursorChannelPrivate;
> -struct CursorChannelPrivate {
> +G_DEFINE_TYPE(CursorChannel, cursor_channel, TYPE_COMMON_GRAPHICS_CHANNEL)
> +
> +#define CURSOR_CHANNEL_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o),
> TYPE_CURSOR_CHANNEL, CursorChannelPrivate))
> +
> +struct CursorChannelPrivate
> +{
> CursorItem *item;
> int cursor_visible;
> SpicePoint16 cursor_position;
> @@ -60,12 +63,6 @@ struct CursorChannelPrivate {
> uint32_t mouse_mode;
> };
>
> -struct CursorChannel {
> - CommonGraphicsChannel common; // Must be the first thing
> -
> - CursorChannelPrivate priv[1];
> -};
> -
> static void cursor_pipe_item_free(RedPipeItem *pipe_item);
>
> static CursorItem *cursor_item_new(QXLInstance *qxl, RedCursorCmd *cmd)
> @@ -219,8 +216,7 @@ static void cursor_marshall(CursorChannelClient *ccc,
> RedCursorPipeItem *cursor_pipe_item)
> {
> RedChannelClient *rcc = RED_CHANNEL_CLIENT(ccc);
> - CursorChannel *cursor_channel =
> SPICE_CONTAINEROF(red_channel_client_get_channel(rcc),
> - CursorChannel,
> common.base);
> + CursorChannel *cursor_channel =
> CURSOR_CHANNEL(red_channel_client_get_channel(rcc));
> CursorItem *item = cursor_pipe_item->cursor_item;
> RedPipeItem *pipe_item = &cursor_pipe_item->base;
> RedCursorCmd *cmd;
> @@ -314,24 +310,14 @@ static void cursor_channel_send_item(RedChannelClient
> *rcc, RedPipeItem *pipe_it
> CursorChannel* cursor_channel_new(RedsState *server, QXLInstance *qxl,
> const SpiceCoreInterfaceInternal *core)
> {
> - CursorChannel *cursor_channel;
> - CommonGraphicsChannel *channel = NULL;
> - ChannelCbs cbs = {
> - .on_disconnect = cursor_channel_client_on_disconnect,
> - .send_item = cursor_channel_send_item,
> - };
> -
> spice_info("create cursor channel");
> - channel = common_graphics_channel_new(server, qxl, core,
> - sizeof(CursorChannel),
> - SPICE_CHANNEL_CURSOR, 0,
> - &cbs,
> red_channel_client_handle_message);
> -
> - cursor_channel = CURSOR_CHANNEL(channel);
> - cursor_channel->priv->cursor_visible = TRUE;
> - cursor_channel->priv->mouse_mode = SPICE_MOUSE_MODE_SERVER;
> -
> - return cursor_channel;
> + return g_object_new(TYPE_CURSOR_CHANNEL,
> + "spice-server", server,
> + "core-interface", core,
> + "channel-type", SPICE_CHANNEL_CURSOR,
> + "migration-flags", 0,
> + "qxl", qxl,
> + NULL);
> }
>
> void cursor_channel_process_cmd(CursorChannel *cursor, RedCursorCmd
> *cursor_cmd)
> @@ -368,11 +354,11 @@ void cursor_channel_process_cmd(CursorChannel *cursor,
> RedCursorCmd *cursor_cmd)
> return;
> }
>
> - if (red_channel_is_connected(&cursor->common.base) &&
> + if (red_channel_is_connected(RED_CHANNEL(cursor)) &&
> (cursor->priv->mouse_mode == SPICE_MOUSE_MODE_SERVER
> || cursor_cmd->type != QXL_CURSOR_MOVE
> || cursor_show)) {
> - red_channel_pipes_new_add(&cursor->common.base,
> + red_channel_pipes_new_add(RED_CHANNEL(cursor),
> new_cursor_pipe_item, cursor_item);
> }
>
> @@ -381,7 +367,7 @@ void cursor_channel_process_cmd(CursorChannel *cursor,
> RedCursorCmd *cursor_cmd)
>
> void cursor_channel_reset(CursorChannel *cursor)
> {
> - RedChannel *channel = &cursor->common.base;
> + RedChannel *channel = RED_CHANNEL(cursor);
>
> spice_return_if_fail(cursor);
>
> @@ -395,9 +381,9 @@ void cursor_channel_reset(CursorChannel *cursor)
> if
> (!common_graphics_channel_get_during_target_migrate(COMMON_GRAPHICS_CHANNEL(cursor)))
> {
> red_pipes_add_verb(channel, SPICE_MSG_CURSOR_RESET);
> }
> - if (!red_channel_wait_all_sent(&cursor->common.base,
> + if (!red_channel_wait_all_sent(RED_CHANNEL(cursor),
> COMMON_CLIENT_TIMEOUT)) {
> - red_channel_apply_clients(channel,
> + red_channel_apply_clients(RED_CHANNEL(cursor),
Why not using channel variable ??
> red_channel_client_disconnect_if_pending_send);
> }
> }
> @@ -407,7 +393,7 @@ static void cursor_channel_init_client(CursorChannel
> *cursor, CursorChannelClien
> {
> spice_return_if_fail(cursor);
>
> - if (!red_channel_is_connected(&cursor->common.base)
> + if (!red_channel_is_connected(RED_CHANNEL(cursor))
> || common_graphics_channel_get_during_target_migrate(COMMON_GRAPHICS_CHANNEL(cursor)))
> || {
> spice_debug("during_target_migrate: skip init");
> return;
> @@ -420,7 +406,7 @@ static void cursor_channel_init_client(CursorChannel
> *cursor, CursorChannelClien
> red_channel_pipes_add_type(RED_CHANNEL(cursor),
> RED_PIPE_ITEM_TYPE_CURSOR_INIT);
> }
>
> -void cursor_channel_init(CursorChannel *cursor)
> +void cursor_channel_do_init(CursorChannel *cursor)
> {
> cursor_channel_init_client(cursor, NULL);
> }
> @@ -454,3 +440,25 @@ void cursor_channel_connect(CursorChannel *cursor,
> RedClient *client, RedsStream
>
> cursor_channel_init_client(cursor, ccc);
> }
> +
> +static void
> +cursor_channel_class_init(CursorChannelClass *klass)
> +{
> + RedChannelClass *channel_class = RED_CHANNEL_CLASS(klass);
> +
> + g_type_class_add_private(klass, sizeof(CursorChannelPrivate));
> +
> + channel_class->parser =
> spice_get_client_channel_parser(SPICE_CHANNEL_CURSOR, NULL);
> + channel_class->handle_parsed = red_channel_client_handle_message;
> +
> + channel_class->on_disconnect = cursor_channel_client_on_disconnect;
> + channel_class->send_item = cursor_channel_send_item;
> +}
> +
> +static void
> +cursor_channel_init(CursorChannel *self)
> +{
> + self->priv = CURSOR_CHANNEL_PRIVATE(self);
> + self->priv->cursor_visible = TRUE;
> + self->priv->mouse_mode = SPICE_MOUSE_MODE_SERVER;
> +}
> diff --git a/server/cursor-channel.h b/server/cursor-channel.h
> index a3ddaa3..8b3bc17 100644
> --- a/server/cursor-channel.h
> +++ b/server/cursor-channel.h
> @@ -19,6 +19,17 @@
> # define CURSOR_CHANNEL_H_
>
> #include "common-graphics-channel.h"
> +#include "red-parse-qxl.h"
> +
> +G_BEGIN_DECLS
> +
> +#define TYPE_CURSOR_CHANNEL cursor_channel_get_type()
> +
> +#define CURSOR_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),
> TYPE_CURSOR_CHANNEL, CursorChannel))
> +#define CURSOR_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),
> TYPE_CURSOR_CHANNEL, CursorChannelClass))
> +#define IS_CURSOR_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),
> TYPE_CURSOR_CHANNEL))
> +#define IS_CURSOR_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),
> TYPE_CURSOR_CHANNEL))
> +#define CURSOR_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),
> TYPE_CURSOR_CHANNEL, CursorChannelClass))
>
> /**
> * This type it's a RedChannel class which implement cursor (mouse)
> @@ -26,6 +37,22 @@
> * A pointer to CursorChannel can be converted to a RedChannel.
> */
> typedef struct CursorChannel CursorChannel;
> +typedef struct CursorChannelClass CursorChannelClass;
> +typedef struct CursorChannelPrivate CursorChannelPrivate;
> +
> +struct CursorChannel
> +{
> + CommonGraphicsChannel parent;
> +
> + CursorChannelPrivate *priv;
> +};
> +
> +struct CursorChannelClass
> +{
> + CommonGraphicsChannelClass parent_class;
> +};
> +
> +GType cursor_channel_get_type(void) G_GNUC_CONST;
>
Why we need to expose this here ? On the C file is not enough ?
> /**
> * Create CursorChannel.
> @@ -47,7 +74,7 @@ CursorChannel* cursor_channel_new (RedsState
> *server, QXLInstance
> */
> void cursor_channel_disconnect (CursorChannel *cursor);
> void cursor_channel_reset (CursorChannel *cursor);
> -void cursor_channel_init (CursorChannel *cursor);
> +void cursor_channel_do_init (CursorChannel *cursor);
> void cursor_channel_process_cmd (CursorChannel *cursor,
> RedCursorCmd *cursor_cmd);
> void cursor_channel_set_mouse_mode(CursorChannel *cursor,
> uint32_t mode);
>
> @@ -69,4 +96,6 @@ void cursor_channel_connect
> (CursorChannel *cursor, RedClien
> */
> void cursor_channel_client_migrate(RedChannelClient
> *client);
>
> +G_END_DECLS
> +
> #endif /* CURSOR_CHANNEL_H_ */
> diff --git a/server/dcc-send.c b/server/dcc-send.c
> index e33f428..ef67f97 100644
> --- a/server/dcc-send.c
> +++ b/server/dcc-send.c
> @@ -20,7 +20,7 @@
> #endif
>
> #include "dcc-private.h"
> -#include "display-channel.h"
> +#include "display-channel-private.h"
> #include "red-channel-client-private.h"
>
> #include <common/marshaller.h>
> @@ -185,8 +185,9 @@ static void
> red_display_add_image_to_pixmap_cache(RedChannelClient *rcc,
> SpiceImage *image,
> SpiceImage *io_image,
> int is_lossy)
> {
> + DisplayChannel *display_channel =
> + DISPLAY_CHANNEL(red_channel_client_get_channel(rcc));
> DisplayChannelClient *dcc = DISPLAY_CHANNEL_CLIENT(rcc);
> - DisplayChannel *display_channel = DCC_TO_DC(dcc);
>
I prefer the old version, DCC_TO_DC is still present and used.
> if ((image->descriptor.flags & SPICE_IMAGE_FLAGS_CACHE_ME)) {
> spice_assert(image->descriptor.width * image->descriptor.height >
> 0);
> @@ -1817,7 +1818,7 @@ static void
> display_channel_marshall_migrate_data(RedChannelClient *rcc,
> ImageEncoders *encoders = dcc_get_encoders(dcc);
> SpiceMigrateDataDisplay display_data = {0,};
>
> - display_channel = DCC_TO_DC(dcc);
> + display_channel = DISPLAY_CHANNEL(red_channel_client_get_channel(rcc));
>
same here
> red_channel_client_init_send_data(rcc, SPICE_MSG_MIGRATE_DATA, NULL);
> spice_marshaller_add_uint32(base_marshaller,
> SPICE_MIGRATE_DATA_DISPLAY_MAGIC);
> @@ -2120,8 +2121,8 @@ static void marshall_qxl_drawable(RedChannelClient
> *rcc,
> spice_return_if_fail(rcc);
>
> Drawable *item = dpi->drawable;
> - DisplayChannel *display =
> SPICE_CONTAINEROF(red_channel_client_get_channel(rcc),
> - DisplayChannel,
> common.base);
> + DisplayChannel *display =
> + DISPLAY_CHANNEL(red_channel_client_get_channel(rcc));
>
> spice_return_if_fail(display);
> /* allow sized frames to be streamed, even if they where replaced by
> another frame, since
> diff --git a/server/dcc.c b/server/dcc.c
> index 3519d2e..ea6305c 100644
> --- a/server/dcc.c
> +++ b/server/dcc.c
> @@ -21,6 +21,7 @@
>
> #include "dcc-private.h"
> #include "display-channel.h"
> +#include "display-channel-private.h"
> #include "red-channel-client-private.h"
> #include "spice-server-enums.h"
>
> diff --git a/server/dcc.h b/server/dcc.h
> index 2456f09..e4fe788 100644
> --- a/server/dcc.h
> +++ b/server/dcc.h
> @@ -23,8 +23,8 @@
> #include "image-encoders.h"
> #include "image-cache.h"
> #include "pixmap-cache.h"
> -#include "red-worker.h"
> #include "display-limits.h"
> +#include "red-channel-client.h"
>
> G_BEGIN_DECLS
>
> diff --git a/server/display-channel-private.h
> b/server/display-channel-private.h
> new file mode 100644
> index 0000000..38330da
> --- /dev/null
> +++ b/server/display-channel-private.h
> @@ -0,0 +1,76 @@
> +/*
> + 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 DISPLAY_CHANNEL_PRIVATE_H_
> +#define DISPLAY_CHANNEL_PRIVATE_H_
> +
> +#include "display-channel.h"
> +
> +struct DisplayChannelPrivate
> +{
> + DisplayChannel *pub;
> +
> + uint32_t bits_unique;
> +
> + MonitorsConfig *monitors_config;
> +
> + uint32_t renderer;
> + int enable_jpeg;
> + int enable_zlib_glz_wrap;
> +
> + Ring current_list; // of TreeItem
> + uint32_t current_size;
> +
> + uint32_t drawable_count;
> + _Drawable drawables[NUM_DRAWABLES];
> + _Drawable *free_drawables;
> +
> + int stream_video;
> + GArray *video_codecs;
> + uint32_t stream_count;
> + Stream streams_buf[NUM_STREAMS];
> + Stream *free_streams;
> + Ring streams;
> + ItemTrace items_trace[NUM_TRACE_ITEMS];
> + uint32_t next_item_trace;
> + uint64_t streams_size_total;
> +
> + RedSurface surfaces[NUM_SURFACES];
> + uint32_t n_surfaces;
> + SpiceImageSurfaces image_surfaces;
> +
> + ImageCache image_cache;
> +
> + int gl_draw_async_count;
> +
> +/* TODO: some day unify this, make it more runtime.. */
> + stat_info_t add_stat;
> + stat_info_t exclude_stat;
> + stat_info_t __exclude_stat;
> +#ifdef RED_WORKER_STAT
> + uint32_t add_count;
> + uint32_t add_with_shadow_count;
> +#endif
> +#ifdef RED_STATISTICS
> + uint64_t *cache_hits_counter;
> + uint64_t *add_to_cache_counter;
> + uint64_t *non_cache_counter;
> +#endif
> + ImageEncoderSharedData encoder_shared_data;
> +};
> +
> +#endif /* DISPLAY_CHANNEL_PRIVATE_H_ */
> diff --git a/server/display-channel.c b/server/display-channel.c
> index 69edd35..19f0aca 100644
> --- a/server/display-channel.c
> +++ b/server/display-channel.c
> @@ -20,7 +20,131 @@
>
> #include <common/sw_canvas.h>
>
> -#include "display-channel.h"
> +#include "display-channel-private.h"
> +
> +G_DEFINE_TYPE(DisplayChannel, display_channel, TYPE_COMMON_GRAPHICS_CHANNEL)
> +
> +enum {
> + PROP0,
> + PROP_N_SURFACES,
> + PROP_VIDEO_CODECS
> +};
> +
> +static void
> +display_channel_get_property(GObject *object,
> + guint property_id,
> + GValue *value,
> + GParamSpec *pspec)
> +{
> + DisplayChannel *self = DISPLAY_CHANNEL(object);
> +
> + switch (property_id)
> + {
> + case PROP_N_SURFACES:
> + g_value_set_uint(value, self->priv->n_surfaces);
> + break;
> + default:
> + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
> + }
> +}
> +
> +static void
> +display_channel_set_property(GObject *object,
> + guint property_id,
> + const GValue *value,
> + GParamSpec *pspec)
> +{
> + DisplayChannel *self = DISPLAY_CHANNEL(object);
> +
> + switch (property_id)
> + {
> + case PROP_N_SURFACES:
> + self->priv->n_surfaces = g_value_get_uint(value);
> + break;
Sure we want this writable ?
Shouldn't we reallocate the array ?
> + case PROP_VIDEO_CODECS:
> + if (self->priv->video_codecs) {
> + g_array_unref(self->priv->video_codecs);
> + }
> + self->priv->video_codecs =
> g_array_ref(g_value_get_boxed(value));
> + break;
> + default:
> + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
> + }
> +}
> +
> +static void
> +display_channel_finalize(GObject *object)
> +{
> + DisplayChannel *self = DISPLAY_CHANNEL(object);
> +
> + G_OBJECT_CLASS(display_channel_parent_class)->finalize(object);
> +
> + g_free(self->priv);
> + g_array_unref(self->priv->video_codecs);
> +}
> +
> +static void
> +display_channel_constructed(GObject *object)
> +{
> + DisplayChannel *self = DISPLAY_CHANNEL(object);
> +
> + G_OBJECT_CLASS(display_channel_parent_class)->constructed(object);
> +
> + spice_assert(self->priv->video_codecs);
> +
> + self->priv->renderer = RED_RENDERER_INVALID;
> +
> + stat_init(&self->priv->add_stat, "add", CLOCK_THREAD_CPUTIME_ID);
> + stat_init(&self->priv->exclude_stat, "exclude",
> CLOCK_THREAD_CPUTIME_ID);
> + stat_init(&self->priv->__exclude_stat, "__exclude",
> CLOCK_THREAD_CPUTIME_ID);
> +#ifdef RED_STATISTICS
> + QXLInstance *qxl = common_graphics_channel_get_qxl(&self->parent);
> + RedsState *reds = red_qxl_get_server(qxl->st);
> + RedChannel *channel = RED_CHANNEL(self);
> + self->priv->cache_hits_counter =
> + stat_add_counter(reds, red_channel_get_stat_node(channel),
> + "cache_hits", TRUE);
> + self->priv->add_to_cache_counter =
> + stat_add_counter(reds, red_channel_get_stat_node(channel),
> + "add_to_cache", TRUE);
> + self->priv->non_cache_counter =
> + stat_add_counter(reds, red_channel_get_stat_node(channel),
> + "non_cache", TRUE);
> +#endif
> + image_cache_init(&self->priv->image_cache);
> + self->priv->stream_video = SPICE_STREAM_VIDEO_OFF;
> + display_channel_init_streams(self);
> +}
> +
> +static SpiceCanvas *image_surfaces_get(SpiceImageSurfaces *surfaces,
> uint32_t surface_id)
> +{
> + DisplayChannelPrivate *p = SPICE_CONTAINEROF(surfaces,
> DisplayChannelPrivate, image_surfaces);
> + DisplayChannel *display = p->pub;
> +
> + spice_return_val_if_fail(display_channel_validate_surface(display,
> surface_id), NULL);
> +
> + return p->surfaces[surface_id].context.canvas;
> +}
> +
> +static void drawables_init(DisplayChannel *display);
> +static void
> +display_channel_init(DisplayChannel *self)
> +{
> + static SpiceImageSurfacesOps image_surfaces_ops = {
> + image_surfaces_get,
> + };
> +
> + /* must be manually allocated here since g_type_class_add_private() only
> + * supports structs smaller than 64k */
> + self->priv = g_new0(DisplayChannelPrivate, 1);
> + self->priv->pub = self;
> +
> + image_encoder_shared_init(&self->priv->encoder_shared_data);
> +
> + ring_init(&self->priv->current_list);
> + drawables_init(self);
> + self->priv->image_surfaces.ops = &image_surfaces_ops;
> +}
>
> static void drawable_draw(DisplayChannel *display, Drawable *drawable);
> static Drawable *display_channel_drawable_try_new(DisplayChannel *display,
> @@ -43,12 +167,16 @@ void display_channel_compress_stats_reset(DisplayChannel
> *display)
> image_encoder_shared_stat_reset(&display->priv->encoder_shared_data);
> }
>
> -void display_channel_compress_stats_print(const DisplayChannel
> *display_channel)
> +void display_channel_compress_stats_print(DisplayChannel *display_channel)
> {
> #ifdef COMPRESS_STAT
> + uint32_t id;
> +
> spice_return_if_fail(display_channel);
>
> - spice_info("==> Compression stats for display %u",
> display_channel->common.base.id);
> + g_object_get(display_channel, "id", &id, NULL);
> +
> + spice_info("==> Compression stats for display %u", id);
> image_encoder_shared_stat_print(&display_channel->priv->encoder_shared_data);
> #endif
> }
> @@ -150,6 +278,11 @@ void display_channel_set_video_codecs(DisplayChannel
> *display, GArray *video_cod
> display->priv->video_codecs = g_array_ref(video_codecs);
> }
>
> +int display_channel_get_stream_video(DisplayChannel *display)
> +{
> + return display->priv->stream_video;
> +}
> +
> static void stop_streams(DisplayChannel *display)
> {
> Ring *ring = &display->priv->streams;
> @@ -280,7 +413,7 @@ static void pipes_add_drawable_after(DisplayChannel
> *display,
> pipes_add_drawable(display, drawable);
> return;
> }
> - if (num_other_linked != g_list_length(display->common.base.clients)) {
> + if (num_other_linked != red_channel_get_n_clients(RED_CHANNEL(display)))
> {
> GListIter iter;
> spice_debug("TODO: not O(n^2)");
> FOREACH_DCC(display, iter, dcc) {
> @@ -1115,18 +1248,18 @@ void display_channel_process_draw(DisplayChannel
> *display, RedDrawable *red_draw
> int display_channel_wait_for_migrate_data(DisplayChannel *display)
> {
> uint64_t end_time = spice_get_monotonic_time_ns() +
> DISPLAY_CLIENT_MIGRATE_DATA_TIMEOUT;
> - RedChannel *channel = &display->common.base;
> RedChannelClient *rcc;
> int ret = FALSE;
> + GList *clients = red_channel_get_clients(RED_CHANNEL(display));;
>
> - if (!red_channel_is_waiting_for_migrate_data(&display->common.base)) {
> + if (!red_channel_is_waiting_for_migrate_data(RED_CHANNEL(display))) {
> return FALSE;
> }
>
> spice_debug(NULL);
> - spice_warn_if_fail(g_list_length(channel->clients) == 1);
> + spice_warn_if_fail(g_list_length(clients) == 1);
>
> - rcc = g_list_nth_data(channel->clients, 0);
> + rcc = g_list_nth_data(clients, 0);
>
> g_object_ref(rcc);
> for (;;) {
> @@ -1893,16 +2026,6 @@ static int handle_migrate_data(RedChannelClient *rcc,
> uint32_t size, void *messa
> return dcc_handle_migrate_data(DISPLAY_CHANNEL_CLIENT(rcc), size,
> message);
> }
>
> -static SpiceCanvas *image_surfaces_get(SpiceImageSurfaces *surfaces,
> uint32_t surface_id)
> -{
> - DisplayChannelPrivate *p = SPICE_CONTAINEROF(surfaces,
> DisplayChannelPrivate, image_surfaces);
> - DisplayChannel *display = p->pub;
> -
> - spice_return_val_if_fail(display_channel_validate_surface(display,
> surface_id), NULL);
> -
> - return display->priv->surfaces[surface_id].context.canvas;
> -}
> -
> DisplayChannel* display_channel_new(RedsState *reds,
> QXLInstance *qxl,
> const SpiceCoreInterfaceInternal *core,
> @@ -1911,52 +2034,21 @@ DisplayChannel* display_channel_new(RedsState *reds,
> uint32_t n_surfaces)
> {
> DisplayChannel *display;
> - ChannelCbs cbs = {
> - .on_disconnect = on_disconnect,
> - .send_item = dcc_send_item,
> - .handle_migrate_flush_mark = handle_migrate_flush_mark,
> - .handle_migrate_data = handle_migrate_data,
> - .handle_migrate_data_get_serial = handle_migrate_data_get_serial,
> - .config_socket = dcc_config_socket
> - };
> - static SpiceImageSurfacesOps image_surfaces_ops = {
> - image_surfaces_get,
> - };
>
> + /* FIXME: migrate is not used...? */
> spice_info("create display channel");
> - display = DISPLAY_CHANNEL(common_graphics_channel_new(
> - reds, qxl, core, sizeof(*display), SPICE_CHANNEL_DISPLAY,
> - SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER,
> - &cbs, dcc_handle_message));
> - spice_return_val_if_fail(display, NULL);
> - display->priv->pub = display;
> -
> - clockid_t stat_clock = CLOCK_THREAD_CPUTIME_ID;
> - stat_init(&display->priv->add_stat, "add", stat_clock);
> - stat_init(&display->priv->exclude_stat, "exclude", stat_clock);
> - stat_init(&display->priv->__exclude_stat, "__exclude", stat_clock);
> -#ifdef RED_STATISTICS
> - RedChannel *channel = RED_CHANNEL(display);
> - display->priv->cache_hits_counter = stat_add_counter(reds,
> channel->stat,
> - "cache_hits",
> TRUE);
> - display->priv->add_to_cache_counter = stat_add_counter(reds,
> channel->stat,
> - "add_to_cache",
> TRUE);
> - display->priv->non_cache_counter = stat_add_counter(reds, channel->stat,
> - "non_cache", TRUE);
> -#endif
> - image_encoder_shared_init(&display->priv->encoder_shared_data);
> -
> - display->priv->n_surfaces = n_surfaces;
> - display->priv->renderer = RED_RENDERER_INVALID;
> -
> - ring_init(&display->priv->current_list);
> - display->priv->image_surfaces.ops = &image_surfaces_ops;
> - drawables_init(display);
> - image_cache_init(&display->priv->image_cache);
> - display->priv->stream_video = stream_video;
> - display->priv->video_codecs = g_array_ref(video_codecs);
> - display_channel_init_streams(display);
> -
> + display = g_object_new(TYPE_DISPLAY_CHANNEL,
> + "spice-server", reds,
> + "core-interface", core,
> + "channel-type", SPICE_CHANNEL_DISPLAY,
> + "migration-flags", (SPICE_MIGRATE_NEED_FLUSH |
> SPICE_MIGRATE_NEED_DATA_TRANSFER),
> + "qxl", qxl,
> + "n-surfaces", n_surfaces,
> + "video-codecs", video_codecs,
> + NULL);
> + if (display) {
> + display_channel_set_stream_video(display, stream_video);
> + }
> return display;
> }
>
> @@ -2085,7 +2177,6 @@ void
> display_channel_update_monitors_config(DisplayChannel *display,
> QXLMonitorsConfig *config,
> uint16_t count, uint16_t
> max_allowed)
> {
> -
> if (display->priv->monitors_config)
> monitors_config_unref(display->priv->monitors_config);
>
> @@ -2113,6 +2204,50 @@ void display_channel_reset_image_cache(DisplayChannel
> *self)
> image_cache_reset(&self->priv->image_cache);
> }
>
> +static void
> +display_channel_class_init(DisplayChannelClass *klass)
> +{
> + GObjectClass *object_class = G_OBJECT_CLASS(klass);
> + RedChannelClass *channel_class = RED_CHANNEL_CLASS(klass);
> +
> + g_type_class_add_private(klass, sizeof(DisplayChannelPrivate));
> +
> + object_class->get_property = display_channel_get_property;
> + object_class->set_property = display_channel_set_property;
> + object_class->constructed = display_channel_constructed;
> + object_class->finalize = display_channel_finalize;
> +
> + channel_class->parser =
> spice_get_client_channel_parser(SPICE_CHANNEL_DISPLAY, NULL);
> + channel_class->handle_parsed = dcc_handle_message;
> +
> + channel_class->on_disconnect = on_disconnect;
> + channel_class->send_item = dcc_send_item;
> + channel_class->handle_migrate_flush_mark = handle_migrate_flush_mark;
> + channel_class->handle_migrate_data = handle_migrate_data;
> + channel_class->handle_migrate_data_get_serial =
> handle_migrate_data_get_serial;
> + channel_class->config_socket = dcc_config_socket;
> +
> + g_object_class_install_property(object_class,
> + PROP_N_SURFACES,
> + g_param_spec_uint("n-surfaces",
> + "number of surfaces",
> + "Number of surfaces
> for this channel",
> + 0, G_MAXUINT,
> + 0,
> + G_PARAM_CONSTRUCT_ONLY
> |
> + G_PARAM_READWRITE |
> +
Imo should be write only.
> G_PARAM_STATIC_STRINGS));
> + g_object_class_install_property(object_class,
> + PROP_VIDEO_CODECS,
> + g_param_spec_boxed("video-codecs",
> + "video codecs",
> + "Video Codecs",
> + G_TYPE_ARRAY,
> +
> G_PARAM_CONSTRUCT_ONLY
> |
> + G_PARAM_WRITABLE |
> +
> G_PARAM_STATIC_STRINGS));
> +}
> +
> void display_channel_debug_oom(DisplayChannel *display, const char *msg)
> {
> RedChannel *channel = RED_CHANNEL(display);
> diff --git a/server/display-channel.h b/server/display-channel.h
> index 3762e54..9ac9046 100644
> --- a/server/display-channel.h
> +++ b/server/display-channel.h
> @@ -20,32 +20,59 @@
>
> #include <setjmp.h>
> #include <common/rect.h>
> +#include <common/sw_canvas.h>
>
> -#include "reds-stream.h"
> #include "cache-item.h"
> -#include "pixmap-cache.h"
> -#include "stat.h"
> -#include "reds.h"
> -#include "memslot.h"
> -#include "red-parse-qxl.h"
> -#include "red-record-qxl.h"
> +#include "image-encoders.h"
> +#include "dcc.h"
> #include "demarshallers.h"
> -#include "red-channel.h"
> -#include "red-qxl.h"
> #include "dispatcher.h"
> #include "main-channel.h"
> -#include "migration-protocol.h"
> #include "main-dispatcher.h"
> +#include "memslot.h"
> +#include "migration-protocol.h"
> +#include "video-encoder.h"
> +#include "pixmap-cache.h"
> +#include "red-channel.h"
> +#include "red-qxl.h"
> +#include "red-parse-qxl.h"
> +#include "red-record-qxl.h"
> +#include "reds-stream.h"
> +#include "reds.h"
> #include "spice-bitmap-utils.h"
> -#include "image-cache.h"
> -#include "utils.h"
> -#include "tree.h"
> +#include "stat.h"
> #include "stream.h"
> -#include "dcc.h"
> -#include "image-encoders.h"
> #include "common-graphics-channel.h"
> +#include "tree.h"
> +#include "utils.h"
> +
May headers are just included in a different order.
Is there any reason to change the order?
> +G_BEGIN_DECLS
> +
> +#define TYPE_DISPLAY_CHANNEL display_channel_get_type()
> +
> +#define DISPLAY_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),
> TYPE_DISPLAY_CHANNEL, DisplayChannel))
> +#define DISPLAY_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),
> TYPE_DISPLAY_CHANNEL, DisplayChannelClass))
> +#define IS_DISPLAY_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),
> TYPE_DISPLAY_CHANNEL))
> +#define IS_DISPLAY_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),
> TYPE_DISPLAY_CHANNEL))
> +#define DISPLAY_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),
> TYPE_DISPLAY_CHANNEL, DisplayChannelClass))
> +
> +typedef struct DisplayChannel DisplayChannel;
> +typedef struct DisplayChannelClass DisplayChannelClass;
> +typedef struct DisplayChannelPrivate DisplayChannelPrivate;
> +
> +struct DisplayChannel
> +{
> + CommonGraphicsChannel parent;
> +
> + DisplayChannelPrivate *priv;
> +};
> +
> +struct DisplayChannelClass
> +{
> + CommonGraphicsChannelClass parent_class;
> +};
>
> -#define DISPLAY_CHANNEL(channel) ((DisplayChannel*)(channel))
> +GType display_channel_get_type(void) G_GNUC_CONST;
>
> typedef struct DependItem {
> Drawable *drawable;
> @@ -154,69 +181,8 @@ struct _Drawable {
> } u;
> };
>
> -typedef struct DisplayChannelPrivate DisplayChannelPrivate;
> -/* FIXME: move to separate file */
> -struct DisplayChannelPrivate
> -{
> - DisplayChannel *pub;
> -
> - uint32_t bits_unique;
> -
> - MonitorsConfig *monitors_config;
> -
> - uint32_t renderer;
> - int enable_jpeg;
> - int enable_zlib_glz_wrap;
> -
> - Ring current_list; // of TreeItem
> - uint32_t current_size;
> -
> - uint32_t drawable_count;
> - _Drawable drawables[NUM_DRAWABLES];
> - _Drawable *free_drawables;
> -
> - int stream_video;
> - GArray *video_codecs;
> - uint32_t stream_count;
> - Stream streams_buf[NUM_STREAMS];
> - Stream *free_streams;
> - Ring streams;
> - ItemTrace items_trace[NUM_TRACE_ITEMS];
> - uint32_t next_item_trace;
> - uint64_t streams_size_total;
> -
> - RedSurface surfaces[NUM_SURFACES];
> - uint32_t n_surfaces;
> - SpiceImageSurfaces image_surfaces;
> -
> - ImageCache image_cache;
> -
> - int gl_draw_async_count;
> -
> -/* TODO: some day unify this, make it more runtime.. */
> - stat_info_t add_stat;
> - stat_info_t exclude_stat;
> - stat_info_t __exclude_stat;
> -#ifdef RED_WORKER_STAT
> - uint32_t add_count;
> - uint32_t add_with_shadow_count;
> -#endif
> -#ifdef RED_STATISTICS
> - uint64_t *cache_hits_counter;
> - uint64_t *add_to_cache_counter;
> - uint64_t *non_cache_counter;
> -#endif
> - ImageEncoderSharedData encoder_shared_data;
> -};
> -
> -struct DisplayChannel {
> - CommonGraphicsChannel common; // Must be the first thing
> -
> - DisplayChannelPrivate priv[1];
> -};
> -
> #define FOREACH_DCC(_channel, _iter, _data) \
> - GLIST_FOREACH((_channel ? RED_CHANNEL(_channel)->clients : NULL), \
> + GLIST_FOREACH((_channel ? red_channel_get_clients(RED_CHANNEL(_channel))
> : NULL), \
> _iter, DisplayChannelClient, _data)
>
> int display_channel_get_stream_id(DisplayChannel *display, Stream *stream);
> @@ -262,8 +228,9 @@ void
> display_channel_set_stream_video (DisplayCha
> int
> stream_video);
> void display_channel_set_video_codecs
> (DisplayChannel *display,
> GArray
> *video_codecs);
> +int display_channel_get_stream_video
> (DisplayChannel *display);
> int display_channel_get_streams_timeout
> (DisplayChannel *display);
> -void display_channel_compress_stats_print (const
> DisplayChannel *display);
> +void display_channel_compress_stats_print
> (DisplayChannel *display);
> void display_channel_compress_stats_reset
> (DisplayChannel *display);
> void display_channel_surface_unref
> (DisplayChannel *display,
> uint32_t
> surface_id);
> @@ -415,4 +382,6 @@ static inline void region_add_clip_rects(QRegion *rgn,
> SpiceClipRects *data)
> }
> }
>
> +G_END_DECLS
> +
> #endif /* DISPLAY_CHANNEL_H_ */
> diff --git a/server/dummy-channel-client.c b/server/dummy-channel-client.c
> index 1b72137..b7fee6f 100644
> --- a/server/dummy-channel-client.c
> +++ b/server/dummy-channel-client.c
> @@ -37,9 +37,11 @@ struct DummyChannelClientPrivate
>
> static int dummy_channel_client_pre_create_validate(RedChannel *channel,
> RedClient *client)
> {
> - if (red_client_get_channel(client, channel->type, channel->id)) {
> + uint32_t type, id;
> + g_object_get(channel, "channel-type", &type, "id", &id, NULL);
> + if (red_client_get_channel(client, type, id)) {
> spice_printerr("Error client %p: duplicate channel type %d id %d",
> - client, channel->type, channel->id);
> + client, type, id);
> return FALSE;
> }
> return TRUE;
> @@ -54,6 +56,9 @@ static gboolean
> dummy_channel_client_initable_init(GInitable *initable,
> RedChannelClient *rcc = RED_CHANNEL_CLIENT(self);
> RedClient *client = red_channel_client_get_client(rcc);
> RedChannel *channel = red_channel_client_get_channel(rcc);
> + uint32_t type, id;
> +
> + g_object_get(channel, "channel-type", &type, "id", &id, NULL);
> pthread_mutex_lock(&client->lock);
> if (!dummy_channel_client_pre_create_validate(channel,
> client)) {
> @@ -61,7 +66,7 @@ static gboolean
> dummy_channel_client_initable_init(GInitable *initable,
> SPICE_SERVER_ERROR,
> SPICE_SERVER_ERROR_FAILED,
> "Client %p: duplicate channel type %d id %d",
> - client, channel->type, channel->id);
> + client, type, id);
> goto cleanup;
> }
>
> @@ -94,10 +99,12 @@ 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(channel->clients, rcc))) {
> + 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,
> - channel->type, channel->id);
> + type, id);
> red_channel_remove_client(channel, link->data);
> }
> self->priv->connected = FALSE;
> diff --git a/server/dummy-channel.c b/server/dummy-channel.c
> new file mode 100644
> index 0000000..6ec7842
> --- /dev/null
> +++ b/server/dummy-channel.c
> @@ -0,0 +1,58 @@
> +/* dummy-channel.c */
> +#ifdef HAVE_CONFIG_H
> +#include <config.h>
> +#endif
> +
> +#include "dummy-channel.h"
> +
> +G_DEFINE_TYPE(DummyChannel, dummy_channel, RED_TYPE_CHANNEL)
> +
> +#define DUMMY_CHANNEL_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o),
> TYPE_DUMMY_CHANNEL, DummyChannelPrivate))
> +
> +struct DummyChannelPrivate
> +{
> + gpointer padding;
> +};
> +
Why just not using a private ? This padding field is not used.
And you can just keep the priv field to retain ABI.
This dummy stuff is moving from ugly to disgusting...
> +static void
> +dummy_channel_class_init(DummyChannelClass *klass)
> +{
> + g_type_class_add_private(klass, sizeof(DummyChannelPrivate));
> +}
> +
> +static void
> +dummy_channel_init(DummyChannel *self)
> +{
> + self->priv = DUMMY_CHANNEL_PRIVATE(self);
> +}
> +
> +// TODO: red_worker can use this one
> +static void dummy_watch_update_mask(SpiceWatch *watch, int event_mask)
> +{
> +}
> +
> +static SpiceWatch *dummy_watch_add(int fd, int event_mask, SpiceWatchFunc
> func, void *opaque)
> +{
> + return NULL; // apparently allowed?
> +}
> +
> +static void dummy_watch_remove(SpiceWatch *watch)
> +{
> +}
> +
> +// TODO: actually, since I also use channel_client_dummym, no need for core.
> Can be NULL
> +static const SpiceCoreInterface dummy_core = {
> + .watch_update_mask = dummy_watch_update_mask,
> + .watch_add = dummy_watch_add,
> + .watch_remove = dummy_watch_remove,
> +};
> +
> +RedChannel *dummy_channel_new(RedsState *reds, uint32_t type, uint32_t id)
> +{
> + return g_object_new(TYPE_DUMMY_CHANNEL,
> + "spice-server", reds,
> + "core-interface", &dummy_core,
> + "channel-type", type,
> + "id", id,
> + NULL);
> +}
> diff --git a/server/dummy-channel.h b/server/dummy-channel.h
> new file mode 100644
> index 0000000..dd2f005
> --- /dev/null
> +++ b/server/dummy-channel.h
> @@ -0,0 +1,61 @@
> +/*
> + 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_H__
> +#define __DUMMY_CHANNEL_H__
> +
> +#include <glib-object.h>
> +
> +#include "red-channel.h"
> +
> +G_BEGIN_DECLS
> +
> +// TODO: tmp, for channels that don't use RedChannel yet (e.g., snd
> channel), but
> +// do use the client callbacks. So the channel clients are not connected
> (the channel doesn't
> +// have list of them, but they do have a link to the channel, and the client
> has a list of them)
> +
> +#define TYPE_DUMMY_CHANNEL dummy_channel_get_type()
> +
> +#define DUMMY_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),
> TYPE_DUMMY_CHANNEL, DummyChannel))
> +#define DUMMY_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),
> TYPE_DUMMY_CHANNEL, DummyChannelClass))
> +#define _IS_DUMMY_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),
> TYPE_DUMMY_CHANNEL))
> +#define _IS_DUMMY_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),
> TYPE_DUMMY_CHANNEL))
> +#define DUMMY_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),
> TYPE_DUMMY_CHANNEL, DummyChannelClass))
> +
> +typedef struct DummyChannel DummyChannel;
> +typedef struct DummyChannelClass DummyChannelClass;
> +typedef struct DummyChannelPrivate DummyChannelPrivate;
> +
> +struct DummyChannel
> +{
> + RedChannel parent;
> +
> + DummyChannelPrivate *priv;
> +};
> +
> +struct DummyChannelClass
> +{
> + RedChannelClass parent_class;
> +};
> +
> +GType dummy_channel_get_type(void) G_GNUC_CONST;
> +
> +RedChannel *dummy_channel_new(RedsState *reds, uint32_t type, uint32_t id);
> +
> +G_END_DECLS
> +
> +#endif /* __DUMMY_CHANNEL_H__ */
> diff --git a/server/inputs-channel.c b/server/inputs-channel.c
> index 83c1360..c351dad 100644
> --- a/server/inputs-channel.c
> +++ b/server/inputs-channel.c
> @@ -57,6 +57,83 @@
> #define RECEIVE_BUF_SIZE \
> (4096 + (REDS_AGENT_WINDOW_SIZE + REDS_NUM_INTERNAL_AGENT_MESSAGES) *
> SPICE_AGENT_MAX_DATA_SIZE)
>
> +G_DEFINE_TYPE(InputsChannel, inputs_channel, RED_TYPE_CHANNEL)
> +
> +#define CHANNEL_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o),
> TYPE_INPUTS_CHANNEL, InputsChannelPrivate))
> +
> +struct InputsChannelPrivate
> +{
> + uint8_t recv_buf[RECEIVE_BUF_SIZE];
> + VDAgentMouseState mouse_state;
> + int src_during_migrate;
> + SpiceTimer *key_modifiers_timer;
> +
> + SpiceKbdInstance *keyboard;
> + SpiceMouseInstance *mouse;
> + SpiceTabletInstance *tablet;
> +};
> +
> +
> +static void
> +inputs_channel_get_property(GObject *object,
> + guint property_id,
> + GValue *value,
> + GParamSpec *pspec)
> +{
> + switch (property_id)
> + {
> + default:
> + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
> + }
> +}
> +
> +static void
> +inputs_channel_set_property(GObject *object,
> + guint property_id,
> + const GValue *value,
> + GParamSpec *pspec)
> +{
> + switch (property_id)
> + {
> + default:
> + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
> + }
> +}
> +
I noted there are these empty function here and in different file.
Don't GObject provide some default functions like these?
> +static void inputs_connect(RedChannel *channel, RedClient *client,
> + RedsStream *stream, int migration,
> + int num_common_caps, uint32_t *common_caps,
> + int num_caps, uint32_t *caps);
> +static void inputs_migrate(RedChannelClient *rcc);
> +static void key_modifiers_sender(void *opaque);
> +
> +static void
> +inputs_channel_constructed(GObject *object)
> +{
> + ClientCbs client_cbs = { NULL, };
> + InputsChannel *self = INPUTS_CHANNEL(object);
> + RedsState *reds = red_channel_get_server(RED_CHANNEL(self));
> +
> + G_OBJECT_CLASS(inputs_channel_parent_class)->constructed(object);
> +
> + client_cbs.connect = inputs_connect;
> + client_cbs.migrate = inputs_migrate;
> + red_channel_register_client_cbs(RED_CHANNEL(self), &client_cbs, NULL);
> +
> + red_channel_set_cap(RED_CHANNEL(self), SPICE_INPUTS_CAP_KEY_SCANCODE);
> + reds_register_channel(reds, RED_CHANNEL(self));
> +
> + if (!(self->priv->key_modifiers_timer = reds_core_timer_add(reds,
> key_modifiers_sender, self))) {
> + spice_error("key modifiers timer create failed");
> + }
> +}
> +
> +static void
> +inputs_channel_init(InputsChannel *self)
> +{
> + self->priv = CHANNEL_PRIVATE(self);
> +}
> +
> struct SpiceKbdState {
> uint8_t push_ext_type;
>
> @@ -105,18 +182,6 @@ RedsState*
> spice_tablet_state_get_server(SpiceTabletState *st)
> return st->reds;
> }
>
> -struct InputsChannel {
> - RedChannel base;
> - uint8_t recv_buf[RECEIVE_BUF_SIZE];
> - VDAgentMouseState mouse_state;
> - int src_during_migrate;
> - SpiceTimer *key_modifiers_timer;
> -
> - SpiceKbdInstance *keyboard;
> - SpiceMouseInstance *mouse;
> - SpiceTabletInstance *tablet;
> -};
> -
Couldn't we move new function after this declaration to reduce patch size?
> typedef struct RedKeyModifiersPipeItem {
> RedPipeItem base;
> uint8_t modifiers;
... omissis ...
Frediano
More information about the Spice-devel
mailing list