Re: [Spice-devel] [PATCH server v2 05/13] red-channel: send marshaller message fd

2016-01-18 Thread Jonathon Jongsma
Maybe it's just me, but I don't really understand the purpose of this patch. Can
you give a big-picture explanation?




On Thu, 2016-01-14 at 22:01 +0100, Marc-André Lureau wrote:
> From: Marc-André Lureau 
> 
> Send the fd associated to the last message sent.
> 
> Even if the fd is invalid, the sendfd msg is appended to the protocol,
> for 2 reasons:
> - trying to send an invalid fd does not have to close the connection (it
>   would with an invalid fd)
> - even if the fd is invalid, the protocol expects an extra byte for the
>   ancillary data
> 
> Signed-off-by: Marc-André Lureau 
> ---
>  server/red-channel.c | 16 
>  1 file changed, 16 insertions(+)
> 
> diff --git a/server/red-channel.c b/server/red-channel.c
> index 306c87d..b33c91d 100644
> --- a/server/red-channel.c
> +++ b/server/red-channel.c
> @@ -608,8 +608,24 @@ static inline void
> red_channel_client_release_sent_item(RedChannelClient *rcc)
>  static void red_channel_peer_on_out_msg_done(void *opaque)
>  {
>  RedChannelClient *rcc = (RedChannelClient *)opaque;
> +int fd = spice_marshaller_get_fd(rcc->send_data.marshaller);
>  
>  rcc->send_data.size = 0;
> +
> +if (fd != -1) {
> +if (fcntl(fd, F_GETFD) == -1) {
> +close(fd);
> +fd = -1;
> +}
> +
> +if (reds_stream_send_msgfd(rcc->stream, fd) < 0) {
> +perror("sendfd");
> +red_channel_client_disconnect(rcc);
> +return;
> +}
> +close(fd);
> +}
> +
>  red_channel_client_release_sent_item(rcc);
>  if (rcc->send_data.blocked) {
>  rcc->send_data.blocked = FALSE;
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH server v2 03/13] tests: make sure all tests are built on default rule

2016-01-18 Thread Jonathon Jongsma
On Fri, 2016-01-15 at 09:08 -0500, Frediano Ziglio wrote:
> > 
> > Hi
> > 
> > - Original Message -
> > > > 
> > > > Hi
> > > > 
> > > > On Fri, Jan 15, 2016 at 11:50 AM, Frediano Ziglio 
> > > > wrote:
> > > > > 
> > > > > > Subject: [PATCH server v2 03/13] tests: make sure all tests are
> > > > > > built
> > > > > > on
> > > > > > default rule
> > > > > > 
> > > > > > We should have all or none, I don't see the point of having just
> > > > > > some
> > > > > > of
> > > > > > them.
> > > > > > 
> > > > > 
> > > > > I don't know why but this description (and subject) looks odd to me.
> > > > > 
> > > > > I would put something like (if I understood it):
> > > > > 
> > > > > "Programs listed in noinst_PROGRAMS inherit default rule/settings to
> > > > > list
> > > > > all
> > > > > tests program also in this macro"
> > > > > 
> > > > 
> > > > I don't mind changing the text, but I really don't understand yours ;)
> > > > 
> > > 
> > > That means I didn't get the reason of the change.
> > > 
> > > What's a rule for you?
> > > 
> > > output: source
> > >   do_something_to_generate_output_from_source
> > > 
> > > is a rule
> > > 
> > > TESTS = xxx
> > > 
> > > is a variable (also called macro)
> > 
> > Yes
> > 
> > the default rule being "all", it builds noinst_PROGRAMS but not
> > check_PROGRAMS. I prefer either build all with noinst_PROGRAMS or none (in
> > which case we should remove some of them duplicated in check_PROGRAMS)
> > 
> 
> Really didn't get it before :)
> Can you post again with an updated comment?
> 
> Frediano


I didn't fully understand the original comment either (nor did I really
understand Frediano's suggested alternative ;). 

I think that even a simple re-wording would make it a little more clear:

"Make sure that the default rule builds all tests."


> 
> > > 
> > > > > > Signed-off-by: Marc-André Lureau 
> > > > > > ---
> > > > > >  server/tests/Makefile.am | 15 +++
> > > > > >  1 file changed, 7 insertions(+), 8 deletions(-)
> > > > > > 
> > > > > > diff --git a/server/tests/Makefile.am b/server/tests/Makefile.am
> > > > > > index 15196f9..007930c 100644
> > > > > > --- a/server/tests/Makefile.am
> > > > > > +++ b/server/tests/Makefile.am
> > > > > > @@ -35,6 +35,12 @@ LDADD =
> > > > > > \
> > > > > >   $(SPICE_NONPKGCONFIG_LIBS)  \
> > > > > >   $(NULL)
> > > > > > 
> > > > > > +TESTS =  \
> > > > > > + stat_test   \
> > > > > > + stream-test \
> > > > > > + test-qxl-parsing\
> > > > > > + $(NULL)
> > > > > > +
> > > > > 
> > > > > Why did you moved above? This just make the patch bigger.
> > > > > 
> > > > 
> > > > It's saner/simpler to define before use.
> > > > 
> > > 
> > > Let's say that is more similar to assignment and other languages so
> > > it's easier to read by people not very friendly with Makefiles
> > > (and honestly I think that many developers does not really like
> > > Makefiles).
> > > 
> > > > > >  noinst_PROGRAMS =\
> > > > > >   test_display_no_ssl \
> > > > > >   test_display_streaming  \
> > > > > > @@ -47,14 +53,7 @@ noinst_PROGRAMS =  \
> > > > > >   test_vdagent\
> > > > > >   test_display_width_stride   \
> > > > > >   spice-server-replay \
> > > > > > - stream-test \
> > > > > > - stat_test   \
> > > > > > - $(NULL)
> > > > > > -
> > > > > > -TESTS =  \
> > > > > > - stat_test   \
> > > > > > - test-qxl-parsing\
> > > > > > - stream-test \
> > > > > > + $(TESTS)\
> > > > > >   $(NULL)
> > > > > > 
> > > > > >  check_PROGRAMS = $(TESTS)
> > > > > > --
> > > > > > 2.5.0
> > > > > > 
> > > > > > 
> > > > > 
> > > > > Frediano
> > > > 
> > > > 
> > > > 
> > > > --
> > > > Marc-André Lureau
> > > > 
> ___
> Spice-devel mailing list
> Spice-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH server v2 02/13] tests: link test-qxl-parsing with libserver

2016-01-18 Thread Jonathon Jongsma
In general, I appreciate a bit more justification in the commit log so I can
quickly understand the "why" in addition to the "what". In this case, I assume
it's to reduce build time and avoid compiling these files twice. ACK with a
slightly expanded commit log.

Acked-by: Jonathon Jongsma 



On Thu, 2016-01-14 at 22:01 +0100, Marc-André Lureau wrote:
> Signed-off-by: Marc-André Lureau 
> ---
>  server/tests/Makefile.am | 6 +-
>  1 file changed, 1 insertion(+), 5 deletions(-)
> 
> diff --git a/server/tests/Makefile.am b/server/tests/Makefile.am
> index 8caff04..15196f9 100644
> --- a/server/tests/Makefile.am
> +++ b/server/tests/Makefile.am
> @@ -91,8 +91,4 @@ libstat_test3_a_CPPFLAGS = $(AM_CPPFLAGS) 
> -DTEST_COMPRESS_STAT=1 -DTEST_RED_WORK
>  libstat_test4_a_SOURCES = stat-test.c
>  libstat_test4_a_CPPFLAGS = $(AM_CPPFLAGS) -DTEST_COMPRESS_STAT=1 
> -DTEST_RED_WORKER_STAT=1 -DTEST_NAME=stat_test4
>  
> -test_qxl_parsing_SOURCES =   \
> - test-qxl-parsing.c  \
> - ../red-parse-qxl.c  \
> - ../memslot.c\
> - $(NULL)
> +test_qxl_parsing_LDADD = ../libserver.la $(LDADD)
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH 15/15] reds_num_of_clients() -> reds_get_n_clients()

2016-01-18 Thread Jonathon Jongsma
On Mon, 2016-01-18 at 16:38 +, Frediano Ziglio wrote:
> From: Jonathon Jongsma 
> 
> More consistent with glib naming conventions. Also make the function
> static since it's not used outside of this source file.

I don't know if this patch has changed slightly due to rebase, but the function
appears to already be static. So we can remove this last sentence from the
commit log.

> ---
>  server/reds.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/server/reds.c b/server/reds.c
> index 4de1640..22ab26d 100644
> --- a/server/reds.c
> +++ b/server/reds.c
> @@ -897,7 +897,7 @@ int reds_get_n_channels(RedsState *reds)
>  }
>  
>  
> -static int reds_num_of_clients(RedsState *reds)
> +static int reds_get_n_clients(RedsState *reds)
>  {
>  return reds ? reds->num_clients : 0;
>  }
> @@ -905,7 +905,7 @@ static int reds_num_of_clients(RedsState *reds)
>  SPICE_GNUC_VISIBLE int spice_server_get_num_clients(SpiceServer *s)
>  {
>  spice_assert(reds == s);
> -return reds_num_of_clients(reds);
> +return reds_get_n_clients(reds);
>  }
>  
>  static int secondary_channels[] = {
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH 14/14] Add strings for translation

2016-01-18 Thread Jonathon Jongsma
On Mon, 2016-01-18 at 10:05 +0100, Fabiano Fidêncio wrote:
> While doing the work to use GTask isntead of GSimpleAsyncResult I've
> noticed a few error strings that were not marked to be translated.
> I am not exactly sure if it was intentional or not, but I do believe
> that our error messages should be translated.
> ---
>  po/POTFILES.in   |  6 ++
>  src/channel-main.c   |  4 +++-
>  src/channel-port.c   |  4 +++-
>  src/channel-usbredir.c   |  4 ++--
>  src/spice-channel.c  |  2 +-
>  src/spice-pulse.c|  8 +---
>  src/usb-acl-helper.c | 10 ++
>  src/usb-device-manager.c |  4 ++--
>  src/vmcstream.c  |  4 +++-
>  src/win-usb-driver-install.c | 16 +---
>  10 files changed, 40 insertions(+), 22 deletions(-)
> 
> diff --git a/po/POTFILES.in b/po/POTFILES.in
> index ad12609..7c79541 100644
> --- a/po/POTFILES.in
> +++ b/po/POTFILES.in
> @@ -1,8 +1,14 @@
> +src/channel-main.c
> +src/channel-port.c
>  src/channel-usbredir.c
>  src/desktop-integration.c
>  src/spice-channel.c
>  src/spice-cmdline.c
>  src/spice-option.c
> +src/spice-pulse.c
> +src/usb-acl-helper.c
>  src/usb-device-manager.c
>  src/usb-device-widget.c
>  src/usbutil.c
> +src/vmcstream.c
> +src/win-usb-driver-install.c
> diff --git a/src/channel-main.c b/src/channel-main.c
> index 6c0f238..40d5cff 100644
> --- a/src/channel-main.c
> +++ b/src/channel-main.c
> @@ -21,6 +21,8 @@
>  #include 
>  #include 
>  
> +#include 
> +
>  #include "glib-compat.h"
>  #include "spice-client.h"
>  #include "spice-common.h"
> @@ -3143,7 +3145,7 @@ void spice_main_file_copy_async(SpiceMainChannel
> *channel,
>  spice_main_file_copy_async,
>  SPICE_CLIENT_ERROR,
>  SPICE_CLIENT_ERROR_FAILED,
> -"The agent is not connected");
> +_("The agent is not connected"));
>  return;
>  }
>  
> diff --git a/src/channel-port.c b/src/channel-port.c
> index 20ee2fa..86194ab 100644
> --- a/src/channel-port.c
> +++ b/src/channel-port.c
> @@ -23,6 +23,8 @@
>  #include "spice-marshal.h"
>  #include "glib-compat.h"
>  
> +#include 
> +
>  /**
>   * SECTION:channel-port
>   * @short_description: private communication channel
> @@ -295,7 +297,7 @@ void spice_port_write_async(SpicePortChannel *self,
>  g_task_report_new_error(self, callback,
>  user_data, spice_port_write_async,
>  SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
> -"The port is not opened");
> +_("The port is not opened"));
>  return;
>  }
>  
> diff --git a/src/channel-usbredir.c b/src/channel-usbredir.c
> index 4ddf7bf..824bc43 100644
> --- a/src/channel-usbredir.c
> +++ b/src/channel-usbredir.c
> @@ -344,14 +344,14 @@ void spice_usbredir_channel_connect_device_async(
>  if (!priv->host) {
>  g_task_return_new_error(task,
>  SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
> -"Error libusb context not set");
> +_("Error libusb context not set"));
>  goto done;
>  }
>  
>  if (priv->state != STATE_DISCONNECTED) {
>  g_task_return_new_error(task,
>  SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
> -"Error channel is busy");
> +_("Error channel is busy"));
>  goto done;
>  }
>  
> diff --git a/src/spice-channel.c b/src/spice-channel.c
> index dd32818..246609a 100644
> --- a/src/spice-channel.c
> +++ b/src/spice-channel.c
> @@ -2979,7 +2979,7 @@ void spice_channel_flush_async(SpiceChannel *self,
> GCancellable *cancellable,
>  g_task_report_new_error(self, callback, user_data,
>  spice_channel_flush_async,
>  SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
> -"The channel is not ready yet");
> +_("The channel is not ready yet"));
>  return;
>  }
>  
> diff --git a/src/spice-pulse.c b/src/spice-pulse.c
> index 60a037c..5c3cfb7 100644
> --- a/src/spice-pulse.c
> +++ b/src/spice-pulse.c
> @@ -28,6 +28,8 @@
>  #include 
>  #include 
>  
> +#include 
> +
>  #define SPICE_PULSE_GET_PRIVATE(obj)  \
>  (G_TYPE_INSTANCE_GET_PRIVATE((obj), SPICE_TYPE_PULSE, SpicePulsePrivate))
>  
> @@ -995,7 +997,7 @@ static void complete_task(SpicePulse *pulse, struct
> async_task *task, const gcha
>  g_task_return_new_error(task->task,
>  SPICE_CLIENT_ERROR,
>  SPICE_CLIENT_ERROR_FAILED,
> -"restore-info failed due %s",
> +_("restore-info failed due %s"),


As long as you're making a change here, it might be good to change this to "due
to %s" instead of "due %s"? O

Re: [Spice-devel] [spice-gtk PATCH v2] gstaudio: set output parameter to NULL on error

2016-01-18 Thread Jonathon Jongsma
Acked-by: Jonathon Jongsma 

On Mon, 2016-01-18 at 15:09 +0100, Victor Toso wrote:
> This is not really triggered in the current code but this is usually
> expected in case of errors; Also, the same function on record side
> already does this.
> ---
>  src/spice-gstaudio.c | 4 
>  1 file changed, 4 insertions(+)
> 
> diff --git a/src/spice-gstaudio.c b/src/spice-gstaudio.c
> index 096fea4..2759c2b 100644
> --- a/src/spice-gstaudio.c
> +++ b/src/spice-gstaudio.c
> @@ -600,6 +600,10 @@ static gboolean
> spice_gstaudio_get_playback_volume_info_finish(SpiceAudio *audio
>  G_OBJECT(audio), spice_gstaudio_get_playback_volume_info_async),
> FALSE);
>  
>  if (g_simple_async_result_propagate_error(simple, error)) {
> +/* set out args that should have new alloc'ed memory to NULL */
> +if (volume != NULL) {
> +*volume = NULL;
> +}
>  return FALSE;
>  }
>  
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] Glib loop and scary corruption

2016-01-18 Thread Frediano Ziglio
Hi,
  I spend some time investigating in 
http://cgit.freedesktop.org/~fziglio/spice-server/commit/?h=refactory&id=48d5c2e74b6a866df2562c1aab8a1a3803bc788b,
one of the last problems of glib loop.
Beside I though that this patch also fix the symmetry between creation and 
destroying (stream is initialized during creation so usually is a good idea to 
deinitialize during destroying).
Looking at the backtrace you can see that stream is inside a event handler 
after being freed by red_channel_client_disconnect called trying to push items 
(red_channel_client_push).
My first idea was that glib called the event handler event after the watch was 
freed. This proved false after some testing.
So I decided to checkout more or less same version and look at the code.
Code was failing trying to retrieve header for a message, the push was called 
from red_channel_client_push handling a message of type SPICE_MSGC_ACK.
But messages are read and handled in a loop in red_peer_handle_incoming which 
is called by a single watcher!
So what's happen if:
- SPICE_MSGC_ACK is read
- handler is called with SPICE_MSGC_ACK
- handler try to push messages
- write fails as connection was closed
- red_channel_client_disconnect is called
- handler return to red_peer_handle_incoming
- red_peer_handle_incoming calls red_peer_receive to read next message header 
(NOTE: error handler in red_peer_handle_incoming is called only if message is 
not handled)
- red_peer_receive crash as rcc->stream is NULL!

If you add a red_channel_client_disconnect after red_channel_client_push in 
red_channel_client_handle_message you can see the same problem.
At this point. Why with Glib loop this happens more often? The reason is that 
the push is not called at last step of iteration so there is more probability 
to find items in red_channel_client_push (or at least the statistics on this 
change).

So to sum up:
- this issue is not a regression introduced by glib code;
- the only thing left to check for glib is this statistical stuff (already at 
good point for Jonathon work).

I'll post the patch based on master.

Frediano
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH 11/14] vmcstream: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Christophe Fergeau
On Mon, Jan 18, 2016 at 10:05:47AM +0100, Fabiano Fidêncio wrote:
> Instead of using GSimpleAsyncResult, use the new GTask API, which is
> much more straightforward.
> ---
>  src/vmcstream.c | 129 
> +++-
>  1 file changed, 52 insertions(+), 77 deletions(-)
> 
> diff --git a/src/vmcstream.c b/src/vmcstream.c
> index 483dd5a..d9b62a0 100644
> --- a/src/vmcstream.c
> +++ b/src/vmcstream.c
> @@ -27,7 +27,7 @@
>  struct _SpiceVmcInputStream
>  {
>  GInputStream parent_instance;
> -GSimpleAsyncResult *result;
> +GTask *task;
>  struct coroutine *coroutine;
>  
>  SpiceChannel *channel;
> @@ -36,7 +36,6 @@ struct _SpiceVmcInputStream
>  gsize count;
>  gsize pos;
>  
> -GCancellable *cancellable;
>  gulong cancel_id;
>  };
>  
> @@ -118,11 +117,12 @@ spice_vmc_input_stream_co_data(SpiceVmcInputStream 
> *self,
>  self->coroutine = coroutine_self();
>  
>  while (size > 0) {
> -SPICE_DEBUG("spicevmc co_data %p", self->result);
> -if (!self->result)
> +GCancellable *cancellable;
> +SPICE_DEBUG("spicevmc co_data %p", self->task);
> +if (!self->task)
>  coroutine_yield(NULL);
>  
> -g_return_if_fail(self->result != NULL);
> +g_return_if_fail(self->task != NULL);
>  
>  gsize min = MIN(self->count, size);
>  memcpy(self->buffer, data, min);
> @@ -139,14 +139,13 @@ spice_vmc_input_stream_co_data(SpiceVmcInputStream 
> *self,
>  if (self->all && min > 0 && self->pos != self->count)
>  continue;
>  
> -g_simple_async_result_set_op_res_gssize(self->result, self->pos);
> +g_task_return_int(self->task, self->pos);
> +
> +cancellable = g_task_get_cancellable(self->task);
> +if (cancellable)
> +g_cancellable_disconnect(cancellable, self->cancel_id);
>  
> -g_simple_async_result_complete_in_idle(self->result);
> -g_clear_object(&self->result);
> -if (self->cancellable) {
> -g_cancellable_disconnect(self->cancellable, self->cancel_id);
> -g_clear_object(&self->cancellable);
> -}
> +g_clear_object(&self->task);
>  }
>  
>  self->coroutine = NULL;
> @@ -158,13 +157,12 @@ read_cancelled(GCancellable *cancellable,
>  {
>  SpiceVmcInputStream *self = SPICE_VMC_INPUT_STREAM(user_data);
>  
> -SPICE_DEBUG("read cancelled, %p", self->result);
> -g_simple_async_result_set_error(self->result,
> -G_IO_ERROR, G_IO_ERROR_CANCELLED,
> -"read cancelled");
> -g_simple_async_result_complete_in_idle(self->result);
> +SPICE_DEBUG("read cancelled, %p", self->task);
> +g_task_return_new_error(self->task,
> +G_IO_ERROR, G_IO_ERROR_CANCELLED,
> +"read cancelled");
>  
> -g_clear_object(&self->result);
> +g_clear_object(&self->task);
>  
>  /* See FIXME */
>  /* if (self->cancellable) { */
> @@ -183,21 +181,20 @@ spice_vmc_input_stream_read_all_async(GInputStream  
>   *stream,
>gpointer user_data)
>  {
>  SpiceVmcInputStream *self = SPICE_VMC_INPUT_STREAM(stream);
> -GSimpleAsyncResult *result;
> +GTask *task;
>  
>  /* no concurrent read permitted by ginputstream */
> -g_return_if_fail(self->result == NULL);
> -g_return_if_fail(self->cancellable == NULL);
> +g_return_if_fail(self->task == NULL);
> +g_return_if_fail(g_task_get_cancellable(self->task) == NULL);
>  self->all = TRUE;
>  self->buffer = buffer;
>  self->count = count;
>  self->pos = 0;
> -result = g_simple_async_result_new(G_OBJECT(self),
> -   callback,
> -   user_data,
> -   spice_vmc_input_stream_read_async);
> -self->result = result;
> -self->cancellable = g_object_ref(cancellable);
> +task = g_task_new(self,
> +  cancellable,
> +  callback,
> +  user_data);
> +self->task = task;
>  if (cancellable)
>  self->cancel_id =
>  g_cancellable_connect(cancellable, G_CALLBACK(read_cancelled), 
> self, NULL);
> @@ -211,27 +208,19 @@ spice_vmc_input_stream_read_all_finish(GInputStream 
> *stream,
> GAsyncResult *result,
> GError **error)
>  {
> -GSimpleAsyncResult *simple;
> +GTask *task = G_TASK(result);
> +GCancellable *cancellable;
>  SpiceVmcInputStream *self = SPICE_VMC_INPUT_STREAM(stream);
>  
> -g_return_val_if_fail(g_simple_async_result_is_valid(result,
> -G_OBJECT(self),
> -
> spice_vmc_inpu

Re: [Spice-devel] [PATCH 09/14] usb-acl-helper: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Christophe Fergeau
On Mon, Jan 18, 2016 at 10:05:45AM +0100, Fabiano Fidêncio wrote:
> Instead of using GSimpleAsyncResult, use the new GTask API, which is
> much more straightforward.
> ---
>  src/usb-acl-helper.c | 76 
> 
>  1 file changed, 35 insertions(+), 41 deletions(-)
> 
> diff --git a/src/usb-acl-helper.c b/src/usb-acl-helper.c
> index 6a49627..17e2b3c 100644
> --- a/src/usb-acl-helper.c
> +++ b/src/usb-acl-helper.c
> @@ -35,10 +35,9 @@
>  (G_TYPE_INSTANCE_GET_PRIVATE ((obj), SPICE_TYPE_USB_ACL_HELPER, 
> SpiceUsbAclHelperPrivate))
>  
>  struct _SpiceUsbAclHelperPrivate {
> -GSimpleAsyncResult *result;
> +GTask *task;
>  GIOChannel *in_ch;
>  GIOChannel *out_ch;
> -GCancellable *cancellable;
>  gulong cancellable_id;
>  };
>  
> @@ -53,11 +52,11 @@ static void 
> spice_usb_acl_helper_cleanup(SpiceUsbAclHelper *self)
>  {
>  SpiceUsbAclHelperPrivate *priv = self->priv;
>  
> -g_cancellable_disconnect(priv->cancellable, priv->cancellable_id);
> -priv->cancellable = NULL;
> +g_cancellable_disconnect(g_task_get_cancellable(priv->task),
> + priv->cancellable_id);
>  priv->cancellable_id = 0;
>  
> -g_clear_object(&priv->result);
> +g_clear_object(&priv->task);
>  
>  if (priv->in_ch) {
>  g_io_channel_unref(priv->in_ch);
> @@ -90,9 +89,9 @@ static void 
> spice_usb_acl_helper_class_init(SpiceUsbAclHelperClass *klass)
>  /* -- */
>  /* callbacks  */
>  
> -static void async_result_set_cancelled(GSimpleAsyncResult *result)
> +static void async_result_set_cancelled(GTask *task)
>  {
> -g_simple_async_result_set_error(result,
> +g_task_return_new_error(task,
>  G_IO_ERROR, G_IO_ERROR_CANCELLED,
>  "Setting USB device node ACL cancelled");
>  }
> @@ -105,12 +104,13 @@ static gboolean cb_out_watch(GIOChannel*channel,
>  SpiceUsbAclHelperPrivate *priv = self->priv;
>  gboolean success = FALSE;
>  GError *err = NULL;
> +GCancellable *cancellable;
>  GIOStatus status;
>  gchar *string;
>  gsize size;
>  
>  /* Check that we've not been cancelled */
> -if (priv->result == NULL)
> +if (priv->task == NULL)
>  goto done;
>  
>  g_return_val_if_fail(channel == priv->out_ch, FALSE);
> @@ -121,10 +121,11 @@ static gboolean cb_out_watch(GIOChannel*channel,
>  string[strlen(string) - 1] = 0;
>  if (!strcmp(string, "SUCCESS")) {
>  success = TRUE;
> +g_task_return_boolean(priv->task, TRUE);
>  } else if (!strcmp(string, "CANCELED")) {
> -async_result_set_cancelled(priv->result);
> +async_result_set_cancelled(priv->task);
>  } else {
> -g_simple_async_result_set_error(priv->result,
> +g_task_return_new_error(priv->task,
>  SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
>  "Error setting USB device node ACL: '%s'",
>  string);
> @@ -132,10 +133,10 @@ static gboolean cb_out_watch(GIOChannel*channel,
>  g_free(string);
>  break;
>  case G_IO_STATUS_ERROR:
> -g_simple_async_result_take_error(priv->result, err);
> +g_task_return_error(priv->task, err);
>  break;
>  case G_IO_STATUS_EOF:
> -g_simple_async_result_set_error(priv->result,
> +g_task_return_new_error(priv->task,
>  SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
>  "Unexpected EOF reading from acl helper stdout");
>  break;
> @@ -143,16 +144,16 @@ static gboolean cb_out_watch(GIOChannel*channel,
>  return TRUE; /* Wait for more input */
>  }
>  
> -g_cancellable_disconnect(priv->cancellable, priv->cancellable_id);
> -priv->cancellable = NULL;
> +cancellable = g_task_get_cancellable(priv->task);
> +g_cancellable_disconnect(cancellable, priv->cancellable_id);
> +cancellable = NULL;

I forgot to mention in my previous mail that setting cancellable to NULL
is probably not needed.

Christophe


signature.asc
Description: PGP signature
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH 09/14] usb-acl-helper: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Christophe Fergeau
On Mon, Jan 18, 2016 at 10:05:45AM +0100, Fabiano Fidêncio wrote:
> Instead of using GSimpleAsyncResult, use the new GTask API, which is
> much more straightforward.
> ---
>  src/usb-acl-helper.c | 76 
> 
>  1 file changed, 35 insertions(+), 41 deletions(-)
> 
> diff --git a/src/usb-acl-helper.c b/src/usb-acl-helper.c
> index 6a49627..17e2b3c 100644
> --- a/src/usb-acl-helper.c
> +++ b/src/usb-acl-helper.c
> @@ -35,10 +35,9 @@
>  (G_TYPE_INSTANCE_GET_PRIVATE ((obj), SPICE_TYPE_USB_ACL_HELPER, 
> SpiceUsbAclHelperPrivate))
>  
>  struct _SpiceUsbAclHelperPrivate {
> -GSimpleAsyncResult *result;
> +GTask *task;
>  GIOChannel *in_ch;
>  GIOChannel *out_ch;
> -GCancellable *cancellable;
>  gulong cancellable_id;
>  };
>  
> @@ -53,11 +52,11 @@ static void 
> spice_usb_acl_helper_cleanup(SpiceUsbAclHelper *self)
>  {
>  SpiceUsbAclHelperPrivate *priv = self->priv;
>  
> -g_cancellable_disconnect(priv->cancellable, priv->cancellable_id);
> -priv->cancellable = NULL;
> +g_cancellable_disconnect(g_task_get_cancellable(priv->task),
> + priv->cancellable_id);
>  priv->cancellable_id = 0;
>  
> -g_clear_object(&priv->result);
> +g_clear_object(&priv->task);
>  
>  if (priv->in_ch) {
>  g_io_channel_unref(priv->in_ch);
> @@ -90,9 +89,9 @@ static void 
> spice_usb_acl_helper_class_init(SpiceUsbAclHelperClass *klass)
>  /* -- */
>  /* callbacks  */
>  
> -static void async_result_set_cancelled(GSimpleAsyncResult *result)
> +static void async_result_set_cancelled(GTask *task)
>  {
> -g_simple_async_result_set_error(result,
> +g_task_return_new_error(task,
>  G_IO_ERROR, G_IO_ERROR_CANCELLED,
>  "Setting USB device node ACL cancelled");
>  }
> @@ -105,12 +104,13 @@ static gboolean cb_out_watch(GIOChannel*channel,
>  SpiceUsbAclHelperPrivate *priv = self->priv;
>  gboolean success = FALSE;
>  GError *err = NULL;
> +GCancellable *cancellable;
>  GIOStatus status;
>  gchar *string;
>  gsize size;
>  
>  /* Check that we've not been cancelled */
> -if (priv->result == NULL)
> +if (priv->task == NULL)
>  goto done;
>  
>  g_return_val_if_fail(channel == priv->out_ch, FALSE);
> @@ -121,10 +121,11 @@ static gboolean cb_out_watch(GIOChannel*channel,
>  string[strlen(string) - 1] = 0;
>  if (!strcmp(string, "SUCCESS")) {
>  success = TRUE;
> +g_task_return_boolean(priv->task, TRUE);
>  } else if (!strcmp(string, "CANCELED")) {
> -async_result_set_cancelled(priv->result);
> +async_result_set_cancelled(priv->task);
>  } else {
> -g_simple_async_result_set_error(priv->result,
> +g_task_return_new_error(priv->task,
>  SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
>  "Error setting USB device node ACL: '%s'",
>  string);
> @@ -132,10 +133,10 @@ static gboolean cb_out_watch(GIOChannel*channel,
>  g_free(string);
>  break;
>  case G_IO_STATUS_ERROR:
> -g_simple_async_result_take_error(priv->result, err);
> +g_task_return_error(priv->task, err);
>  break;
>  case G_IO_STATUS_EOF:
> -g_simple_async_result_set_error(priv->result,
> +g_task_return_new_error(priv->task,
>  SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
>  "Unexpected EOF reading from acl helper stdout");
>  break;
> @@ -143,16 +144,16 @@ static gboolean cb_out_watch(GIOChannel*channel,
>  return TRUE; /* Wait for more input */
>  }
>  
> -g_cancellable_disconnect(priv->cancellable, priv->cancellable_id);
> -priv->cancellable = NULL;
> +cancellable = g_task_get_cancellable(priv->task);
> +g_cancellable_disconnect(cancellable, priv->cancellable_id);
> +cancellable = NULL;
>  priv->cancellable_id = 0;
>  
> -g_simple_async_result_complete_in_idle(priv->result);
> -g_clear_object(&priv->result);
> -
>  if (!success)
>  spice_usb_acl_helper_cleanup(self);
>  
> +g_clear_object(&priv->task);
> +
>  done:
>  g_object_unref(self);
>  return FALSE;
> @@ -193,7 +194,7 @@ void spice_usb_acl_helper_open_acl(SpiceUsbAclHelper 
> *self,
>  g_return_if_fail(SPICE_IS_USB_ACL_HELPER(self));
>  
>  SpiceUsbAclHelperPrivate *priv = self->priv;
> -GSimpleAsyncResult *result;
> +GTask *task;
>  GError *err = NULL;
>  GIOStatus status;
>  GPid helper_pid;
> @@ -202,25 +203,24 @@ void spice_usb_acl_helper_open_acl(SpiceUsbAclHelper 
> *self,
>  g

[Spice-devel] [PATCH 09/15] Change reds_on_main_agent_start() to take RedsState arg

2016-01-18 Thread Frediano Ziglio
From: Jonathon Jongsma 

---
 server/main-channel.c | 2 +-
 server/reds.c | 2 +-
 server/reds.h | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/server/main-channel.c b/server/main-channel.c
index b5268fb..0ab3dec 100644
--- a/server/main-channel.c
+++ b/server/main-channel.c
@@ -891,7 +891,7 @@ static int main_channel_handle_parsed(RedChannelClient 
*rcc, uint32_t size, uint
 return FALSE;
 }
 tokens = (SpiceMsgcMainAgentStart *)message;
-reds_on_main_agent_start(mcc, tokens->num_tokens);
+reds_on_main_agent_start(reds, mcc, tokens->num_tokens);
 break;
 }
 case SPICE_MSGC_MAIN_AGENT_DATA: {
diff --git a/server/reds.c b/server/reds.c
index bd905e2..db1f718 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -944,7 +944,7 @@ void reds_fill_channels(RedsState *reds, SpiceMsgChannels 
*channels_info)
 }
 }
 
-void reds_on_main_agent_start(MainChannelClient *mcc, uint32_t num_tokens)
+void reds_on_main_agent_start(RedsState *reds, MainChannelClient *mcc, 
uint32_t num_tokens)
 {
 SpiceCharDeviceState *dev_state = reds->agent_state.base;
 RedChannelClient *rcc;
diff --git a/server/reds.h b/server/reds.h
index fbb616d..4033724 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -94,7 +94,7 @@ void reds_update_stat_value(uint32_t value);
 
 /* callbacks from main channel messages */
 
-void reds_on_main_agent_start(MainChannelClient *mcc, uint32_t num_tokens);
+void reds_on_main_agent_start(RedsState *reds, MainChannelClient *mcc, 
uint32_t num_tokens);
 void reds_on_main_agent_tokens(MainChannelClient *mcc, uint32_t num_tokens);
 uint8_t *reds_get_agent_data_buffer(MainChannelClient *mcc, size_t size);
 void reds_release_agent_data_buffer(uint8_t *buf);
-- 
2.4.3

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH 08/15] Change reds_fill_channels() to take a RedsState arg

2016-01-18 Thread Frediano Ziglio
From: Jonathon Jongsma 

---
 server/main-channel.c | 2 +-
 server/reds.c | 2 +-
 server/reds.h | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/server/main-channel.c b/server/main-channel.c
index 1b774f3..b5268fb 100644
--- a/server/main-channel.c
+++ b/server/main-channel.c
@@ -349,7 +349,7 @@ static void main_channel_marshall_channels(RedChannelClient 
*rcc,
 red_channel_client_init_send_data(rcc, SPICE_MSG_MAIN_CHANNELS_LIST, item);
 channels_info = (SpiceMsgChannels *)spice_malloc(sizeof(SpiceMsgChannels)
 + reds_num_of_channels(reds) * 
sizeof(SpiceChannelId));
-reds_fill_channels(channels_info);
+reds_fill_channels(reds, channels_info);
 spice_marshall_msg_main_channels_list(m, channels_info);
 free(channels_info);
 }
diff --git a/server/reds.c b/server/reds.c
index 0169fac..bd905e2 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -922,7 +922,7 @@ static int channel_is_secondary(RedChannel *channel)
 return FALSE;
 }
 
-void reds_fill_channels(SpiceMsgChannels *channels_info)
+void reds_fill_channels(RedsState *reds, SpiceMsgChannels *channels_info)
 {
 RingItem *now;
 int used_channels = 0;
diff --git a/server/reds.h b/server/reds.h
index aaa9477..fbb616d 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -86,7 +86,7 @@ void reds_client_disconnect(RedsState *reds, RedClient 
*client);
 // Temporary (?) for splitting main channel
 typedef struct MainMigrateData MainMigrateData;
 void reds_marshall_migrate_data(SpiceMarshaller *m);
-void reds_fill_channels(SpiceMsgChannels *channels_info);
+void reds_fill_channels(RedsState *reds, SpiceMsgChannels *channels_info);
 int reds_num_of_channels(RedsState *reds);
 #ifdef RED_STATISTICS
 void reds_update_stat_value(uint32_t value);
-- 
2.4.3

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH 04/15] Change vdi_port_read_buf_unref() to take RedsState arg

2016-01-18 Thread Frediano Ziglio
From: Jonathon Jongsma 

---
 server/reds.c | 17 ++---
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/server/reds.c b/server/reds.c
index 928cb83..4e0caba 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -214,7 +214,7 @@ static void reds_send_mm_time(void);
 
 static VDIReadBuf *vdi_port_read_buf_get(RedsState *reds);
 static VDIReadBuf *vdi_port_read_buf_ref(VDIReadBuf *buf);
-static void vdi_port_read_buf_unref(VDIReadBuf *buf);
+static void vdi_port_read_buf_unref(RedsState *reds, VDIReadBuf *buf);
 
 static ChannelSecurityOptions *channels_security = NULL;
 static int default_channel_security =
@@ -440,7 +440,7 @@ static void reds_reset_vdp(RedsState *reds)
 state->receive_len = sizeof(state->vdi_chunk_header);
 state->message_receive_len = 0;
 if (state->current_read_buf) {
-vdi_port_read_buf_unref(state->current_read_buf);
+vdi_port_read_buf_unref(reds, state->current_read_buf);
 state->current_read_buf = NULL;
 }
 /* Reset read filter to start with clean state when the agent reconnects */
@@ -658,7 +658,7 @@ static void vdi_port_read_buf_release(uint8_t *data, void 
*opaque)
 {
 VDIReadBuf *buf = (VDIReadBuf *)opaque;
 
-vdi_port_read_buf_unref(buf);
+vdi_port_read_buf_unref(reds, buf);
 }
 
 /* returns TRUE if the buffer can be forwarded */
@@ -713,7 +713,9 @@ static VDIReadBuf* vdi_port_read_buf_ref(VDIReadBuf *buf)
 return buf;
 }
 
-static void vdi_port_read_buf_unref(VDIReadBuf *buf)
+/* FIXME: refactor so that unreffing the VDIReadBuf doesn't require accessing
+ * RedsState? */
+static void vdi_port_read_buf_unref(RedsState *reds, VDIReadBuf *buf)
 {
 if (!--buf->refs) {
 ring_add(&reds->agent_state.read_bufs, &buf->link);
@@ -790,7 +792,7 @@ static SpiceCharDeviceMsgToClient 
*vdi_port_read_one_msg_from_device(SpiceCharDe
 if (vdi_port_read_buf_process(reds, state->vdi_chunk_header.port, 
dispatch_buf)) {
 return dispatch_buf;
 } else {
-vdi_port_read_buf_unref(dispatch_buf);
+vdi_port_read_buf_unref(reds, dispatch_buf);
 }
 } /* END switch */
 } /* END while */
@@ -806,7 +808,8 @@ static SpiceCharDeviceMsgToClient 
*vdi_port_ref_msg_to_client(SpiceCharDeviceMsg
 static void vdi_port_unref_msg_to_client(SpiceCharDeviceMsgToClient *msg,
   void *opaque)
 {
-vdi_port_read_buf_unref(msg);
+RedsState *reds = opaque;
+vdi_port_read_buf_unref(reds, msg);
 }
 
 /* after calling this, we unref the message, and the ref is in the instance 
side */
@@ -1163,7 +1166,7 @@ void reds_on_main_channel_migrate(MainChannelClient *mcc)
 vdi_port_read_buf_release,
 read_buf);
 } else {
-vdi_port_read_buf_unref(read_buf);
+vdi_port_read_buf_unref(reds, read_buf);
 }
 
 spice_assert(agent_state->receive_len);
-- 
2.4.3

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH 13/15] Change red_on_main_agent_data() to take RedsState arg

2016-01-18 Thread Frediano Ziglio
From: Jonathon Jongsma 

---
 server/main-channel.c | 2 +-
 server/reds.c | 6 +++---
 server/reds.h | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/server/main-channel.c b/server/main-channel.c
index 3315d6c..a30ba1e 100644
--- a/server/main-channel.c
+++ b/server/main-channel.c
@@ -895,7 +895,7 @@ static int main_channel_handle_parsed(RedChannelClient 
*rcc, uint32_t size, uint
 break;
 }
 case SPICE_MSGC_MAIN_AGENT_DATA: {
-reds_on_main_agent_data(mcc, message, size);
+reds_on_main_agent_data(reds, mcc, message, size);
 break;
 }
 case SPICE_MSGC_MAIN_AGENT_TOKEN: {
diff --git a/server/reds.c b/server/reds.c
index 5c038ca..37d0393 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -1050,7 +1050,7 @@ static void reds_client_monitors_config_cleanup(RedsState 
*reds)
 cmc->mcc = NULL;
 }
 
-static void reds_on_main_agent_monitors_config(
+static void reds_on_main_agent_monitors_config(RedsState *reds,
 MainChannelClient *mcc, void *message, size_t size)
 {
 VDAgentMessage *msg_header;
@@ -1075,7 +1075,7 @@ static void reds_on_main_agent_monitors_config(
 reds_client_monitors_config_cleanup(reds);
 }
 
-void reds_on_main_agent_data(MainChannelClient *mcc, void *message, size_t 
size)
+void reds_on_main_agent_data(RedsState *reds, MainChannelClient *mcc, void 
*message, size_t size)
 {
 VDIPortState *dev_state = &reds->agent_state;
 VDIChunkHeader *header;
@@ -1089,7 +1089,7 @@ void reds_on_main_agent_data(MainChannelClient *mcc, void 
*message, size_t size)
 case AGENT_MSG_FILTER_DISCARD:
 return;
 case AGENT_MSG_FILTER_MONITORS_CONFIG:
-reds_on_main_agent_monitors_config(mcc, message, size);
+reds_on_main_agent_monitors_config(reds, mcc, message, size);
 return;
 case AGENT_MSG_FILTER_PROTO_ERROR:
 red_channel_client_shutdown(main_channel_client_get_base(mcc));
diff --git a/server/reds.h b/server/reds.h
index 0294333..9672c5e 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -98,7 +98,7 @@ void reds_on_main_agent_start(RedsState *reds, 
MainChannelClient *mcc, uint32_t
 void reds_on_main_agent_tokens(MainChannelClient *mcc, uint32_t num_tokens);
 uint8_t *reds_get_agent_data_buffer(RedsState *reds, MainChannelClient *mcc, 
size_t size);
 void reds_release_agent_data_buffer(RedsState *reds, uint8_t *buf);
-void reds_on_main_agent_data(MainChannelClient *mcc, void *message, size_t 
size);
+void reds_on_main_agent_data(RedsState *reds, MainChannelClient *mcc, void 
*message, size_t size);
 void reds_on_main_migrate_connected(int seamless); //should be called when all 
the clients
// are connected to the 
target
 int reds_handle_migrate_data(MainChannelClient *mcc,
-- 
2.4.3

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH 03/15] Change vdi_port_read_buf_get() to take RedsState arg

2016-01-18 Thread Frediano Ziglio
From: Jonathon Jongsma 

---
 server/reds.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/server/reds.c b/server/reds.c
index b347d1d..928cb83 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -212,7 +212,7 @@ static void reds_char_device_add_state(SpiceCharDeviceState 
*st);
 static void reds_char_device_remove_state(SpiceCharDeviceState *st);
 static void reds_send_mm_time(void);
 
-static VDIReadBuf *vdi_port_read_buf_get(void);
+static VDIReadBuf *vdi_port_read_buf_get(RedsState *reds);
 static VDIReadBuf *vdi_port_read_buf_ref(VDIReadBuf *buf);
 static void vdi_port_read_buf_unref(VDIReadBuf *buf);
 
@@ -690,7 +690,7 @@ static int vdi_port_read_buf_process(RedsState *reds, int 
port, VDIReadBuf *buf)
 }
 }
 
-static VDIReadBuf *vdi_port_read_buf_get(void)
+static VDIReadBuf *vdi_port_read_buf_get(RedsState *reds)
 {
 VDIPortState *state = &reds->agent_state;
 RingItem *item;
@@ -758,7 +758,7 @@ static SpiceCharDeviceMsgToClient 
*vdi_port_read_one_msg_from_device(SpiceCharDe
 state->message_receive_len = state->vdi_chunk_header.size;
 state->read_state = VDI_PORT_READ_STATE_GET_BUFF;
 case VDI_PORT_READ_STATE_GET_BUFF: {
-if (!(state->current_read_buf = vdi_port_read_buf_get())) {
+if (!(state->current_read_buf = vdi_port_read_buf_get(reds))) {
 return NULL;
 }
 state->receive_pos = state->current_read_buf->data;
@@ -1281,7 +1281,7 @@ static int reds_agent_state_restore(SpiceMigrateDataMain 
*mig_data)
 uint32_t cur_buf_size;
 
 agent_state->read_state = VDI_PORT_READ_STATE_READ_DATA;
-agent_state->current_read_buf = vdi_port_read_buf_get();
+agent_state->current_read_buf = vdi_port_read_buf_get(reds);
 spice_assert(agent_state->current_read_buf);
 partial_msg_header = (uint8_t *)mig_data + 
mig_data->agent2client.msg_header_ptr -
 sizeof(SpiceMiniDataHeader);
-- 
2.4.3

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH 12/15] Change reds_client_monitors_config_cleanup() to take RedsState arg

2016-01-18 Thread Frediano Ziglio
From: Jonathon Jongsma 

---
 server/reds.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/server/reds.c b/server/reds.c
index b183ee1..5c038ca 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -1040,7 +1040,7 @@ void reds_release_agent_data_buffer(RedsState *reds, 
uint8_t *buf)
 dev_state->recv_from_client_buf_pushed = FALSE;
 }
 
-static void reds_client_monitors_config_cleanup(void)
+static void reds_client_monitors_config_cleanup(RedsState *reds)
 {
 RedsClientMonitorsConfig *cmc = &reds->client_monitors_config;
 
@@ -1072,7 +1072,7 @@ static void reds_on_main_agent_monitors_config(
 monitors_config = (VDAgentMonitorsConfig *)(cmc->buffer + 
sizeof(*msg_header));
 spice_debug("%s: %d", __func__, monitors_config->num_of_monitors);
 red_dispatcher_client_monitors_config(monitors_config);
-reds_client_monitors_config_cleanup();
+reds_client_monitors_config_cleanup(reds);
 }
 
 void reds_on_main_agent_data(MainChannelClient *mcc, void *message, size_t 
size)
@@ -3418,7 +3418,7 @@ static int do_spice_init(SpiceCoreInterface 
*core_interface)
 
 reds->mouse_mode = SPICE_MOUSE_MODE_SERVER;
 
-reds_client_monitors_config_cleanup();
+reds_client_monitors_config_cleanup(reds);
 
 reds->allow_multiple_clients = getenv(SPICE_DEBUG_ALLOW_MC_ENV) != NULL;
 if (reds->allow_multiple_clients) {
-- 
2.4.3

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH 07/15] Change reds_num_of_clients() to take RedsState arg

2016-01-18 Thread Frediano Ziglio
From: Jonathon Jongsma 

---
 server/reds.c | 4 ++--
 server/reds.h | 1 -
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/server/reds.c b/server/reds.c
index 9b28a7c..0169fac 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -897,7 +897,7 @@ int reds_num_of_channels(RedsState *reds)
 }
 
 
-int reds_num_of_clients(void)
+static int reds_num_of_clients(RedsState *reds)
 {
 return reds ? reds->num_clients : 0;
 }
@@ -905,7 +905,7 @@ int reds_num_of_clients(void)
 SPICE_GNUC_VISIBLE int spice_server_get_num_clients(SpiceServer *s)
 {
 spice_assert(reds == s);
-return reds_num_of_clients();
+return reds_num_of_clients(reds);
 }
 
 static int secondary_channels[] = {
diff --git a/server/reds.h b/server/reds.h
index 65e8f69..aaa9477 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -88,7 +88,6 @@ typedef struct MainMigrateData MainMigrateData;
 void reds_marshall_migrate_data(SpiceMarshaller *m);
 void reds_fill_channels(SpiceMsgChannels *channels_info);
 int reds_num_of_channels(RedsState *reds);
-int reds_num_of_clients(void);
 #ifdef RED_STATISTICS
 void reds_update_stat_value(uint32_t value);
 #endif
-- 
2.4.3

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH 14/15] reds_num_of_channels() -> reds_get_n_channels()

2016-01-18 Thread Frediano Ziglio
From: Jonathon Jongsma 

More consistent with glib naming conventions.
---
 server/main-channel.c | 2 +-
 server/reds.c | 2 +-
 server/reds.h | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/server/main-channel.c b/server/main-channel.c
index a30ba1e..9f8a861 100644
--- a/server/main-channel.c
+++ b/server/main-channel.c
@@ -348,7 +348,7 @@ static void main_channel_marshall_channels(RedChannelClient 
*rcc,
 
 red_channel_client_init_send_data(rcc, SPICE_MSG_MAIN_CHANNELS_LIST, item);
 channels_info = (SpiceMsgChannels *)spice_malloc(sizeof(SpiceMsgChannels)
-+ reds_num_of_channels(reds) * 
sizeof(SpiceChannelId));
++ reds_get_n_channels(reds) * 
sizeof(SpiceChannelId));
 reds_fill_channels(reds, channels_info);
 spice_marshall_msg_main_channels_list(m, channels_info);
 free(channels_info);
diff --git a/server/reds.c b/server/reds.c
index 37d0393..4de1640 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -891,7 +891,7 @@ void reds_handle_agent_mouse_event(RedsState *reds, const 
VDAgentMouseState *mou
 spice_char_device_write_buffer_add(reds->agent_state.base, char_dev_buf);
 }
 
-int reds_num_of_channels(RedsState *reds)
+int reds_get_n_channels(RedsState *reds)
 {
 return reds ? reds->num_of_channels : 0;
 }
diff --git a/server/reds.h b/server/reds.h
index 9672c5e..39fe291 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -87,7 +87,7 @@ void reds_client_disconnect(RedsState *reds, RedClient 
*client);
 typedef struct MainMigrateData MainMigrateData;
 void reds_marshall_migrate_data(SpiceMarshaller *m);
 void reds_fill_channels(RedsState *reds, SpiceMsgChannels *channels_info);
-int reds_num_of_channels(RedsState *reds);
+int reds_get_n_channels(RedsState *reds);
 #ifdef RED_STATISTICS
 void reds_update_stat_value(uint32_t value);
 #endif
-- 
2.4.3

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH 01/15] Pass 'reds' as opaque data in vdi port char device

2016-01-18 Thread Frediano Ziglio
From: Jonathon Jongsma 

This allows us to access the RedsState variable non-globally without
changing the signature of the callback functions.
---
 server/reds.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/server/reds.c b/server/reds.c
index 9868928..25e9f90 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -733,6 +733,7 @@ static void vdi_port_read_buf_unref(VDIReadBuf *buf)
 static SpiceCharDeviceMsgToClient 
*vdi_port_read_one_msg_from_device(SpiceCharDeviceInstance *sin,
  void 
*opaque)
 {
+RedsState *reds = opaque;
 VDIPortState *state = &reds->agent_state;
 SpiceCharDeviceInterface *sif;
 VDIReadBuf *dispatch_buf;
@@ -2987,7 +2988,7 @@ static SpiceCharDeviceState 
*attach_to_red_agent(SpiceCharDeviceInstance *sin)
  REDS_TOKENS_TO_SEND,
  
REDS_NUM_INTERNAL_AGENT_MESSAGES,
  &char_dev_state_cbs,
- NULL);
+ reds);
 } else {
 spice_char_device_state_reset_dev_instance(state->base, sin);
 }
-- 
2.4.3

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH 15/15] reds_num_of_clients() -> reds_get_n_clients()

2016-01-18 Thread Frediano Ziglio
From: Jonathon Jongsma 

More consistent with glib naming conventions. Also make the function
static since it's not used outside of this source file.
---
 server/reds.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/server/reds.c b/server/reds.c
index 4de1640..22ab26d 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -897,7 +897,7 @@ int reds_get_n_channels(RedsState *reds)
 }
 
 
-static int reds_num_of_clients(RedsState *reds)
+static int reds_get_n_clients(RedsState *reds)
 {
 return reds ? reds->num_clients : 0;
 }
@@ -905,7 +905,7 @@ static int reds_num_of_clients(RedsState *reds)
 SPICE_GNUC_VISIBLE int spice_server_get_num_clients(SpiceServer *s)
 {
 spice_assert(reds == s);
-return reds_num_of_clients(reds);
+return reds_get_n_clients(reds);
 }
 
 static int secondary_channels[] = {
-- 
2.4.3

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH 11/15] Change reds_release_agent_data_buffer() to take RedsState arg

2016-01-18 Thread Frediano Ziglio
From: Jonathon Jongsma 

---
 server/main-channel.c | 2 +-
 server/reds.c | 2 +-
 server/reds.h | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/server/main-channel.c b/server/main-channel.c
index 31e65f0..3315d6c 100644
--- a/server/main-channel.c
+++ b/server/main-channel.c
@@ -1020,7 +1020,7 @@ static void 
main_channel_release_msg_rcv_buf(RedChannelClient *rcc,
uint8_t *msg)
 {
 if (type == SPICE_MSGC_MAIN_AGENT_DATA) {
-reds_release_agent_data_buffer(msg);
+reds_release_agent_data_buffer(reds, msg);
 }
 }
 
diff --git a/server/reds.c b/server/reds.c
index d480ce3..b183ee1 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -1022,7 +1022,7 @@ uint8_t *reds_get_agent_data_buffer(RedsState *reds, 
MainChannelClient *mcc, siz
 return dev_state->recv_from_client_buf->buf + sizeof(VDIChunkHeader);
 }
 
-void reds_release_agent_data_buffer(uint8_t *buf)
+void reds_release_agent_data_buffer(RedsState *reds, uint8_t *buf)
 {
 VDIPortState *dev_state = &reds->agent_state;
 
diff --git a/server/reds.h b/server/reds.h
index 2659493..0294333 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -96,8 +96,8 @@ void reds_update_stat_value(uint32_t value);
 
 void reds_on_main_agent_start(RedsState *reds, MainChannelClient *mcc, 
uint32_t num_tokens);
 void reds_on_main_agent_tokens(MainChannelClient *mcc, uint32_t num_tokens);
-void reds_release_agent_data_buffer(uint8_t *buf);
 uint8_t *reds_get_agent_data_buffer(RedsState *reds, MainChannelClient *mcc, 
size_t size);
+void reds_release_agent_data_buffer(RedsState *reds, uint8_t *buf);
 void reds_on_main_agent_data(MainChannelClient *mcc, void *message, size_t 
size);
 void reds_on_main_migrate_connected(int seamless); //should be called when all 
the clients
// are connected to the 
target
-- 
2.4.3

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH 10/15] Change reds_get_agent_data_buffer() to take RedsState arg

2016-01-18 Thread Frediano Ziglio
From: Jonathon Jongsma 

---
 server/main-channel.c | 2 +-
 server/reds.c | 2 +-
 server/reds.h | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/server/main-channel.c b/server/main-channel.c
index 0ab3dec..31e65f0 100644
--- a/server/main-channel.c
+++ b/server/main-channel.c
@@ -1008,7 +1008,7 @@ static uint8_t 
*main_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
 MainChannelClient *mcc = SPICE_CONTAINEROF(rcc, MainChannelClient, base);
 
 if (type == SPICE_MSGC_MAIN_AGENT_DATA) {
-return reds_get_agent_data_buffer(mcc, size);
+return reds_get_agent_data_buffer(reds, mcc, size);
 } else {
 return main_chan->recv_buf;
 }
diff --git a/server/reds.c b/server/reds.c
index db1f718..d480ce3 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -997,7 +997,7 @@ void reds_on_main_agent_tokens(MainChannelClient *mcc, 
uint32_t num_tokens)
 num_tokens);
 }
 
-uint8_t *reds_get_agent_data_buffer(MainChannelClient *mcc, size_t size)
+uint8_t *reds_get_agent_data_buffer(RedsState *reds, MainChannelClient *mcc, 
size_t size)
 {
 VDIPortState *dev_state = &reds->agent_state;
 RedClient *client;
diff --git a/server/reds.h b/server/reds.h
index 4033724..2659493 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -96,8 +96,8 @@ void reds_update_stat_value(uint32_t value);
 
 void reds_on_main_agent_start(RedsState *reds, MainChannelClient *mcc, 
uint32_t num_tokens);
 void reds_on_main_agent_tokens(MainChannelClient *mcc, uint32_t num_tokens);
-uint8_t *reds_get_agent_data_buffer(MainChannelClient *mcc, size_t size);
 void reds_release_agent_data_buffer(uint8_t *buf);
+uint8_t *reds_get_agent_data_buffer(RedsState *reds, MainChannelClient *mcc, 
size_t size);
 void reds_on_main_agent_data(MainChannelClient *mcc, void *message, size_t 
size);
 void reds_on_main_migrate_connected(int seamless); //should be called when all 
the clients
// are connected to the 
target
-- 
2.4.3

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH 06/15] Change reds_num_of_channels() to take RedsState arg

2016-01-18 Thread Frediano Ziglio
From: Jonathon Jongsma 

---
 server/main-channel.c | 2 +-
 server/reds.c | 2 +-
 server/reds.h | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/server/main-channel.c b/server/main-channel.c
index 2a9f0ce..1b774f3 100644
--- a/server/main-channel.c
+++ b/server/main-channel.c
@@ -348,7 +348,7 @@ static void main_channel_marshall_channels(RedChannelClient 
*rcc,
 
 red_channel_client_init_send_data(rcc, SPICE_MSG_MAIN_CHANNELS_LIST, item);
 channels_info = (SpiceMsgChannels *)spice_malloc(sizeof(SpiceMsgChannels)
-+ reds_num_of_channels() * sizeof(SpiceChannelId));
++ reds_num_of_channels(reds) * 
sizeof(SpiceChannelId));
 reds_fill_channels(channels_info);
 spice_marshall_msg_main_channels_list(m, channels_info);
 free(channels_info);
diff --git a/server/reds.c b/server/reds.c
index 11f0e1a..9b28a7c 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -891,7 +891,7 @@ void reds_handle_agent_mouse_event(RedsState *reds, const 
VDAgentMouseState *mou
 spice_char_device_write_buffer_add(reds->agent_state.base, char_dev_buf);
 }
 
-int reds_num_of_channels(void)
+int reds_num_of_channels(RedsState *reds)
 {
 return reds ? reds->num_of_channels : 0;
 }
diff --git a/server/reds.h b/server/reds.h
index 76262ce..65e8f69 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -87,7 +87,7 @@ void reds_client_disconnect(RedsState *reds, RedClient 
*client);
 typedef struct MainMigrateData MainMigrateData;
 void reds_marshall_migrate_data(SpiceMarshaller *m);
 void reds_fill_channels(SpiceMsgChannels *channels_info);
-int reds_num_of_channels(void);
+int reds_num_of_channels(RedsState *reds);
 int reds_num_of_clients(void);
 #ifdef RED_STATISTICS
 void reds_update_stat_value(uint32_t value);
-- 
2.4.3

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH 05/15] Change reds_handle_agent_mouse_event() to take RedsState arg

2016-01-18 Thread Frediano Ziglio
From: Jonathon Jongsma 

---
 server/inputs-channel.c | 6 +++---
 server/reds.c   | 5 +++--
 server/reds.h   | 2 +-
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/server/inputs-channel.c b/server/inputs-channel.c
index bb5b203..d13f9d7 100644
--- a/server/inputs-channel.c
+++ b/server/inputs-channel.c
@@ -396,7 +396,7 @@ static int inputs_channel_handle_parsed(RedChannelClient 
*rcc, uint32_t size, ui
 mouse_state->y = pos->y;
 mouse_state->buttons = 
RED_MOUSE_BUTTON_STATE_TO_AGENT(pos->buttons_state);
 mouse_state->display_id = pos->display_id;
-reds_handle_agent_mouse_event(mouse_state);
+reds_handle_agent_mouse_event(reds, mouse_state);
 break;
 }
 case SPICE_MSGC_INPUTS_MOUSE_PRESS: {
@@ -413,7 +413,7 @@ static int inputs_channel_handle_parsed(RedChannelClient 
*rcc, uint32_t size, ui
 
RED_MOUSE_BUTTON_STATE_TO_AGENT(mouse_press->buttons_state) |
 (dz == -1 ? VD_AGENT_UBUTTON_MASK : 0) |
 (dz == 1 ? VD_AGENT_DBUTTON_MASK : 0);
-reds_handle_agent_mouse_event(&inputs_channel->mouse_state);
+reds_handle_agent_mouse_event(reds, 
&inputs_channel->mouse_state);
 } else if (tablet) {
 SpiceTabletInterface *sif;
 sif = SPICE_CONTAINEROF(tablet->base.sif, 
SpiceTabletInterface, base);
@@ -433,7 +433,7 @@ static int inputs_channel_handle_parsed(RedChannelClient 
*rcc, uint32_t size, ui
 if (reds_get_agent_mouse() && reds_has_vdagent()) {
 inputs_channel->mouse_state.buttons =
 
RED_MOUSE_BUTTON_STATE_TO_AGENT(mouse_release->buttons_state);
-reds_handle_agent_mouse_event(&inputs_channel->mouse_state);
+reds_handle_agent_mouse_event(reds, 
&inputs_channel->mouse_state);
 } else if (tablet) {
 SpiceTabletInterface *sif;
 sif = SPICE_CONTAINEROF(tablet->base.sif, 
SpiceTabletInterface, base);
diff --git a/server/reds.c b/server/reds.c
index 4e0caba..11f0e1a 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -834,10 +834,11 @@ static void vdi_port_send_tokens_to_client(RedClient 
*client, uint32_t tokens, v
 
 static void vdi_port_on_free_self_token(void *opaque)
 {
+RedsState *reds = opaque;
 
 if (inputs_inited() && reds->pending_mouse_event) {
 spice_debug("pending mouse event");
-reds_handle_agent_mouse_event(inputs_get_mouse_state());
+reds_handle_agent_mouse_event(reds, inputs_get_mouse_state());
 }
 }
 
@@ -854,7 +855,7 @@ int reds_has_vdagent(void)
 return !!vdagent;
 }
 
-void reds_handle_agent_mouse_event(const VDAgentMouseState *mouse_state)
+void reds_handle_agent_mouse_event(RedsState *reds, const VDAgentMouseState 
*mouse_state)
 {
 SpiceCharDeviceWriteBuffer *char_dev_buf;
 VDInternalBuf *internal_buf;
diff --git a/server/reds.h b/server/reds.h
index e38a99a..76262ce 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -60,7 +60,7 @@ void reds_unregister_channel(RedsState *reds, RedChannel 
*channel);
 int reds_get_mouse_mode(RedsState *reds); // used by inputs_channel
 int reds_get_agent_mouse(void); // used by inputs_channel
 int reds_has_vdagent(void); // used by inputs channel
-void reds_handle_agent_mouse_event(const VDAgentMouseState *mouse_state); // 
used by inputs_channel
+void reds_handle_agent_mouse_event(RedsState *reds, const VDAgentMouseState 
*mouse_state); // used by inputs_channel
 
 enum {
 RED_RENDERER_INVALID,
-- 
2.4.3

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH 02/15] Change vdi_port_read_buf_process() to take RedsState arg

2016-01-18 Thread Frediano Ziglio
From: Jonathon Jongsma 

---
 server/reds.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/server/reds.c b/server/reds.c
index 25e9f90..b347d1d 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -662,7 +662,7 @@ static void vdi_port_read_buf_release(uint8_t *data, void 
*opaque)
 }
 
 /* returns TRUE if the buffer can be forwarded */
-static int vdi_port_read_buf_process(int port, VDIReadBuf *buf)
+static int vdi_port_read_buf_process(RedsState *reds, int port, VDIReadBuf 
*buf)
 {
 VDIPortState *state = &reds->agent_state;
 int res;
@@ -787,7 +787,7 @@ static SpiceCharDeviceMsgToClient 
*vdi_port_read_one_msg_from_device(SpiceCharDe
 } else {
 state->read_state = VDI_PORT_READ_STATE_GET_BUFF;
 }
-if (vdi_port_read_buf_process(state->vdi_chunk_header.port, 
dispatch_buf)) {
+if (vdi_port_read_buf_process(reds, state->vdi_chunk_header.port, 
dispatch_buf)) {
 return dispatch_buf;
 } else {
 vdi_port_read_buf_unref(dispatch_buf);
@@ -1156,7 +1156,7 @@ void reds_on_main_channel_migrate(MainChannelClient *mcc)
 !agent_state->read_filter.msg_data_to_read);
 
 read_buf->len = read_data_len;
-if (vdi_port_read_buf_process(agent_state->vdi_chunk_header.port, 
read_buf)) {
+if (vdi_port_read_buf_process(reds, 
agent_state->vdi_chunk_header.port, read_buf)) {
 main_channel_client_push_agent_data(mcc,
 read_buf->data,
 read_buf->len,
-- 
2.4.3

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH 00/15] Backported some patches from refactory branches (18th Jan)

2016-01-18 Thread Frediano Ziglio
Many new patches try to incrementally remove global reds variable so
they add RedsState* as parameter.

All previous patches were merged.

Jonathon Jongsma (15):
  Pass 'reds' as opaque data in vdi port char device
  Change vdi_port_read_buf_process() to take RedsState arg
  Change vdi_port_read_buf_get() to take RedsState arg
  Change vdi_port_read_buf_unref() to take RedsState arg
  Change reds_handle_agent_mouse_event() to take RedsState arg
  Change reds_num_of_channels() to take RedsState arg
  Change reds_num_of_clients() to take RedsState arg
  Change reds_fill_channels() to take a RedsState arg
  Change reds_on_main_agent_start() to take RedsState arg
  Change reds_get_agent_data_buffer() to take RedsState arg
  Change reds_release_agent_data_buffer() to take RedsState arg
  Change reds_client_monitors_config_cleanup() to take RedsState arg
  Change red_on_main_agent_data() to take RedsState arg
  reds_num_of_channels() -> reds_get_n_channels()
  reds_num_of_clients() -> reds_get_n_clients()

 server/inputs-channel.c |  6 ++---
 server/main-channel.c   | 12 -
 server/reds.c   | 65 ++---
 server/reds.h   | 15 ++--
 4 files changed, 51 insertions(+), 47 deletions(-)

-- 
2.4.3

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH] tests: remove leaks in test-qxl-parsing

2016-01-18 Thread Frediano Ziglio
This make happy address sanitizer during make check.
Otherwise memory leak detector can keep in and make tests fails.

Signed-off-by: Frediano Ziglio 
---
 server/tests/test-qxl-parsing.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/server/tests/test-qxl-parsing.c b/server/tests/test-qxl-parsing.c
index d44289f..a3b2e6c 100644
--- a/server/tests/test-qxl-parsing.c
+++ b/server/tests/test-qxl-parsing.c
@@ -65,6 +65,8 @@ int main(int argc, char **argv)
 QXLCursor *cursor;
 QXLDataChunk *chunks[2];
 
+void *surface_mem;
+
 memset(&qxl, 0, sizeof(qxl));
 
 qxl.surface_id = 123;
@@ -75,7 +77,8 @@ int main(int argc, char **argv)
 qxl.u.surface_create.width = 128;
 qxl.u.surface_create.stride = 512;
 qxl.u.surface_create.height = 128;
-qxl.u.surface_create.data = to_physical(malloc(0x1));
+surface_mem = malloc(0x1);
+qxl.u.surface_create.data = to_physical(surface_mem);
 if (red_get_surface_cmd(&mem_info, 0, &cmd, to_physical(&qxl)))
 failure();
 
@@ -117,6 +120,7 @@ int main(int argc, char **argv)
 
 if (red_get_cursor_cmd(&mem_info, 0, &red_cursor_cmd, 
to_physical(&cursor_cmd)))
 failure();
+free(red_cursor_cmd.u.set.shape.data);
 free(cursor);
 
 /* a circular list of empty chunks should not be a problems */
@@ -173,5 +177,9 @@ int main(int argc, char **argv)
 free(cursor);
 free(chunks[0]);
 
+free(mem_info.mem_slots[0]);
+free(mem_info.mem_slots);
+free(surface_mem);
+
 return exit_code;
 }
-- 
2.4.3

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH 13/14] wocky-http-proxy: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Christophe Fergeau
On Mon, Jan 18, 2016 at 10:05:49AM +0100, Fabiano Fidêncio wrote:
> Instead of using GSimpleAsyncResult, use the new GTask API, which is
> much more straightforward.

Is there an upstream for wocky-http-proxy where you should send this
patch?

> ---
>  src/wocky-http-proxy.c | 47 ++-
>  1 file changed, 18 insertions(+), 29 deletions(-)
> 
> diff --git a/src/wocky-http-proxy.c b/src/wocky-http-proxy.c
> index d84cd72..f079e10 100644
> --- a/src/wocky-http-proxy.c
> +++ b/src/wocky-http-proxy.c
> @@ -254,14 +254,13 @@ error:
>  
>  typedef struct
>  {
> -  GSimpleAsyncResult *simple;
> +  GTask *task;
>GIOStream *io_stream;
>gchar *buffer;
>gssize length;
>gssize offset;
>GDataInputStream *data_in;
>gboolean has_cred;
> -  GCancellable *cancellable;
>  } ConnectAsyncData;
>  
>  static void request_write_cb (GObject *source,
> @@ -282,26 +281,22 @@ free_connect_data (ConnectAsyncData *data)
>if (data->data_in != NULL)
>  g_object_unref (data->data_in);
>  
> -  if (data->cancellable != NULL)
> -g_object_unref (data->cancellable);
> -
>g_free (data);
>  }
>  
>  static void
>  complete_async_from_error (ConnectAsyncData *data, GError *error)
>  {
> -  GSimpleAsyncResult *simple = data->simple;
> +  GTask *task = data->task;
>  
>if (error == NULL)
>  g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_PROXY_FAILED,
>  "HTTP proxy server closed connection unexpectedly.");
>  
> -  g_simple_async_result_set_from_error (data->simple, error);
> +  g_task_return_error(data->task, error);
>g_error_free (error);

This should be removed

> -  g_simple_async_result_set_op_res_gpointer (simple, NULL, NULL);
> -  g_simple_async_result_complete (simple);
> -  g_object_unref (simple);
> +  g_task_return_pointer(task, NULL, NULL);

I don't think you need this g_task_return_pointer(), you already
returned an error.

> +  g_object_unref (task);
>  }
>  
>  static void
> @@ -312,7 +307,7 @@ do_write (GAsyncReadyCallback callback, ConnectAsyncData 
> *data)
>g_output_stream_write_async (out,
>data->buffer + data->offset,
>data->length - data->offset,
> -  G_PRIORITY_DEFAULT, data->cancellable,
> +  G_PRIORITY_DEFAULT, g_task_get_cancellable(data->task),
>callback, data);
>  }
>  
> @@ -357,24 +352,22 @@ wocky_http_proxy_connect_async (GProxy *proxy,
>  GAsyncReadyCallback callback,
>  gpointer user_data)
>  {
> -  GSimpleAsyncResult *simple;
> +  GTask *task;
>ConnectAsyncData *data;
>  
> -  simple = g_simple_async_result_new (G_OBJECT (proxy),
> -  callback, user_data,
> -  wocky_http_proxy_connect_async);
> +  task = g_task_new (proxy,
> + cancellable,
> + callback,
> + user_data);
>  
>data = g_new0 (ConnectAsyncData, 1);
> -  if (cancellable != NULL)
> -data->cancellable = g_object_ref (cancellable);
> -  data->simple = simple;
> +  data->task = task;
>  
>data->buffer = create_request (proxy_address, &data->has_cred);
>data->length = strlen (data->buffer);
>data->offset = 0;
>  
> -  g_simple_async_result_set_op_res_gpointer (simple, data,
> - (GDestroyNotify) 
> free_connect_data);
> +  g_task_return_pointer (task, data, (GDestroyNotify) free_connect_data);

Ah, I don't think the initial code meant g_task_return_pointer() here
(there is no call to g_simple_async_result_complete_* in this function).
It's rather a slight abuse of GSimpleAsyncResult API in order to get
g_task_set_task_data functionality. Or maybe this is really the value
that it wants to return to the user, but not before it's time to do that
in reply_read_cb().

>  
>if (WOCKY_IS_HTTPS_PROXY (proxy))
>  {
> @@ -435,7 +428,7 @@ request_write_cb (GObject *source,
>g_data_input_stream_read_until_async (data->data_in,
>HTTP_END_MARKER,
>G_PRIORITY_DEFAULT,
> -  data->cancellable,
> +  g_task_get_cancellable(data->task),
>reply_read_cb, data);
>  
>  }
> @@ -468,8 +461,7 @@ reply_read_cb (GObject *source,
>return;
>  }
>  
> -  g_simple_async_result_complete (data->simple);

You need a g_task_return_ here in my opinion.


Christophe


signature.asc
Description: PGP signature
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [spice-gtk PATCH v2] gstaudio: set output parameter to NULL on error

2016-01-18 Thread Victor Toso
hmmm, subjectprefix with v2. sorry. This is v1.

On Mon, Jan 18, 2016 at 03:09:48PM +0100, Victor Toso wrote:
> This is not really triggered in the current code but this is usually
> expected in case of errors; Also, the same function on record side
> already does this.
> ---
>  src/spice-gstaudio.c | 4 
>  1 file changed, 4 insertions(+)
> 
> diff --git a/src/spice-gstaudio.c b/src/spice-gstaudio.c
> index 096fea4..2759c2b 100644
> --- a/src/spice-gstaudio.c
> +++ b/src/spice-gstaudio.c
> @@ -600,6 +600,10 @@ static gboolean 
> spice_gstaudio_get_playback_volume_info_finish(SpiceAudio *audio
>  G_OBJECT(audio), spice_gstaudio_get_playback_volume_info_async), 
> FALSE);
>  
>  if (g_simple_async_result_propagate_error(simple, error)) {
> +/* set out args that should have new alloc'ed memory to NULL */
> +if (volume != NULL) {
> +*volume = NULL;
> +}
>  return FALSE;
>  }
>  
> -- 
> 2.5.0
> 
> ___
> Spice-devel mailing list
> Spice-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [spice-gtk PATCH v2] gstaudio: set output parameter to NULL on error

2016-01-18 Thread Victor Toso
This is not really triggered in the current code but this is usually
expected in case of errors; Also, the same function on record side
already does this.
---
 src/spice-gstaudio.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/src/spice-gstaudio.c b/src/spice-gstaudio.c
index 096fea4..2759c2b 100644
--- a/src/spice-gstaudio.c
+++ b/src/spice-gstaudio.c
@@ -600,6 +600,10 @@ static gboolean 
spice_gstaudio_get_playback_volume_info_finish(SpiceAudio *audio
 G_OBJECT(audio), spice_gstaudio_get_playback_volume_info_async), 
FALSE);
 
 if (g_simple_async_result_propagate_error(simple, error)) {
+/* set out args that should have new alloc'ed memory to NULL */
+if (volume != NULL) {
+*volume = NULL;
+}
 return FALSE;
 }
 
-- 
2.5.0

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH 12/14] win-usb-driver-install: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Christophe Fergeau
On Mon, Jan 18, 2016 at 10:05:48AM +0100, Fabiano Fidêncio wrote:
> Instead of using GSimpleAsyncResult, use the new GTask API, which is
> much more straightforward.
> ---
>  src/win-usb-driver-install.c | 86 
> +---
>  1 file changed, 41 insertions(+), 45 deletions(-)
> 
> diff --git a/src/win-usb-driver-install.c b/src/win-usb-driver-install.c
> index 54e9b14..a7c4864 100644
> --- a/src/win-usb-driver-install.c
> +++ b/src/win-usb-driver-install.c
> @@ -44,8 +44,7 @@
>  
>  struct _SpiceWinUsbDriverPrivate {
>  USBClerkReply reply;
> -GSimpleAsyncResult*result;
> -GCancellable  *cancellable;
> +GTask *task;
>  HANDLEhandle;
>  SpiceUsbDevice*device;
>  };
> @@ -144,16 +143,16 @@ void win_usb_driver_handle_reply_cb(GObject *gobject,
>  
>  if (err) {
>  g_warning("failed to read reply from usbclerk (%s)", err->message);
> -g_simple_async_result_take_error(priv->result, err);
> +g_task_return_error(priv->task, err);
>  goto failed_reply;
>  }
>  
>  if (bytes == 0) {
>  g_warning("unexpected EOF from usbclerk");
> -g_simple_async_result_set_error(priv->result,
> -SPICE_WIN_USB_DRIVER_ERROR,
> -SPICE_WIN_USB_DRIVER_ERROR_FAILED,
> -"unexpected EOF from usbclerk");
> +g_task_return_new_error(priv->task,
> +SPICE_WIN_USB_DRIVER_ERROR,
> +SPICE_WIN_USB_DRIVER_ERROR_FAILED,
> +"unexpected EOF from usbclerk");
>  goto failed_reply;
>  }
>  
> @@ -167,52 +166,53 @@ void win_usb_driver_handle_reply_cb(GObject *gobject,
>  if (priv->reply.hdr.magic != USB_CLERK_MAGIC) {
>  g_warning("usbclerk magic mismatch: mine=0x%04x  server=0x%04x",
>USB_CLERK_MAGIC, priv->reply.hdr.magic);
> -g_simple_async_result_set_error(priv->result,
> -SPICE_WIN_USB_DRIVER_ERROR,
> -SPICE_WIN_USB_DRIVER_ERROR_MESSAGE,
> -"usbclerk magic mismatch");
> +g_task_return_new_error(priv->task,
> +SPICE_WIN_USB_DRIVER_ERROR,
> +SPICE_WIN_USB_DRIVER_ERROR_MESSAGE,
> +"usbclerk magic mismatch");
>  goto failed_reply;
>  }
>  
>  if (priv->reply.hdr.version != USB_CLERK_VERSION) {
>  g_warning("usbclerk version mismatch: mine=0x%04x  server=0x%04x",
>USB_CLERK_VERSION, priv->reply.hdr.version);
> -g_simple_async_result_set_error(priv->result,
> -SPICE_WIN_USB_DRIVER_ERROR,
> -SPICE_WIN_USB_DRIVER_ERROR_MESSAGE,
> -"usbclerk version mismatch");
> +g_task_return_new_error(priv->task,
> +SPICE_WIN_USB_DRIVER_ERROR,
> +SPICE_WIN_USB_DRIVER_ERROR_MESSAGE,
> +"usbclerk version mismatch");
>  }
>  
>  if (priv->reply.hdr.type != USB_CLERK_REPLY) {
>  g_warning("usbclerk message with unexpected type %d",
>priv->reply.hdr.type);
> -g_simple_async_result_set_error(priv->result,
> -SPICE_WIN_USB_DRIVER_ERROR,
> -SPICE_WIN_USB_DRIVER_ERROR_MESSAGE,
> -"usbclerk message with unexpected 
> type");
> +g_task_return_new_error(priv->task,
> +SPICE_WIN_USB_DRIVER_ERROR,
> +SPICE_WIN_USB_DRIVER_ERROR_MESSAGE,
> +"usbclerk message with unexpected type");
>  goto failed_reply;
>  }
>  
>  if (priv->reply.hdr.size != bytes) {
>  g_warning("usbclerk message size mismatch: read %"G_GSSIZE_FORMAT" 
> bytes  hdr.size=%d",
>bytes, priv->reply.hdr.size);
> -g_simple_async_result_set_error(priv->result,
> -SPICE_WIN_USB_DRIVER_ERROR,
> -SPICE_WIN_USB_DRIVER_ERROR_MESSAGE,
> -"usbclerk message with unexpected 
> size");
> +g_task_return_new_error(priv->task,
> +SPICE_WIN_USB_DRIVER_ERROR,
> +SPICE_WIN_USB_DRIVER_ERROR_MESSAGE,
> +"usbclerk message with unexpected size");
>  goto failed_reply;
>  }
>  
>  if (priv->reply.status == 0) {
> -g_simple_async_result_set_error(priv->resul

Re: [Spice-devel] [PATCH 07/14] spice-gstaudio: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Victor Toso
Hi,

On Mon, Jan 18, 2016 at 02:51:05PM +0100, Christophe Fergeau wrote:
> On Mon, Jan 18, 2016 at 10:05:43AM +0100, Fabiano Fidêncio wrote:
> > Instead of using GSimpleAsyncResult, use the new GTask API, which is
> > much more straightforward.
> > ---
> >  src/spice-gstaudio.c | 48 ++--
> >  1 file changed, 10 insertions(+), 38 deletions(-)
> > 
> > diff --git a/src/spice-gstaudio.c b/src/spice-gstaudio.c
> > index 096fea4..65fc173 100644
> > --- a/src/spice-gstaudio.c
> > +++ b/src/spice-gstaudio.c
> > @@ -570,16 +570,9 @@ static void 
> > spice_gstaudio_get_playback_volume_info_async(SpiceAudio *audio,
> >
> > GAsyncReadyCallback callback,
> >gpointer 
> > user_data)
> >  {
> > -GSimpleAsyncResult *simple;
> > +GTask *task = g_task_new(audio, cancellable, callback, user_data);
> >  
> > -simple = g_simple_async_result_new(G_OBJECT(audio),
> > -   callback,
> > -   user_data,
> > -   
> > spice_gstaudio_get_playback_volume_info_async);
> > -g_simple_async_result_set_check_cancellable (simple, cancellable);
> > -
> > -g_simple_async_result_set_op_res_gboolean(simple, TRUE);
> > -g_simple_async_result_complete_in_idle(simple);
> > +g_task_return_boolean(task, TRUE);
> >  }
> >  
> >  static gboolean spice_gstaudio_get_playback_volume_info_finish(SpiceAudio 
> > *audio,
> > @@ -594,14 +587,9 @@ static gboolean 
> > spice_gstaudio_get_playback_volume_info_finish(SpiceAudio *audio
> >  gboolean lmute;
> >  gdouble vol;
> >  gboolean fake_channel = FALSE;
> > -GSimpleAsyncResult *simple = (GSimpleAsyncResult *) res;
> > -
> > -g_return_val_if_fail(g_simple_async_result_is_valid(res,
> > -G_OBJECT(audio), spice_gstaudio_get_playback_volume_info_async), 
> > FALSE);
> > +GTask *task = G_TASK(res);
> >  
> > -if (g_simple_async_result_propagate_error(simple, error)) {
> > -return FALSE;
> > -}
> > +g_return_val_if_fail(g_task_is_valid(task, audio), FALSE);
> 
> 
> I would keep a
> if (g_task_had_error(task)) {
> return g_task_propage_error(task, error);
> }
> 
> to avoid trying to do a lot of things when there had been an error.
> 
> >  if (p->playback.sink == NULL || p->playback.channels == 0) {
> >  SPICE_DEBUG("PlaybackChannel not created yet, force start");
> > @@ -647,7 +635,7 @@ static gboolean 
> > spice_gstaudio_get_playback_volume_info_finish(SpiceAudio *audio
> >  }
> >  }
> >  
> > -return g_simple_async_result_get_op_res_gboolean(simple);
> > +return g_task_propagate_boolean(task, error);
> >  }
> >  
> >  static void spice_gstaudio_get_record_volume_info_async(SpiceAudio *audio,
> > @@ -656,16 +644,9 @@ static void 
> > spice_gstaudio_get_record_volume_info_async(SpiceAudio *audio,
> >  
> > GAsyncReadyCallback callback,
> >  gpointer user_data)
> >  {
> > -GSimpleAsyncResult *simple;
> > -
> > -simple = g_simple_async_result_new(G_OBJECT(audio),
> > -   callback,
> > -   user_data,
> > -   
> > spice_gstaudio_get_record_volume_info_async);
> > -g_simple_async_result_set_check_cancellable (simple, cancellable);
> > +GTask *task = g_task_new(audio, cancellable, callback, user_data);
> >  
> > -g_simple_async_result_set_op_res_gboolean(simple, TRUE);
> > -g_simple_async_result_complete_in_idle(simple);
> > +g_task_return_boolean(task, TRUE);
> >  }
> >  
> >  static gboolean spice_gstaudio_get_record_volume_info_finish(SpiceAudio 
> > *audio,
> > @@ -680,18 +661,9 @@ static gboolean 
> > spice_gstaudio_get_record_volume_info_finish(SpiceAudio *audio,
> >  gboolean lmute;
> >  gdouble vol;
> >  gboolean fake_channel = FALSE;
> > -GSimpleAsyncResult *simple = (GSimpleAsyncResult *) res;
> > +GTask *task = G_TASK(res);
> >
> > -g_return_val_if_fail(g_simple_async_result_is_valid(res,
> > -G_OBJECT(audio), spice_gstaudio_get_record_volume_info_async), 
> > FALSE);
> > -
> > -if (g_simple_async_result_propagate_error(simple, error)) {
> > -/* set out args that should have new alloc'ed memory to NULL */
> > -if (volume != NULL) {
> > -*volume = NULL;
> > -}
>
> I would keep this too, I'm a bit surprised it's only done in the record
> case and not in the playback case.

Indeed, seems that it was forgotten in the playback case.
Both calls from channel-main don't mess with the output arg if the
function return FALSE but it is recommended to set to NULL.

>
> Christophe

> 
> > -return FALSE;
> > -}
> > + 

Re: [Spice-devel] [PATCH 10/14] usb-device-manager: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Christophe Fergeau
On Mon, Jan 18, 2016 at 10:05:46AM +0100, Fabiano Fidêncio wrote:
> Instead of using GSimpleAsyncResult, use the new GTask API, which is
> much more straightforward.
> ---
>  src/usb-device-manager.c | 61 
> 
>  1 file changed, 30 insertions(+), 31 deletions(-)
> 
> diff --git a/src/usb-device-manager.c b/src/usb-device-manager.c
> index c62f56e..1840177 100644
> --- a/src/usb-device-manager.c
> +++ b/src/usb-device-manager.c
> @@ -1055,15 +1055,16 @@ static void 
> spice_usb_device_manager_channel_connect_cb(
>  GObject *gobject, GAsyncResult *channel_res, gpointer user_data)
>  {
>  SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(gobject);
> -GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT(user_data);
> +GTask *task = G_TASK(user_data);
>  GError *err = NULL;
>  
>  spice_usbredir_channel_connect_device_finish(channel, channel_res, &err);
> -if (err) {
> -g_simple_async_result_take_error(result, err);
> -}
> -g_simple_async_result_complete(result);
> -g_object_unref(result);
> +if (err)
> +g_task_return_error(task, err);
> +else
> +g_task_return_boolean(task, TRUE);
> +
> +g_object_unref(task);
>  }
>  
>  #ifdef G_OS_WIN32
> @@ -1229,7 +1230,7 @@ static void 
> spice_usb_device_manager_check_redir_on_connect(
>  SpiceUsbDeviceManager *self, SpiceChannel *channel)
>  {
>  SpiceUsbDeviceManagerPrivate *priv = self->priv;
> -GSimpleAsyncResult *result;
> +GTask *task;
>  SpiceUsbDevice *device;
>  libusb_device *libdev;
>  guint i;
> @@ -1254,15 +1255,19 @@ static void 
> spice_usb_device_manager_check_redir_on_connect(
>  libdev, 0) == 0) {
>  /* Note: re-uses spice_usb_device_manager_connect_device_async's
> completion handling code! */
> -result = g_simple_async_result_new(G_OBJECT(self),
> -   spice_usb_device_manager_auto_connect_cb,
> -   spice_usb_device_ref(device),
> -   
> spice_usb_device_manager_connect_device_async);
> +task = g_task_new(self,
> +  NULL,
> +  spice_usb_device_manager_auto_connect_cb,
> +  spice_usb_device_ref(device));
> +
> +g_task_set_source_tag(task,
> +  spice_usb_device_manager_connect_device_async);
> +

I don't think this is used.

Acked-by: Christophe Fergeau 

Christophe


signature.asc
Description: PGP signature
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH 08/14] spice-pulse: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Christophe Fergeau
On Mon, Jan 18, 2016 at 10:05:44AM +0100, Fabiano Fidêncio wrote:
> Instead of using GSimpleAsyncResult, use the new GTask API, which is
> much more straightforward.
> ---
>  src/spice-pulse.c | 96 
> +++
>  1 file changed, 33 insertions(+), 63 deletions(-)
> 
> diff --git a/src/spice-pulse.c b/src/spice-pulse.c
> index 22db893..60a037c 100644
> --- a/src/spice-pulse.c
> +++ b/src/spice-pulse.c
> @@ -34,13 +34,12 @@
>  struct async_task {
>  SpicePulse *pulse;
>  SpiceMainChannel   *main_channel;
> -GSimpleAsyncResult *res;
> +GTask  *task;
>  GAsyncReadyCallbackcallback;
>  gpointer   user_data;
>  gboolean   is_playback;
>  pa_operation   *pa_op;
>  gulong cancel_id;
> -GCancellable   *cancellable;
>  };
>  
>  struct stream {
> @@ -941,8 +940,8 @@ static gboolean free_async_task(gpointer user_data)
>  g_object_unref(task->pulse);
>  }
>  
> -if (task->res)
> -g_object_unref(task->res);
> +if (task->task)
> +g_object_unref(task->task);
>  
>  if (task->main_channel)
>  g_object_unref(task->main_channel);
> @@ -950,10 +949,9 @@ static gboolean free_async_task(gpointer user_data)
>  if (task->pa_op != NULL)
>  pa_operation_unref(task->pa_op);
>  
> -if (task->cancel_id != 0) {
> -g_cancellable_disconnect(task->cancellable, task->cancel_id);
> -g_clear_object(&task->cancellable);
> -}
> +if (task->cancel_id != 0)
> +g_cancellable_disconnect(g_task_get_cancellable(task->task),
> + task->cancel_id);

You need to move the g_object_unref(task->task) after this.

>  
>  g_free(task);
>  return G_SOURCE_REMOVE;
> @@ -981,14 +979,6 @@ static void cancel_task(GCancellable *cancellable, 
> gpointer user_data)
>  task->pulse->priv->pending_restore_task = NULL;
>  }
>  
> -#if !GLIB_CHECK_VERSION(2,32,0)
> -/* g_simple_async_result_set_check_cancellable is not present. Set an 
> error
> - * in the GSimpleAsyncResult in case of _finish functions is called */
> -g_simple_async_result_set_error(task->res,
> -SPICE_CLIENT_ERROR,
> -SPICE_CLIENT_ERROR_FAILED,
> -"Operation was cancelled");
> -#endif
>  /* FIXME: https://bugzilla.gnome.org/show_bug.cgi?id=705395
>   * Free the memory in idle */
>  g_idle_add(free_async_task, task);
> @@ -1001,27 +991,23 @@ static void complete_task(SpicePulse *pulse, struct 
> async_task *task, const gcha
>  
>  /* If we do have any err_msg, we failed */
>  if (err_msg != NULL) {
> -g_simple_async_result_set_op_res_gboolean(task->res, FALSE);
> -g_simple_async_result_set_error(task->res,
> -SPICE_CLIENT_ERROR,
> -SPICE_CLIENT_ERROR_FAILED,
> -"restore-info failed due %s",
> -err_msg);
> +g_task_return_boolean(task->task, FALSE);

This can be removed.

> +g_task_return_new_error(task->task,
> +SPICE_CLIENT_ERROR,
> +SPICE_CLIENT_ERROR_FAILED,
> +"restore-info failed due %s",
> +err_msg);
>  /* Volume-info does not change if stream is not found */
>  } else if ((task->is_playback == TRUE && p->playback.info_updated == 
> FALSE) ||
> (task->is_playback == FALSE && p->record.info_updated == 
> FALSE)) {
> -g_simple_async_result_set_op_res_gboolean(task->res, FALSE);
> -g_simple_async_result_set_error(task->res,
> -SPICE_CLIENT_ERROR,
> -SPICE_CLIENT_ERROR_FAILED,
> -"Stream not found by pulse");
> +g_task_return_boolean(task->task, FALSE);

This can be removed too.

> +g_task_return_new_error(task->task,
> +SPICE_CLIENT_ERROR,
> +SPICE_CLIENT_ERROR_FAILED,
> +"Stream not found by pulse");
>  } else {
> -g_simple_async_result_set_op_res_gboolean(task->res, TRUE);
> +g_task_return_boolean(task->task, TRUE);
>  }
> -
> -/* As all async calls to PulseAudio are done with glib mainloop, it is
> - * safe to complete the operation synchronously here. */
> -g_simple_async_result_complete(task->res);
>  }
>  
>  static void spice_pulse_complete_async_task(struct async_task *task, const 
> gchar *err_msg)
> @@ -1157,19 +1143,13 @@ static void pulse_stream_restore_info_async(gboolean 

Re: [Spice-devel] [PATCH 07/14] spice-gstaudio: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Christophe Fergeau
On Mon, Jan 18, 2016 at 10:05:43AM +0100, Fabiano Fidêncio wrote:
> Instead of using GSimpleAsyncResult, use the new GTask API, which is
> much more straightforward.
> ---
>  src/spice-gstaudio.c | 48 ++--
>  1 file changed, 10 insertions(+), 38 deletions(-)
> 
> diff --git a/src/spice-gstaudio.c b/src/spice-gstaudio.c
> index 096fea4..65fc173 100644
> --- a/src/spice-gstaudio.c
> +++ b/src/spice-gstaudio.c
> @@ -570,16 +570,9 @@ static void 
> spice_gstaudio_get_playback_volume_info_async(SpiceAudio *audio,
>
> GAsyncReadyCallback callback,
>gpointer user_data)
>  {
> -GSimpleAsyncResult *simple;
> +GTask *task = g_task_new(audio, cancellable, callback, user_data);
>  
> -simple = g_simple_async_result_new(G_OBJECT(audio),
> -   callback,
> -   user_data,
> -   
> spice_gstaudio_get_playback_volume_info_async);
> -g_simple_async_result_set_check_cancellable (simple, cancellable);
> -
> -g_simple_async_result_set_op_res_gboolean(simple, TRUE);
> -g_simple_async_result_complete_in_idle(simple);
> +g_task_return_boolean(task, TRUE);
>  }
>  
>  static gboolean spice_gstaudio_get_playback_volume_info_finish(SpiceAudio 
> *audio,
> @@ -594,14 +587,9 @@ static gboolean 
> spice_gstaudio_get_playback_volume_info_finish(SpiceAudio *audio
>  gboolean lmute;
>  gdouble vol;
>  gboolean fake_channel = FALSE;
> -GSimpleAsyncResult *simple = (GSimpleAsyncResult *) res;
> -
> -g_return_val_if_fail(g_simple_async_result_is_valid(res,
> -G_OBJECT(audio), spice_gstaudio_get_playback_volume_info_async), 
> FALSE);
> +GTask *task = G_TASK(res);
>  
> -if (g_simple_async_result_propagate_error(simple, error)) {
> -return FALSE;
> -}
> +g_return_val_if_fail(g_task_is_valid(task, audio), FALSE);


I would keep a
if (g_task_had_error(task)) {
return g_task_propage_error(task, error);
}

to avoid trying to do a lot of things when there had been an error.

>  if (p->playback.sink == NULL || p->playback.channels == 0) {
>  SPICE_DEBUG("PlaybackChannel not created yet, force start");
> @@ -647,7 +635,7 @@ static gboolean 
> spice_gstaudio_get_playback_volume_info_finish(SpiceAudio *audio
>  }
>  }
>  
> -return g_simple_async_result_get_op_res_gboolean(simple);
> +return g_task_propagate_boolean(task, error);
>  }
>  
>  static void spice_gstaudio_get_record_volume_info_async(SpiceAudio *audio,
> @@ -656,16 +644,9 @@ static void 
> spice_gstaudio_get_record_volume_info_async(SpiceAudio *audio,
>  GAsyncReadyCallback 
> callback,
>  gpointer user_data)
>  {
> -GSimpleAsyncResult *simple;
> -
> -simple = g_simple_async_result_new(G_OBJECT(audio),
> -   callback,
> -   user_data,
> -   
> spice_gstaudio_get_record_volume_info_async);
> -g_simple_async_result_set_check_cancellable (simple, cancellable);
> +GTask *task = g_task_new(audio, cancellable, callback, user_data);
>  
> -g_simple_async_result_set_op_res_gboolean(simple, TRUE);
> -g_simple_async_result_complete_in_idle(simple);
> +g_task_return_boolean(task, TRUE);
>  }
>  
>  static gboolean spice_gstaudio_get_record_volume_info_finish(SpiceAudio 
> *audio,
> @@ -680,18 +661,9 @@ static gboolean 
> spice_gstaudio_get_record_volume_info_finish(SpiceAudio *audio,
>  gboolean lmute;
>  gdouble vol;
>  gboolean fake_channel = FALSE;
> -GSimpleAsyncResult *simple = (GSimpleAsyncResult *) res;
> +GTask *task = G_TASK(res);
>  
> -g_return_val_if_fail(g_simple_async_result_is_valid(res,
> -G_OBJECT(audio), spice_gstaudio_get_record_volume_info_async), 
> FALSE);
> -
> -if (g_simple_async_result_propagate_error(simple, error)) {
> -/* set out args that should have new alloc'ed memory to NULL */
> -if (volume != NULL) {
> -*volume = NULL;
> -}

I would keep this too, I'm a bit surprised it's only done in the record
case and not in the playback case.

Christophe

> -return FALSE;
> -}
> +g_return_val_if_fail(g_task_is_valid(task, audio), FALSE);
>  
>  if (p->record.src == NULL || p->record.channels == 0) {
>  SPICE_DEBUG("RecordChannel not created yet, force start");
> @@ -737,5 +709,5 @@ static gboolean 
> spice_gstaudio_get_record_volume_info_finish(SpiceAudio *audio,
>  }
>  }
>  
> -return g_simple_async_result_get_op_res_gboolean(simple);
> +return g_task_propagate_boolean(task, error);
>  }
> -- 
> 2.5.0
> 
> __

Re: [Spice-devel] [PATCH 06/14] spice-channel: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Christophe Fergeau
Acked-by: Christophe Fergeau 

On Mon, Jan 18, 2016 at 10:05:42AM +0100, Fabiano Fidêncio wrote:
> Instead of using GSimpleAsyncResult, use the new GTask API, which is
> much more straightforward.
> ---
>  src/spice-channel.c | 32 +---
>  1 file changed, 13 insertions(+), 19 deletions(-)
> 
> diff --git a/src/spice-channel.c b/src/spice-channel.c
> index ff85715..dd32818 100644
> --- a/src/spice-channel.c
> +++ b/src/spice-channel.c
> @@ -2124,9 +2124,7 @@ static void spice_channel_flushed(SpiceChannel 
> *channel, gboolean success)
>  GSList *l;
>  
>  for (l = c->flushing; l != NULL; l = l->next) {
> -GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT(l->data);
> -g_simple_async_result_set_op_res_gboolean(result, success);
> -g_simple_async_result_complete_in_idle(result);
> +g_task_return_boolean(G_TASK(l->data), success);
>  }
>  
>  g_slist_free_full(c->flushing, g_object_unref);
> @@ -2970,7 +2968,7 @@ static void 
> spice_channel_send_migration_handshake(SpiceChannel *channel)
>  void spice_channel_flush_async(SpiceChannel *self, GCancellable *cancellable,
> GAsyncReadyCallback callback, gpointer 
> user_data)
>  {
> -GSimpleAsyncResult *simple;
> +GTask *task;
>  SpiceChannelPrivate *c;
>  gboolean was_empty;
>  
> @@ -2978,26 +2976,25 @@ void spice_channel_flush_async(SpiceChannel *self, 
> GCancellable *cancellable,
>  c = self->priv;
>  
>  if (c->state != SPICE_CHANNEL_STATE_READY) {
> -g_simple_async_report_error_in_idle(G_OBJECT(self), callback, 
> user_data,
> +g_task_report_new_error(self, callback, user_data,
> +spice_channel_flush_async,
>  SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
>  "The channel is not ready yet");
>  return;
>  }
>  
> -simple = g_simple_async_result_new(G_OBJECT(self), callback, user_data,
> -   spice_channel_flush_async);
> +task = g_task_new(self, cancellable, callback, user_data);
>  
>  STATIC_MUTEX_LOCK(c->xmit_queue_lock);
>  was_empty = g_queue_is_empty(&c->xmit_queue);
>  STATIC_MUTEX_UNLOCK(c->xmit_queue_lock);
>  if (was_empty) {
> -g_simple_async_result_set_op_res_gboolean(simple, TRUE);
> -g_simple_async_result_complete_in_idle(simple);
> -g_object_unref(simple);
> +g_task_return_boolean(task, TRUE);
> +g_object_unref(task);
>  return;
>  }
>  
> -c->flushing = g_slist_append(c->flushing, simple);
> +c->flushing = g_slist_append(c->flushing, task);
>  }
>  
>  /**
> @@ -3015,19 +3012,16 @@ void spice_channel_flush_async(SpiceChannel *self, 
> GCancellable *cancellable,
>  gboolean spice_channel_flush_finish(SpiceChannel *self, GAsyncResult *result,
>  GError **error)
>  {
> -GSimpleAsyncResult *simple;
> +GTask *task;
>  
>  g_return_val_if_fail(SPICE_IS_CHANNEL(self), FALSE);
>  g_return_val_if_fail(result != NULL, FALSE);
>  
> -simple = (GSimpleAsyncResult *)result;
> +task = G_TASK(result);
>  
> -if (g_simple_async_result_propagate_error(simple, error))
> -return -1;
> -
> -g_return_val_if_fail(g_simple_async_result_is_valid(result, 
> G_OBJECT(self),
> -
> spice_channel_flush_async), FALSE);
> +g_return_val_if_fail(g_task_is_valid(task, self),
> + FALSE);
>  
>  CHANNEL_DEBUG(self, "flushed finished!");
> -return g_simple_async_result_get_op_res_gboolean(simple);
> +return g_task_propagate_boolean(task, error);
>  }
> -- 
> 2.5.0
> 
> ___
> Spice-devel mailing list
> Spice-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel


signature.asc
Description: PGP signature
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] RFC: drop spice-gtk gtk+ 2.0 support

2016-01-18 Thread Marc-André Lureau
Hi

- Original Message -
> On Mon, Dec 21, 2015 at 4:54 PM, Marc-André Lureau
>  wrote:
> > Hi,
> >
> > With virt-viewer now dropping gtk 2.0, I don't know anyone left using
> > the spice-gtk with gtk+ 2.0. Thus I'd like to propose that the next
> > spice-gtk release be the last with 2.0 support.

fwiw, I also have a branch ready for a while. I'd like to see first local virgl 
support with gtk+2.0 released. Then switching to gtk3/gtkglarea to support 
wayland will be easier. 

cheers
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] RFC: drop spice-gtk gtk+ 2.0 support

2016-01-18 Thread Daniel P. Berrange
On Mon, Jan 18, 2016 at 02:07:49PM +0100, Fabiano Fidêncio wrote:
> On Mon, Dec 21, 2015 at 4:54 PM, Marc-André Lureau
>  wrote:
> > Hi,
> >
> > With virt-viewer now dropping gtk 2.0, I don't know anyone left using
> > the spice-gtk with gtk+ 2.0. Thus I'd like to propose that the next
> > spice-gtk release be the last with 2.0 support.
> >
> > Comments?
> 
> I completely agree with this.
> I already have been working on a patch dropping the support and I will
> submit it as soon we do the last release with gtk2 support.

virt-manager is already gtk3 only too, as is GNOME boxes, so I doubt
that there's any mainstream user of spice-gtk with gtk2, and if there
was they can stick on an older maint branch if really needed

Regards,
Daniel
-- 
|: http://berrange.com  -o-http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org  -o- http://virt-manager.org :|
|: http://autobuild.org   -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org   -o-   http://live.gnome.org/gtk-vnc :|
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] RFC: drop spice-gtk gtk+ 2.0 support

2016-01-18 Thread Fabiano Fidêncio
On Mon, Dec 21, 2015 at 4:54 PM, Marc-André Lureau
 wrote:
> Hi,
>
> With virt-viewer now dropping gtk 2.0, I don't know anyone left using
> the spice-gtk with gtk+ 2.0. Thus I'd like to propose that the next
> spice-gtk release be the last with 2.0 support.
>
> Comments?

I completely agree with this.
I already have been working on a patch dropping the support and I will
submit it as soon we do the last release with gtk2 support.

Best Regards,
--
Fabiano Fidêncio
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH] Change some functions to take RedsState arg

2016-01-18 Thread Pavel Grunt
On Mon, 2016-01-18 at 06:07 -0500, Frediano Ziglio wrote:
> > 
> > From: Jonathon Jongsma 
> > 
> > In preparation for getting rid of the global 'reds' variable, we
> > need to
> > pass the RedsState variable to all functions where it is needed.
> > For now
> > the callers just pass in the global reds variable.
> > 
> > Functions changed:
> > - reds_register_channel;
> > - reds_unregister_channel;
> > - reds_get_mouse_mode;
> > - reds_set_mouse_mode;
> > - reds_update_mouse_mode;
> > - reds_agent_remove;
> > - reds_find_channel;
> > - reds_mig_cleanup;
> > - reds_reset_vdp;
> > - reds_main_channel_connected;
> > - reds_client_disconnect;
> > - reds_disconnect;
> > - reds_mig_disconnect.
> > 
> > Acked-by: Frediano Ziglio 
> 
> Does it sound reasonable as comment and patch (just a squash of
> posted ones)?

Yes, it does. It is a simple change

Acked-by: Pavel Grunt 

Pavel

> Should I number the title?
> 
> Frediano
> 
> > ---
> >  server/inputs-channel.c  |  10 ++---
> >  server/main-dispatcher.c |   2 +-
> >  server/red-dispatcher.c  |   4 +-
> >  server/reds.c| 104
> >  +++
> >  server/reds.h|   8 ++--
> >  server/smartcard.c   |   2 +-
> >  server/sound.c   |   6 +--
> >  server/spicevmc.c|   4 +-
> >  8 files changed, 70 insertions(+), 70 deletions(-)
> > 
> > diff --git a/server/inputs-channel.c b/server/inputs-channel.c
> > index c21cab8..bb5b203 100644
> > --- a/server/inputs-channel.c
> > +++ b/server/inputs-channel.c
> > @@ -364,7 +364,7 @@ static int
> > inputs_channel_handle_parsed(RedChannelClient
> > *rcc, uint32_t size, ui
> >  red_channel_client_pipe_add_type(rcc,
> >  PIPE_ITEM_MOUSE_MOTION_ACK);
> >  icc->motion_count = 0;
> >  }
> > -if (mouse && reds_get_mouse_mode() ==
> > SPICE_MOUSE_MODE_SERVER) {
> > +if (mouse && reds_get_mouse_mode(reds) ==
> > SPICE_MOUSE_MODE_SERVER) {
> >  SpiceMouseInterface *sif;
> >  sif = SPICE_CONTAINEROF(mouse->base.sif,
> > SpiceMouseInterface,
> >  base);
> >  sif->motion(mouse,
> > @@ -381,7 +381,7 @@ static int
> > inputs_channel_handle_parsed(RedChannelClient
> > *rcc, uint32_t size, ui
> >  red_channel_client_pipe_add_type(rcc,
> >  PIPE_ITEM_MOUSE_MOTION_ACK);
> >  icc->motion_count = 0;
> >  }
> > -if (reds_get_mouse_mode() != SPICE_MOUSE_MODE_CLIENT) {
> > +if (reds_get_mouse_mode(reds) != SPICE_MOUSE_MODE_CLIENT)
> > {
> >  break;
> >  }
> >  spice_assert((reds_get_agent_mouse() &&
> > reds_has_vdagent()) ||
> >  tablet);
> > @@ -407,7 +407,7 @@ static int
> > inputs_channel_handle_parsed(RedChannelClient
> > *rcc, uint32_t size, ui
> >  } else if (mouse_press->button == SPICE_MOUSE_BUTTON_DOWN)
> > {
> >  dz = 1;
> >  }
> > -if (reds_get_mouse_mode() == SPICE_MOUSE_MODE_CLIENT) {
> > +if (reds_get_mouse_mode(reds) == SPICE_MOUSE_MODE_CLIENT)
> > {
> >  if (reds_get_agent_mouse() && reds_has_vdagent()) {
> >  inputs_channel->mouse_state.buttons =
> >  RED_MOUSE_BUTTON_STATE_TO_AGENT(mouse_press-
> > >buttons_state)
> >  |
> > @@ -429,7 +429,7 @@ static int
> > inputs_channel_handle_parsed(RedChannelClient
> > *rcc, uint32_t size, ui
> >  }
> >  case SPICE_MSGC_INPUTS_MOUSE_RELEASE: {
> >  SpiceMsgcMouseRelease *mouse_release = message;
> > -if (reds_get_mouse_mode() == SPICE_MOUSE_MODE_CLIENT) {
> > +if (reds_get_mouse_mode(reds) == SPICE_MOUSE_MODE_CLIENT)
> > {
> >  if (reds_get_agent_mouse() && reds_has_vdagent()) {
> >  inputs_channel->mouse_state.buttons =
> >  RED_MOUSE_BUTTON_STATE_TO_AGENT(mouse_release-
> > >buttons_state);
> > @@ -672,7 +672,7 @@ void inputs_init(void)
> >  red_channel_register_client_cbs(&g_inputs_channel->base,
> > &client_cbs);
> >  
> >  red_channel_set_cap(&g_inputs_channel->base,
> >  SPICE_INPUTS_CAP_KEY_SCANCODE);
> > -reds_register_channel(&g_inputs_channel->base);
> > +reds_register_channel(reds, &g_inputs_channel->base);
> >  
> >  if (!(key_modifiers_timer = core->timer_add(core,
> > key_modifiers_sender,
> >  NULL))) {
> >  spice_error("key modifiers timer create failed");
> > diff --git a/server/main-dispatcher.c b/server/main-dispatcher.c
> > index 2cb53ef..db87e05 100644
> > --- a/server/main-dispatcher.c
> > +++ b/server/main-dispatcher.c
> > @@ -136,7 +136,7 @@ static void
> > main_dispatcher_handle_client_disconnect(void
> > *opaque,
> >  MainDispatcherClientDisconnectMessage *msg = payload;
> >  
> >  spice_debug("client=%p", msg->client);
> > -reds_client_disconnect(msg->client);
> > +reds_client_disconnect(reds, msg->client);
> >  red_client_unref(msg->client);
> >  }

Re: [Spice-devel] [PATCH spice v2 3/4] dcc: make dcc_compress_image_*() private

2016-01-18 Thread Victor Toso
Hi,

Looks good
Reviewed-by: Victor Toso 

On Fri, Jan 15, 2016 at 05:11:34PM +0100, Pavel Grunt wrote:
> ---
>  server/dcc.c | 30 +++---
>  server/dcc.h | 15 ---
>  2 files changed, 15 insertions(+), 30 deletions(-)
> 
> diff --git a/server/dcc.c b/server/dcc.c
> index 097140a..9b65031 100644
> --- a/server/dcc.c
> +++ b/server/dcc.c
> @@ -646,9 +646,9 @@ static const LzImageType bitmap_fmt_to_lz_image_type[] = {
>  
>  #define MIN_GLZ_SIZE_FOR_ZLIB 100
>  
> -int dcc_compress_image_glz(DisplayChannelClient *dcc,
> -   SpiceImage *dest, SpiceBitmap *src, Drawable 
> *drawable,
> -   compress_send_data_t* o_comp_data)
> +static int dcc_compress_image_glz(DisplayChannelClient *dcc,
> +  SpiceImage *dest, SpiceBitmap *src, 
> Drawable *drawable,
> +  compress_send_data_t* o_comp_data)
>  {
>  DisplayChannel *display_channel = DCC_TO_DC(dcc);
>  stat_start_time_t start_time;
> @@ -723,9 +723,9 @@ glz:
>  return TRUE;
>  }
>  
> -int dcc_compress_image_lz(DisplayChannelClient *dcc,
> -  SpiceImage *dest, SpiceBitmap *src,
> -  compress_send_data_t* o_comp_data, uint32_t 
> group_id)
> +static int dcc_compress_image_lz(DisplayChannelClient *dcc,
> + SpiceImage *dest, SpiceBitmap *src,
> + compress_send_data_t* o_comp_data, uint32_t 
> group_id)
>  {
>  LzData *lz_data = &dcc->lz_data;
>  LzContext *lz = dcc->lz;
> @@ -785,9 +785,9 @@ int dcc_compress_image_lz(DisplayChannelClient *dcc,
>  return TRUE;
>  }
>  
> -int dcc_compress_image_jpeg(DisplayChannelClient *dcc, SpiceImage *dest,
> -SpiceBitmap *src, compress_send_data_t* 
> o_comp_data,
> -uint32_t group_id)
> +static int dcc_compress_image_jpeg(DisplayChannelClient *dcc, SpiceImage 
> *dest,
> +   SpiceBitmap *src, compress_send_data_t* 
> o_comp_data,
> +   uint32_t group_id)
>  {
>  JpegData *jpeg_data = &dcc->jpeg_data;
>  LzData *lz_data = &dcc->lz_data;
> @@ -910,9 +910,9 @@ int dcc_compress_image_jpeg(DisplayChannelClient *dcc, 
> SpiceImage *dest,
>  }
>  
>  #ifdef USE_LZ4
> -int dcc_compress_image_lz4(DisplayChannelClient *dcc, SpiceImage *dest,
> -   SpiceBitmap *src, compress_send_data_t* 
> o_comp_data,
> -   uint32_t group_id)
> +static int dcc_compress_image_lz4(DisplayChannelClient *dcc, SpiceImage 
> *dest,
> +  SpiceBitmap *src, compress_send_data_t* 
> o_comp_data,
> +  uint32_t group_id)
>  {
>  Lz4Data *lz4_data = &dcc->lz4_data;
>  Lz4EncoderContext *lz4 = dcc->lz4;
> @@ -957,9 +957,9 @@ int dcc_compress_image_lz4(DisplayChannelClient *dcc, 
> SpiceImage *dest,
>  }
>  #endif
>  
> -int dcc_compress_image_quic(DisplayChannelClient *dcc, SpiceImage *dest,
> -SpiceBitmap *src, compress_send_data_t* 
> o_comp_data,
> -uint32_t group_id)
> +static int dcc_compress_image_quic(DisplayChannelClient *dcc, SpiceImage 
> *dest,
> +   SpiceBitmap *src, compress_send_data_t* 
> o_comp_data,
> +   uint32_t group_id)
>  {
>  QuicData *quic_data = &dcc->quic_data;
>  QuicContext *quic = dcc->quic;
> diff --git a/server/dcc.h b/server/dcc.h
> index 2a12226..f715792 100644
> --- a/server/dcc.h
> +++ b/server/dcc.h
> @@ -219,20 +219,5 @@ intdcc_compress_image
> (DisplayCha
>
> SpiceImage *dest, SpiceBitmap *src, Drawable *drawable,
>int 
> can_lossy,
>
> compress_send_data_t* o_comp_data);
> -intdcc_compress_image_glz
> (DisplayChannelClient *dcc,
> -  
> SpiceImage *dest, SpiceBitmap *src, Drawable *drawable,
> -  
> compress_send_data_t* o_comp_data);
> -intdcc_compress_image_lz 
> (DisplayChannelClient *dcc,
> -  
> SpiceImage *dest, SpiceBitmap *src,
> -  
> compress_send_data_t* o_comp_data, uint32_t group_id);
> -intdcc_compress_image_jpeg   
> (DisplayChannelClient *dcc, SpiceImage *dest,
> -   

Re: [Spice-devel] [PATCH spice v2 2/4] dcc-send: Use dcc_compress_image to compress image

2016-01-18 Thread Victor Toso
Hi,

On Fri, Jan 15, 2016 at 05:11:33PM +0100, Pavel Grunt wrote:
> ---
>  server/dcc-send.c | 44 +++-
>  1 file changed, 3 insertions(+), 41 deletions(-)
> 
> diff --git a/server/dcc-send.c b/server/dcc-send.c
> index c3f79ef..58e654e 100644
> --- a/server/dcc-send.c
> +++ b/server/dcc-send.c
> @@ -1920,20 +1920,14 @@ static void red_marshall_image(RedChannelClient *rcc, 
> SpiceMarshaller *m, ImageI
>  DisplayChannelClient *dcc = RCC_TO_DCC(rcc);
>  DisplayChannel *display = DCC_TO_DC(dcc);
>  SpiceImage red_image;
> -RedWorker *worker;
>  SpiceBitmap bitmap;
>  SpiceChunks *chunks;
>  QRegion *surface_lossy_region;
> -int comp_succeeded = FALSE;
> -int lossy_comp = FALSE;
> -int quic_comp = FALSE;
> -SpiceImageCompression comp_mode;
>  SpiceMsgDisplayDrawCopy copy;
>  SpiceMarshaller *src_bitmap_out, *mask_bitmap_out;
>  SpiceMarshaller *bitmap_palette_out, *lzplt_palette_out;
>  
>  spice_assert(rcc && display && item);
> -worker = display->common.worker;
>  
>  QXL_SET_IMAGE_ID(&red_image, QXL_IMAGE_GROUP_RED, 
> display_channel_generate_uid(display));
>  red_image.descriptor.type = SPICE_IMAGE_TYPE_BITMAP;
> @@ -1981,44 +1975,12 @@ static void red_marshall_image(RedChannelClient *rcc, 
> SpiceMarshaller *m, ImageI
>  
>  compress_send_data_t comp_send_data = {0};
>  
> -comp_mode = dcc->image_compression;
> -
> -if (((comp_mode == SPICE_IMAGE_COMPRESSION_AUTO_LZ) ||
> -(comp_mode == SPICE_IMAGE_COMPRESSION_AUTO_GLZ)) && 
> !bitmap_has_extra_stride(&bitmap)) {
> -
> -if (bitmap_fmt_has_graduality(item->image_format)) {
> -BitmapGradualType grad_level;
> -
> -grad_level = bitmap_get_graduality_level(&bitmap);
> -if (grad_level == BITMAP_GRADUAL_HIGH) {
> -// if we use lz for alpha, the stride can't be extra
> -lossy_comp = display->enable_jpeg && item->can_lossy;
> -quic_comp = TRUE;
> -}
> -}
> -} else if (comp_mode == SPICE_IMAGE_COMPRESSION_QUIC) {
> -quic_comp = TRUE;
> -}
> -
> -uint32_t groupid = red_worker_get_memslot(worker)->internal_groupslot_id;
> -
> -if (lossy_comp) {
> -comp_succeeded = dcc_compress_image_jpeg(dcc, &red_image, &bitmap, 
> &comp_send_data, groupid);
> -} else if (quic_comp) {
> -comp_succeeded = dcc_compress_image_quic(dcc, &red_image, &bitmap, 
> &comp_send_data, groupid);
> -#ifdef USE_LZ4
> -} else if (comp_mode == SPICE_IMAGE_COMPRESSION_LZ4 &&
> -   bitmap_fmt_is_rgb(bitmap.format) &&
> -   red_channel_client_test_remote_cap(&dcc->common.base,
> -  
> SPICE_DISPLAY_CAP_LZ4_COMPRESSION)) {
> -comp_succeeded = dcc_compress_image_lz4(dcc, &red_image, &bitmap, 
> &comp_send_data, groupid);
> -#endif
> -} else if (comp_mode != SPICE_IMAGE_COMPRESSION_OFF) {
> -comp_succeeded = dcc_compress_image_lz(dcc, &red_image, &bitmap, 
> &comp_send_data, groupid);
> -}
> +int comp_succeeded = dcc_compress_image(dcc, &red_image, &bitmap, NULL, 
> item->can_lossy, &comp_send_data);
>
>  surface_lossy_region = 
> &dcc->surface_client_lossy_region[item->surface_id];
>  if (comp_succeeded) {
> +int lossy_comp = red_image.descriptor.type == SPICE_IMAGE_TYPE_JPEG 
> ||
> + red_image.descriptor.type == 
> SPICE_IMAGE_TYPE_JPEG_ALPHA;

This is not explained.. so, dcc_compress_image takes it->can_lossy but
you need to verify it in the end. Maybe a helper function would be more
clear?

>  spice_marshall_Image(src_bitmap_out, &red_image,
>   &bitmap_palette_out, &lzplt_palette_out);
>  
> -- 
> 2.5.0
> 
> ___
> Spice-devel mailing list
> Spice-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice v2 1/4] dcc_compress_image: Handle NULL drawable

2016-01-18 Thread Victor Toso
Hi,

On Fri, Jan 15, 2016 at 05:11:32PM +0100, Pavel Grunt wrote:
> ---
>  server/dcc.c | 38 +-
>  1 file changed, 21 insertions(+), 17 deletions(-)

The drawable being NULL only start to happen in the next patch, right?
It might be worth to mention it. Also, if drawable is NULL it is either
quic or lz/lz4, is that right?

Patch looks good otherwise

>
> diff --git a/server/dcc.c b/server/dcc.c
> index 2568e24..097140a 100644
> --- a/server/dcc.c
> +++ b/server/dcc.c
> @@ -1037,6 +1037,7 @@ int dcc_compress_image(DisplayChannelClient *dcc,
>  DisplayChannel *display_channel = DCC_TO_DC(dcc);
>  SpiceImageCompression image_compression = dcc->image_compression;
>  int quic_compress = FALSE;
> +uint32_t group_id;
>
>  if ((image_compression == SPICE_IMAGE_COMPRESSION_OFF) ||
>  ((src->y * src->stride) < MIN_SIZE_TO_COMPRESS)) { // TODO: change 
> the size cond
> @@ -1067,7 +1068,8 @@ int dcc_compress_image(DisplayChannelClient *dcc,
>  if ((src->x < MIN_DIMENSION_TO_QUIC) || (src->y < 
> MIN_DIMENSION_TO_QUIC)) {
>  quic_compress = FALSE;
>  } else {
> -if (drawable->copy_bitmap_graduality == 
> BITMAP_GRADUAL_INVALID) {
> +if (drawable == NULL ||
> +drawable->copy_bitmap_graduality == 
> BITMAP_GRADUAL_INVALID) {
>  quic_compress = 
> bitmap_fmt_has_graduality(src->format) &&
>  bitmap_get_graduality_level(src) == 
> BITMAP_GRADUAL_HIGH;
>  } else {
> @@ -1080,6 +1082,12 @@ int dcc_compress_image(DisplayChannelClient *dcc,
>  }
>  }
>
> +if (drawable != NULL) {
> +group_id = drawable->group_id;
> +} else {
> +group_id = 
> red_worker_get_memslot(display_channel->common.worker)->internal_groupslot_id;
> +}
> +
>  if (quic_compress) {
>  #ifdef COMPRESS_DEBUG
>  spice_info("QUIC compress");
> @@ -1090,24 +1098,22 @@ int dcc_compress_image(DisplayChannelClient *dcc,
>  (image_compression == SPICE_IMAGE_COMPRESSION_AUTO_GLZ))) {
>  // if we use lz for alpha, the stride can't be extra
>  if (src->format != SPICE_BITMAP_FMT_RGBA || 
> !bitmap_has_extra_stride(src)) {
> -return dcc_compress_image_jpeg(dcc, dest,
> -   src, o_comp_data, 
> drawable->group_id);
> +return dcc_compress_image_jpeg(dcc, dest, src, o_comp_data, 
> group_id);
>  }
>  }
> -return dcc_compress_image_quic(dcc, dest,
> -   src, o_comp_data, drawable->group_id);
> +return dcc_compress_image_quic(dcc, dest, src, o_comp_data, 
> group_id);
>  } else {
>  int glz;
>  int ret;
> -if ((image_compression == SPICE_IMAGE_COMPRESSION_AUTO_GLZ) ||
> -(image_compression == SPICE_IMAGE_COMPRESSION_GLZ)) {
> -glz = bitmap_fmt_has_graduality(src->format) && (
> -(src->x * src->y) < glz_enc_dictionary_get_size(
> -dcc->glz_dict->dict));
> -} else if ((image_compression == SPICE_IMAGE_COMPRESSION_AUTO_LZ) ||
> -   (image_compression == SPICE_IMAGE_COMPRESSION_LZ) ||
> -   (image_compression == SPICE_IMAGE_COMPRESSION_LZ4)) {
> +if ((image_compression == SPICE_IMAGE_COMPRESSION_AUTO_LZ) ||
> +(image_compression == SPICE_IMAGE_COMPRESSION_LZ) ||
> +(image_compression == SPICE_IMAGE_COMPRESSION_LZ4) ||
> +drawable == NULL) {
>  glz = FALSE;
> +} else if ((image_compression == SPICE_IMAGE_COMPRESSION_AUTO_GLZ) ||
> +   (image_compression == SPICE_IMAGE_COMPRESSION_GLZ)) {
> +glz = bitmap_fmt_has_graduality(src->format) &&
> +  ((src->x * src->y) < 
> glz_enc_dictionary_get_size(dcc->glz_dict->dict));
>  } else {
>  spice_error("invalid image compression type %u", 
> image_compression);
>  return FALSE;
> @@ -1132,12 +1138,10 @@ int dcc_compress_image(DisplayChannelClient *dcc,
>  bitmap_fmt_is_rgb(src->format) &&
>  red_channel_client_test_remote_cap(&dcc->common.base,
>  SPICE_DISPLAY_CAP_LZ4_COMPRESSION)) {
> -ret = dcc_compress_image_lz4(dcc, dest, src, o_comp_data,
> - drawable->group_id);
> +ret = dcc_compress_image_lz4(dcc, dest, src, o_comp_data, 
> group_id);
>  } else
>  #endif
> -ret = dcc_compress_image_lz(dcc, dest, src, o_comp_data,
> -drawable->group_id);
> +ret = dcc_compress_image_lz(dcc, dest, src, o_comp_data, 
> group_id);
>  #ifdef COMPRESS_DEBUG
>  spice_info("LZ LOC

[Spice-devel] [client v9 22/24] spice-gtk: Probe GStreamer before advertising support for a codec

2016-01-18 Thread Francois Gouget
Signed-off-by: Francois Gouget 
---
 src/channel-display-gst.c  | 17 +++--
 src/channel-display-priv.h |  4 ++--
 src/channel-display.c  | 21 +
 3 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/src/channel-display-gst.c b/src/channel-display-gst.c
index c5ad2e9..7b7d0eb 100644
--- a/src/channel-display-gst.c
+++ b/src/channel-display-gst.c
@@ -204,8 +204,7 @@ static uint8_t* gst_decoder_decode_frame(VideoDecoder 
*video_decoder,
 return NULL;
 }
 
-G_GNUC_INTERNAL
-gboolean gstvideo_init(void)
+static gboolean gstvideo_init(void)
 {
 static int success = 0;
 if (!success) {
@@ -236,3 +235,17 @@ VideoDecoder* create_gstreamer_decoder(int codec_type, 
display_stream *stream)
 
 return (VideoDecoder*)decoder;
 }
+
+G_GNUC_INTERNAL
+gboolean gstvideo_has_codec(int codec_type)
+{
+gboolean has_codec = FALSE;
+
+VideoDecoder *decoder = create_gstreamer_decoder(codec_type, NULL);
+if (decoder) {
+has_codec = construct_pipeline((SpiceGstDecoder*)decoder);
+decoder->destroy(decoder);
+}
+
+return has_codec;
+}
diff --git a/src/channel-display-priv.h b/src/channel-display-priv.h
index 2c64eb4..fee1047 100644
--- a/src/channel-display-priv.h
+++ b/src/channel-display-priv.h
@@ -70,9 +70,9 @@ VideoDecoder* create_mjpeg_decoder(int codec_type, 
display_stream *stream);
 #endif
 #ifdef HAVE_GSTVIDEO
 VideoDecoder* create_gstreamer_decoder(int codec_type, display_stream *stream);
-gboolean gstvideo_init(void);
+gboolean gstvideo_has_codec(int codec_type);
 #else
-# define gstvideo_init() FALSE
+# define gstvideo_has_codec(codec_type) FALSE
 #endif
 
 
diff --git a/src/channel-display.c b/src/channel-display.c
index 193f177..4a998b4 100644
--- a/src/channel-display.c
+++ b/src/channel-display.c
@@ -632,10 +632,23 @@ static void 
spice_display_channel_reset_capabilities(SpiceChannel *channel)
 #ifdef HAVE_BUILTIN_MJPEG
 spice_channel_set_capability(SPICE_CHANNEL(channel), 
SPICE_DISPLAY_CAP_CODEC_MJPEG);
 #endif
-if (gstvideo_init()) {
-spice_channel_set_capability(SPICE_CHANNEL(channel), 
SPICE_DISPLAY_CAP_CODEC_MJPEG);
-spice_channel_set_capability(SPICE_CHANNEL(channel), 
SPICE_DISPLAY_CAP_CODEC_VP8);
-spice_channel_set_capability(SPICE_CHANNEL(channel), 
SPICE_DISPLAY_CAP_CODEC_H264);
+if (gstvideo_has_codec(SPICE_VIDEO_CODEC_TYPE_MJPEG)) {
+spice_channel_set_capability(SPICE_CHANNEL(channel),
+ SPICE_DISPLAY_CAP_CODEC_MJPEG);
+} else {
+spice_info("GStreamer does not support the mjpeg codec");
+}
+if (gstvideo_has_codec(SPICE_VIDEO_CODEC_TYPE_VP8)) {
+spice_channel_set_capability(SPICE_CHANNEL(channel),
+ SPICE_DISPLAY_CAP_CODEC_VP8);
+} else {
+spice_info("GStreamer does not support the vp8 codec");
+}
+if (gstvideo_has_codec(SPICE_VIDEO_CODEC_TYPE_H264)) {
+spice_channel_set_capability(SPICE_CHANNEL(channel),
+ SPICE_DISPLAY_CAP_CODEC_H264);
+} else {
+spice_info("GStreamer does not support the h264 codec");
 }
 }
 
-- 
2.6.4

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH] Change some functions to take RedsState arg

2016-01-18 Thread Frediano Ziglio
> 
> From: Jonathon Jongsma 
> 
> In preparation for getting rid of the global 'reds' variable, we need to
> pass the RedsState variable to all functions where it is needed. For now
> the callers just pass in the global reds variable.
> 
> Functions changed:
> - reds_register_channel;
> - reds_unregister_channel;
> - reds_get_mouse_mode;
> - reds_set_mouse_mode;
> - reds_update_mouse_mode;
> - reds_agent_remove;
> - reds_find_channel;
> - reds_mig_cleanup;
> - reds_reset_vdp;
> - reds_main_channel_connected;
> - reds_client_disconnect;
> - reds_disconnect;
> - reds_mig_disconnect.
> 
> Acked-by: Frediano Ziglio 

Does it sound reasonable as comment and patch (just a squash of posted ones)?
Should I number the title?

Frediano

> ---
>  server/inputs-channel.c  |  10 ++---
>  server/main-dispatcher.c |   2 +-
>  server/red-dispatcher.c  |   4 +-
>  server/reds.c| 104
>  +++
>  server/reds.h|   8 ++--
>  server/smartcard.c   |   2 +-
>  server/sound.c   |   6 +--
>  server/spicevmc.c|   4 +-
>  8 files changed, 70 insertions(+), 70 deletions(-)
> 
> diff --git a/server/inputs-channel.c b/server/inputs-channel.c
> index c21cab8..bb5b203 100644
> --- a/server/inputs-channel.c
> +++ b/server/inputs-channel.c
> @@ -364,7 +364,7 @@ static int inputs_channel_handle_parsed(RedChannelClient
> *rcc, uint32_t size, ui
>  red_channel_client_pipe_add_type(rcc,
>  PIPE_ITEM_MOUSE_MOTION_ACK);
>  icc->motion_count = 0;
>  }
> -if (mouse && reds_get_mouse_mode() == SPICE_MOUSE_MODE_SERVER) {
> +if (mouse && reds_get_mouse_mode(reds) == SPICE_MOUSE_MODE_SERVER) {
>  SpiceMouseInterface *sif;
>  sif = SPICE_CONTAINEROF(mouse->base.sif, SpiceMouseInterface,
>  base);
>  sif->motion(mouse,
> @@ -381,7 +381,7 @@ static int inputs_channel_handle_parsed(RedChannelClient
> *rcc, uint32_t size, ui
>  red_channel_client_pipe_add_type(rcc,
>  PIPE_ITEM_MOUSE_MOTION_ACK);
>  icc->motion_count = 0;
>  }
> -if (reds_get_mouse_mode() != SPICE_MOUSE_MODE_CLIENT) {
> +if (reds_get_mouse_mode(reds) != SPICE_MOUSE_MODE_CLIENT) {
>  break;
>  }
>  spice_assert((reds_get_agent_mouse() && reds_has_vdagent()) ||
>  tablet);
> @@ -407,7 +407,7 @@ static int inputs_channel_handle_parsed(RedChannelClient
> *rcc, uint32_t size, ui
>  } else if (mouse_press->button == SPICE_MOUSE_BUTTON_DOWN) {
>  dz = 1;
>  }
> -if (reds_get_mouse_mode() == SPICE_MOUSE_MODE_CLIENT) {
> +if (reds_get_mouse_mode(reds) == SPICE_MOUSE_MODE_CLIENT) {
>  if (reds_get_agent_mouse() && reds_has_vdagent()) {
>  inputs_channel->mouse_state.buttons =
>  
> RED_MOUSE_BUTTON_STATE_TO_AGENT(mouse_press->buttons_state)
>  |
> @@ -429,7 +429,7 @@ static int inputs_channel_handle_parsed(RedChannelClient
> *rcc, uint32_t size, ui
>  }
>  case SPICE_MSGC_INPUTS_MOUSE_RELEASE: {
>  SpiceMsgcMouseRelease *mouse_release = message;
> -if (reds_get_mouse_mode() == SPICE_MOUSE_MODE_CLIENT) {
> +if (reds_get_mouse_mode(reds) == SPICE_MOUSE_MODE_CLIENT) {
>  if (reds_get_agent_mouse() && reds_has_vdagent()) {
>  inputs_channel->mouse_state.buttons =
>  
> RED_MOUSE_BUTTON_STATE_TO_AGENT(mouse_release->buttons_state);
> @@ -672,7 +672,7 @@ void inputs_init(void)
>  red_channel_register_client_cbs(&g_inputs_channel->base, &client_cbs);
>  
>  red_channel_set_cap(&g_inputs_channel->base,
>  SPICE_INPUTS_CAP_KEY_SCANCODE);
> -reds_register_channel(&g_inputs_channel->base);
> +reds_register_channel(reds, &g_inputs_channel->base);
>  
>  if (!(key_modifiers_timer = core->timer_add(core, key_modifiers_sender,
>  NULL))) {
>  spice_error("key modifiers timer create failed");
> diff --git a/server/main-dispatcher.c b/server/main-dispatcher.c
> index 2cb53ef..db87e05 100644
> --- a/server/main-dispatcher.c
> +++ b/server/main-dispatcher.c
> @@ -136,7 +136,7 @@ static void main_dispatcher_handle_client_disconnect(void
> *opaque,
>  MainDispatcherClientDisconnectMessage *msg = payload;
>  
>  spice_debug("client=%p", msg->client);
> -reds_client_disconnect(msg->client);
> +reds_client_disconnect(reds, msg->client);
>  red_client_unref(msg->client);
>  }
>  
> diff --git a/server/red-dispatcher.c b/server/red-dispatcher.c
> index 0810798..dc958d9 100644
> --- a/server/red-dispatcher.c
> +++ b/server/red-dispatcher.c
> @@ -1044,7 +1044,7 @@ void red_dispatcher_init(QXLInstance *qxl)
>  client_cbs.migrate = red_dispatcher_cursor_migrate;
>  red_channel_register_client_cbs(channel, &client_cbs);
>  red_channel_set_data(channel, red_dispatcher);
> -reds_register_c

[Spice-devel] [qxl v9 16/24] spiceqxl: Add SpiceVideoCodecs to specify video codec preferences

2016-01-18 Thread Francois Gouget
Signed-off-by: Francois Gouget 
---
 examples/spiceqxl.xorg.conf.example |  7 +++
 src/qxl.h   |  1 +
 src/qxl_driver.c|  2 ++
 src/spiceqxl_spice_server.c | 15 +++
 4 files changed, 25 insertions(+)

diff --git a/examples/spiceqxl.xorg.conf.example 
b/examples/spiceqxl.xorg.conf.example
index ec6321e..b6f4840 100644
--- a/examples/spiceqxl.xorg.conf.example
+++ b/examples/spiceqxl.xorg.conf.example
@@ -52,6 +52,13 @@ Section "Device"
 # default: filter
 #Option "SpiceStreamingVideo" ""
 
+# Set video codecs to use.  Provide a semicolon list of
+# codecs, in preference order.  Each codec requires an encoder
+# which can be one of spice or gstreamer, and then a codec type,
+# for instance mjpeg or vp8. The default is spice:mjpeg,
+# which uses the builtin mjpeg encoder.
+#Option "SpiceVideoCodecs" ""
+
 # Set zlib glz wan compression. Options are auto, never, always.
 # default: auto
 #Option "SpiceZlibGlzWanCompression" ""
diff --git a/src/qxl.h b/src/qxl.h
index ff55604..5cc8d05 100644
--- a/src/qxl.h
+++ b/src/qxl.h
@@ -158,6 +158,7 @@ enum {
 OPTION_SURFACE_BUFFER_SIZE,
 OPTION_COMMAND_BUFFER_SIZE,
 OPTION_SPICE_SMARTCARD_FILE,
+OPTION_SPICE_VIDEO_CODECS,
 #endif
 OPTION_COUNT,
 };
diff --git a/src/qxl_driver.c b/src/qxl_driver.c
index e21addd..fc1b629 100644
--- a/src/qxl_driver.c
+++ b/src/qxl_driver.c
@@ -154,6 +154,8 @@ const OptionInfoRec DefaultOptions[] =
   "CommandBufferSize",OPTV_INTEGER,
{DEFAULT_COMMAND_BUFFER_SIZE}, FALSE},
 { OPTION_SPICE_SMARTCARD_FILE,
   "SpiceSmartcardFile",   OPTV_STRING,{0}, FALSE},
+{ OPTION_SPICE_VIDEO_CODECS,
+  "SpiceVideoCodecs", OPTV_STRING,{0}, FALSE},
 #endif
 
 { -1, NULL, OPTV_NONE, {0}, FALSE }
diff --git a/src/spiceqxl_spice_server.c b/src/spiceqxl_spice_server.c
index b2b31ff..15b0531 100644
--- a/src/spiceqxl_spice_server.c
+++ b/src/spiceqxl_spice_server.c
@@ -173,6 +173,9 @@ void xspice_set_spice_server_options(OptionInfoPtr options)
 const char *streaming_video =
 get_str_option(options, OPTION_SPICE_STREAMING_VIDEO,
"XSPICE_STREAMING_VIDEO");
+const char *video_codecs =
+get_str_option(options, OPTION_SPICE_VIDEO_CODECS,
+   "XSPICE_VIDEO_CODECS");
 int agent_mouse =
 get_bool_option(options, OPTION_SPICE_AGENT_MOUSE,
 "XSPICE_AGENT_MOUSE");
@@ -294,6 +297,18 @@ void xspice_set_spice_server_options(OptionInfoPtr options)
 spice_server_set_streaming_video(spice_server, streaming_video_opt);
 }
 
+if (video_codecs) {
+#if SPICE_SERVER_VERSION >= 0x000c06 /* 0.12.6 */
+if (spice_server_set_video_codecs(spice_server, video_codecs)) {
+fprintf(stderr, "spice: invalid video encoder %s\n", video_codecs);
+exit(1);
+}
+#else
+fprintf(stderr, "spice: video_codecs are not available (spice >= 
0.12.6 required)\n");
+exit(1);
+#endif
+}
+
 spice_server_set_agent_mouse(spice_server, agent_mouse);
 spice_server_set_playback_compression(spice_server, playback_compression);
 
-- 
2.6.4

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [qxl v9 17/24] Xspice: Add --video-codecs to specify encoder and codec preferences

2016-01-18 Thread Francois Gouget
Signed-off-by: Francois Gouget 
---
 scripts/Xspice | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/scripts/Xspice b/scripts/Xspice
index 15a5a5e..bf8112f 100755
--- a/scripts/Xspice
+++ b/scripts/Xspice
@@ -87,6 +87,7 @@ parser.add_argument('--zlib-glz-wan-compression',
 # TODO - sound support
 parser.add_argument('--streaming-video', choices=['off', 'all', 'filter'],
 help='filter by default')
+parser.add_argument('--video-codecs', help="Sets a semicolon-separated list of 
preferred video codecs to use. Each takes the form encoder:codec, with 
spice:mjpeg being the default and other options being provided by gstreamer for 
the mjpeg, vp8 and h264 codecs.")
 add_boolean('--ipv4-only')
 add_boolean('--ipv6-only')
 parser.add_argument('--vdagent', action='store_true', dest='vdagent_enabled', 
default=False, help='launch vdagent & vdagentd. They provide clipboard & 
resolution automation')
@@ -282,7 +283,7 @@ var_args = ['port', 'tls_port', 'disable_ticketing',
 'x509_key_file', 'x509_key_password',
 'tls_ciphers', 'dh_file', 'password', 'image_compression',
 'jpeg_wan_compression', 'zlib_glz_wan_compression',
-'streaming_video', 'deferred_fps', 'exit_on_disconnect',
+'streaming_video', 'video_codecs', 'deferred_fps', 'exit_on_disconnect',
 'vdagent_enabled', 'vdagent_virtio_path', 'vdagent_uinput_path',
 'vdagent_uid', 'vdagent_gid']
 
-- 
2.6.4
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [client v9 23/24] spice-gtk: Avoid copying the compressed message data for SpiceGstDecoder

2016-01-18 Thread Francois Gouget
Signed-off-by: Francois Gouget 
---
 src/channel-display-gst.c | 88 +--
 1 file changed, 85 insertions(+), 3 deletions(-)

diff --git a/src/channel-display-gst.c b/src/channel-display-gst.c
index 7b7d0eb..bc7f94a 100644
--- a/src/channel-display-gst.c
+++ b/src/channel-display-gst.c
@@ -46,11 +46,43 @@ typedef struct SpiceGstDecoder {
 
 /* -- Output frame data -- */
 
+GMutex pipeline_mutex;
+GCond pipeline_cond;
+gboolean pipeline_wait;
+uint32_t samples_count;
+
 GstBuffer *buffer;
 GstMapInfo mapinfo;
 } SpiceGstDecoder;
 
 
+/* Signals that the pipeline is done processing the last buffer we gave it.
+ *
+ * @decoder:   The video decoder object.
+ * @samples:   How many samples to add to the available samples count.
+ */
+static void signal_pipeline(SpiceGstDecoder *decoder, uint32_t samples)
+{
+g_mutex_lock(&decoder->pipeline_mutex);
+decoder->pipeline_wait = FALSE;
+decoder->samples_count += samples;
+g_cond_signal(&decoder->pipeline_cond);
+g_mutex_unlock(&decoder->pipeline_mutex);
+}
+
+static void appsrc_need_data_cb(GstAppSrc *src, guint length, gpointer 
user_data)
+{
+SpiceGstDecoder *decoder = (SpiceGstDecoder*)user_data;
+signal_pipeline(decoder, 0);
+}
+
+static GstFlowReturn appsink_new_sample_cb(GstAppSink *appsrc, gpointer 
user_data)
+{
+SpiceGstDecoder *decoder = (SpiceGstDecoder*)user_data;
+signal_pipeline(decoder, 1);
+return GST_FLOW_OK;
+}
+
 /* -- GStreamer pipeline -- */
 
 static void reset_pipeline(SpiceGstDecoder *decoder)
@@ -64,10 +96,18 @@ static void reset_pipeline(SpiceGstDecoder *decoder)
 gst_object_unref(decoder->appsink);
 gst_object_unref(decoder->pipeline);
 decoder->pipeline = NULL;
+
+g_mutex_clear(&decoder->pipeline_mutex);
+g_cond_clear(&decoder->pipeline_cond);
 }
 
 static gboolean construct_pipeline(SpiceGstDecoder *decoder)
 {
+g_mutex_init(&decoder->pipeline_mutex);
+g_cond_init(&decoder->pipeline_cond);
+decoder->pipeline_wait = TRUE;
+decoder->samples_count = 0;
+
 const gchar *src_caps, *gstdec_name;
 switch (decoder->base.codec_type) {
 case SPICE_VIDEO_CODEC_TYPE_MJPEG:
@@ -99,7 +139,12 @@ static gboolean construct_pipeline(SpiceGstDecoder *decoder)
 }
 
 decoder->appsrc = 
GST_APP_SRC(gst_bin_get_by_name(GST_BIN(decoder->pipeline), "src"));
+GstAppSrcCallbacks appsrc_cbs = {&appsrc_need_data_cb, NULL, NULL, {NULL}};
+gst_app_src_set_callbacks(decoder->appsrc, &appsrc_cbs, decoder, NULL);
+
 decoder->appsink = 
GST_APP_SINK(gst_bin_get_by_name(GST_BIN(decoder->pipeline), "sink"));
+GstAppSinkCallbacks appsink_cbs = {NULL, NULL, &appsink_new_sample_cb, 
{NULL}};
+gst_app_sink_set_callbacks(decoder->appsink, &appsink_cbs, decoder, NULL);
 
 if (gst_element_set_state(decoder->pipeline, GST_STATE_PLAYING) == 
GST_STATE_CHANGE_FAILURE) {
 SPICE_DEBUG("GStreamer error: Unable to set the pipeline to the 
playing state.");
@@ -110,6 +155,11 @@ static gboolean construct_pipeline(SpiceGstDecoder 
*decoder)
 return TRUE;
 }
 
+static void release_msg_in(gpointer data)
+{
+spice_msg_in_unref((SpiceMsgIn*)data);
+}
+
 static gboolean push_compressed_buffer(SpiceGstDecoder *decoder,
SpiceMsgIn *frame_msg)
 {
@@ -120,8 +170,12 @@ static gboolean push_compressed_buffer(SpiceGstDecoder 
*decoder,
 return FALSE;
 }
 
-GstBuffer *buffer = gst_buffer_new_allocate(NULL, size, NULL);
-gst_buffer_fill(buffer, 0, data, size);
+/* Reference frame_msg so it stays around until our 'deallocator' releases 
it */
+spice_msg_in_ref(frame_msg);
+GstBuffer *buffer = gst_buffer_new_wrapped_full(GST_MEMORY_FLAG_READONLY,
+data, size, 0, size,
+frame_msg, 
&release_msg_in);
+
 if (gst_app_src_push_buffer(decoder->appsrc, buffer) != GST_FLOW_OK) {
 SPICE_DEBUG("GStreamer error: unable to push frame of size %d", size);
 return FALSE;
@@ -198,8 +252,36 @@ static uint8_t* gst_decoder_decode_frame(VideoDecoder 
*video_decoder,
  */
 release_last_frame(decoder);
 
+/* The pipeline may have called appsrc_need_data_cb() after we got the last
+ * output frame. This would cause us to return prematurely so reset
+ * pipeline_wait so we do wait for it to process this buffer.
+ */
+g_mutex_lock(&decoder->pipeline_mutex);
+decoder->pipeline_wait = TRUE;
+g_mutex_unlock(&decoder->pipeline_mutex);
+/* Note that it's possible for appsrc_need_data_cb() to get called between
+ * now and the pipeline wait. But this will at most cause a one frame 
delay.
+ */
+
 if (push_compressed_buffer(decoder, frame_msg)) {
-return pull_raw_frame(decoder);
+/* Wait for the pipeline to either produce a decoded frame, or ask
+ 

[Spice-devel] [client v9 24/24] spice-gtk: Use decodebin as a fallback for the GStreamer video decoder

2016-01-18 Thread Francois Gouget
This means future video codecs may be supported automatically.
One can also force usage of decodebin by setting $SPICE_GSTVIDEO_AUTO.

Signed-off-by: Francois Gouget 
---
 src/channel-display-gst.c | 21 ++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/src/channel-display-gst.c b/src/channel-display-gst.c
index bc7f94a..4e2c6f9 100644
--- a/src/channel-display-gst.c
+++ b/src/channel-display-gst.c
@@ -108,7 +108,16 @@ static gboolean construct_pipeline(SpiceGstDecoder 
*decoder)
 decoder->pipeline_wait = TRUE;
 decoder->samples_count = 0;
 
-const gchar *src_caps, *gstdec_name;
+/* Note that we cannot rely on typefind to always identify the stream type
+ * (e.g. VP8). So always set the source caps for streams we know about.
+ * See: https://bugzilla.gnome.org/show_bug.cgi?id=756457
+ *
+ * Furthermore decodebin will use vaapi if installed, which for a time
+ * could intentionally crash the application. So only use decodebin as a
+ * fallback for now. See: 
https://bugs.freedesktop.org/show_bug.cgi?id=90884
+ */
+const gchar *src_caps;
+const gchar *gstdec_name = NULL;
 switch (decoder->base.codec_type) {
 case SPICE_VIDEO_CODEC_TYPE_MJPEG:
 src_caps = "caps=image/jpeg";
@@ -123,8 +132,14 @@ static gboolean construct_pipeline(SpiceGstDecoder 
*decoder)
 gstdec_name = "h264parse ! avdec_h264";
 break;
 default:
-spice_warning("Unknown codec type %d", decoder->base.codec_type);
-return -1;
+SPICE_DEBUG("Unknown codec type %d. Trying decodebin.",
+decoder->base.codec_type);
+src_caps = "";
+break;
+}
+/* Set SPICE_GSTVIDEO_AUTO to test decodebin and maybe get hardware 
acceleration */
+if (!gstdec_name || getenv("SPICE_GSTVIDEO_AUTO")) {
+gstdec_name = "decodebin";
 }
 
 GError *err = NULL;
-- 
2.6.4
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [client v9 20/24] spice-gtk: Add a GStreamer video decoder for MJPEG, VP8 and h264

2016-01-18 Thread Francois Gouget
Based on a patch by Jeremy White.

Signed-off-by: Francois Gouget 
---
 configure.ac   |  28 +-
 src/Makefile.am|   8 ++
 src/channel-display-gst.c  | 238 +
 src/channel-display-priv.h |   6 ++
 src/channel-display.c  |  10 ++
 5 files changed, 288 insertions(+), 2 deletions(-)
 create mode 100644 src/channel-display-gst.c

diff --git a/configure.ac b/configure.ac
index 38db8b5..cef73de 100644
--- a/configure.ac
+++ b/configure.ac
@@ -70,7 +70,7 @@ AC_CHECK_LIBM
 AC_SUBST(LIBM)
 
 AC_CONFIG_SUBDIRS([spice-common])
-PKG_CHECK_MODULES([SPICE_PROTOCOL], [spice-protocol >= 0.12.10])
+PKG_CHECK_MODULES([SPICE_PROTOCOL], [spice-protocol >= 0.12.11])
 
 COMMON_CFLAGS='-I ${top_srcdir}/spice-common/ ${SPICE_PROTOCOL_CFLAGS}'
 AC_SUBST(COMMON_CFLAGS)
@@ -292,6 +292,29 @@ AS_IF([test "x$enable_pulse$have_gstaudio" = "xnono"],
   [SPICE_WARNING([No PulseAudio or GStreamer 1.0 audio decoder, audio will 
not be streamed])
 ])
 
+AC_ARG_ENABLE([gstvideo],
+  AS_HELP_STRING([--enable-gstvideo=@<:@auto/yes/no@:>@],
+ [Enable GStreamer video support @<:@default=auto@:>@]),
+  [],
+  [enable_gstvideo="auto"])
+AS_IF([test "x$enable_gstvideo" != "xno"],
+  [SPICE_CHECK_GSTREAMER(GSTVIDEO, 1.0,
+ [gstreamer-1.0 gstreamer-base-1.0 gstreamer-app-1.0 
gstreamer-video-1.0],
+ [missing_gstreamer_elements=""
+  SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_1_0, [gst-plugins-base 
1.0], [appsrc videoconvert appsink])
+  SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_1_0, [gst-plugins-good 
1.0], [jpegdec vp8dec])
+  SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_1_0, [gst-plugins-bad 
1.0], [h264parse])
+  SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_1_0, [gstreamer-libav 
1.0], [avdec_h264])
+  AS_IF([test x"$missing_gstreamer_elements" = "xyes"],
+SPICE_WARNING([The GStreamer video decoder can be built but 
may not work.]))
+ ],
+ [AS_IF([test "x$enable_gstvideo" = "xyes"],
+AC_MSG_ERROR([GStreamer 1.0 video requested but not found]))
+ ])
+  ], [have_gstvideo="no"]
+)
+AM_CONDITIONAL([HAVE_GSTVIDEO], [test "x$have_gstvideo" = "xyes"])
+
 AC_CHECK_LIB(jpeg, jpeg_destroy_decompress,
 AC_MSG_CHECKING([for jpeglib.h])
 AC_TRY_CPP(
@@ -654,7 +677,7 @@ SPICE_CFLAGS="$SPICE_CFLAGS $WARN_CFLAGS"
 
 AC_SUBST(SPICE_CFLAGS)
 
-SPICE_GLIB_CFLAGS="$PIXMAN_CFLAGS $PULSE_CFLAGS $GSTAUDIO_CFLAGS $GLIB2_CFLAGS 
$GIO_CFLAGS $GOBJECT2_CFLAGS $SSL_CFLAGS $SASL_CFLAGS"
+SPICE_GLIB_CFLAGS="$PIXMAN_CFLAGS $PULSE_CFLAGS $GSTAUDIO_CFLAGS 
$GSTVIDEO_CFLAGS $GLIB2_CFLAGS $GIO_CFLAGS $GOBJECT2_CFLAGS $SSL_CFLAGS 
$SASL_CFLAGS"
 SPICE_GTK_CFLAGS="$SPICE_GLIB_CFLAGS $GTK_CFLAGS "
 
 AC_SUBST(SPICE_GLIB_CFLAGS)
@@ -699,6 +722,7 @@ AC_MSG_NOTICE([
 Coroutine:${with_coroutine}
 PulseAudio:   ${enable_pulse}
 GStreamer Audio:  ${have_gstaudio}
+GStreamer Video:  ${have_gstvideo}
 SASL support: ${have_sasl}
 Smartcard support:${have_smartcard}
 USB redirection support:  ${have_usbredir} ${with_usbredir_hotplug}
diff --git a/src/Makefile.am b/src/Makefile.am
index 37b89fe..cb99610 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -98,6 +98,7 @@ SPICE_COMMON_CPPFLAGS =   
\
$(SSL_CFLAGS)   \
$(SASL_CFLAGS)  \
$(GSTAUDIO_CFLAGS)  \
+   $(GSTVIDEO_CFLAGS)  \
$(SMARTCARD_CFLAGS) \
$(USBREDIR_CFLAGS)  \
$(GUDEV_CFLAGS) \
@@ -210,6 +211,7 @@ libspice_client_glib_2_0_la_LIBADD =
\
$(SSL_LIBS) \
$(PULSE_LIBS)   \
$(GSTAUDIO_LIBS)\
+   $(GSTVIDEO_LIBS)\
$(SASL_LIBS)\
$(SMARTCARD_LIBS)   \
$(USBREDIR_LIBS)\
@@ -343,6 +345,12 @@ libspice_client_glib_2_0_la_SOURCES += \
$(NULL)
 endif
 
+if HAVE_GSTVIDEO
+libspice_client_glib_2_0_la_SOURCES += \
+   channel-display-gst.c   \
+   $(NULL)
+endif
+
 if WITH_PHODAV
 libspice_client_glib_2_0_la_SOURCES += \
giopipe.c   \
diff --git a/src/channel-display-gst.c b/src/channel-display-gst.c
new file mode 100644
index 000..c5ad2e9
--- /dev/null
+++ b/src/channel-displa

[Spice-devel] [client v9 21/24] spice-gtk: Allow disabling support for the builtin MJPEG video decoder

2016-01-18 Thread Francois Gouget
This makes it possible to test the GStreamer video decoder with MJPEG
streams.

Signed-off-by: Francois Gouget 
---
 configure.ac   | 11 +++
 src/Makefile.am|  7 ++-
 src/channel-display-priv.h |  2 ++
 src/channel-display.c  |  5 +
 4 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index cef73de..8f44a59 100644
--- a/configure.ac
+++ b/configure.ac
@@ -315,6 +315,17 @@ AS_IF([test "x$enable_gstvideo" != "xno"],
 )
 AM_CONDITIONAL([HAVE_GSTVIDEO], [test "x$have_gstvideo" = "xyes"])
 
+AC_ARG_ENABLE([builtin-mjpeg],
+  AS_HELP_STRING([--enable-builtin-mjpeg], [Enable the builtin mjpeg video 
decoder @<:@default=yes@:>@]),
+  [],
+  enable_builtin_mjpeg="yes")
+AS_IF([test "x$enable_builtin_mjpeg" = "xyes"],
+  [AC_DEFINE([HAVE_BUILTIN_MJPEG], 1, [Use the builtin mjpeg decoder?])])
+AM_CONDITIONAL(HAVE_BUILTIN_MJPEG, [test "x$enable_builtin_mjpeg" != "xno"])
+
+AS_IF([test "x$enable_builtin_mjpeg$enable_gstvideo" = "xnono"],
+  [SPICE_WARNING([No builtin MJPEG or GStreamer decoder, video will not be 
streamed])])
+
 AC_CHECK_LIB(jpeg, jpeg_destroy_decompress,
 AC_MSG_CHECKING([for jpeglib.h])
 AC_TRY_CPP(
diff --git a/src/Makefile.am b/src/Makefile.am
index cb99610..37a2234 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -257,7 +257,6 @@ libspice_client_glib_2_0_la_SOURCES =   
\
channel-cursor.c\
channel-display.c   \
channel-display-priv.h  \
-   channel-display-mjpeg.c \
channel-inputs.c\
channel-main.c  \
channel-playback.c  \
@@ -345,6 +344,12 @@ libspice_client_glib_2_0_la_SOURCES += \
$(NULL)
 endif
 
+if HAVE_BUILTIN_MJPEG
+libspice_client_glib_2_0_la_SOURCES += \
+   channel-display-mjpeg.c \
+   $(NULL)
+endif
+
 if HAVE_GSTVIDEO
 libspice_client_glib_2_0_la_SOURCES += \
channel-display-gst.c   \
diff --git a/src/channel-display-priv.h b/src/channel-display-priv.h
index d8a03e9..2c64eb4 100644
--- a/src/channel-display-priv.h
+++ b/src/channel-display-priv.h
@@ -65,7 +65,9 @@ struct VideoDecoder {
  * @stream: The associated video stream.
  * @return: A pointer to a structure implementing the VideoDecoder methods.
  */
+#ifdef HAVE_BUILTIN_MJPEG
 VideoDecoder* create_mjpeg_decoder(int codec_type, display_stream *stream);
+#endif
 #ifdef HAVE_GSTVIDEO
 VideoDecoder* create_gstreamer_decoder(int codec_type, display_stream *stream);
 gboolean gstvideo_init(void);
diff --git a/src/channel-display.c b/src/channel-display.c
index c1ccde5..193f177 100644
--- a/src/channel-display.c
+++ b/src/channel-display.c
@@ -629,8 +629,11 @@ static void 
spice_display_channel_reset_capabilities(SpiceChannel *channel)
 spice_channel_set_capability(SPICE_CHANNEL(channel), 
SPICE_DISPLAY_CAP_STREAM_REPORT);
 }
 spice_channel_set_capability(SPICE_CHANNEL(channel), 
SPICE_DISPLAY_CAP_MULTI_CODEC);
+#ifdef HAVE_BUILTIN_MJPEG
 spice_channel_set_capability(SPICE_CHANNEL(channel), 
SPICE_DISPLAY_CAP_CODEC_MJPEG);
+#endif
 if (gstvideo_init()) {
+spice_channel_set_capability(SPICE_CHANNEL(channel), 
SPICE_DISPLAY_CAP_CODEC_MJPEG);
 spice_channel_set_capability(SPICE_CHANNEL(channel), 
SPICE_DISPLAY_CAP_CODEC_VP8);
 spice_channel_set_capability(SPICE_CHANNEL(channel), 
SPICE_DISPLAY_CAP_CODEC_H264);
 }
@@ -1038,9 +1041,11 @@ static void display_handle_stream_create(SpiceChannel 
*channel, SpiceMsgIn *in)
 display_update_stream_region(st);
 
 switch (op->codec_type) {
+#ifdef HAVE_BUILTIN_MJPEG
 case SPICE_VIDEO_CODEC_TYPE_MJPEG:
 st->video_decoder = create_mjpeg_decoder(op->codec_type, st);
 break;
+#endif
 default:
 #ifdef HAVE_GSTVIDEO
 st->video_decoder = create_gstreamer_decoder(op->codec_type, st);
-- 
2.6.4

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [client v9 18/24] spice-gtk: Enable adding alternative video decoders

2016-01-18 Thread Francois Gouget
This replaces the original channel-display-mjpeg API with a VideoDecoder
base class which can be reimplemented by other decoders.
Furthermore this moves the MJPEG-specific state information from the
display_stream struct to a derived class of VideoDecoder.

Signed-off-by: Francois Gouget 
---
 src/channel-display-mjpeg.c | 131 
 src/channel-display-priv.h  |  53 +-
 src/channel-display.c   |  63 ++---
 3 files changed, 151 insertions(+), 96 deletions(-)

diff --git a/src/channel-display-mjpeg.c b/src/channel-display-mjpeg.c
index 95d5b33..78e3d5a 100644
--- a/src/channel-display-mjpeg.c
+++ b/src/channel-display-mjpeg.c
@@ -23,12 +23,33 @@
 
 #include "channel-display-priv.h"
 
+
+/* MJpeg decoder implementation */
+
+typedef struct MJpegDecoder {
+VideoDecoder base;
+
+/* -- The builtin mjpeg decoder -- */
+
+SpiceMsgIn *frame_msg;
+struct jpeg_source_mgr mjpeg_src;
+struct jpeg_decompress_struct  mjpeg_cinfo;
+struct jpeg_error_mgr  mjpeg_jerr;
+
+/* -- Output frame data -- */
+
+uint8_t *out_frame;
+} MJpegDecoder;
+
+
+/* -- The JPEG library callbacks -- */
+
 static void mjpeg_src_init(struct jpeg_decompress_struct *cinfo)
 {
-display_stream *st = SPICE_CONTAINEROF(cinfo->src, display_stream, 
mjpeg_src);
-uint8_t *data;
+MJpegDecoder *decoder = SPICE_CONTAINEROF(cinfo->src, MJpegDecoder, 
mjpeg_src);
 
-cinfo->src->bytes_in_buffer = stream_get_current_frame(st, &data);
+uint8_t *data;
+cinfo->src->bytes_in_buffer = spice_msg_in_frame_data(decoder->frame_msg, 
&data);
 cinfo->src->next_input_byte = data;
 }
 
@@ -49,68 +70,57 @@ static void mjpeg_src_term(struct jpeg_decompress_struct 
*cinfo)
 /* nothing */
 }
 
-G_GNUC_INTERNAL
-void stream_mjpeg_init(display_stream *st)
-{
-st->mjpeg_cinfo.err = jpeg_std_error(&st->mjpeg_jerr);
-jpeg_create_decompress(&st->mjpeg_cinfo);
-
-st->mjpeg_src.init_source = mjpeg_src_init;
-st->mjpeg_src.fill_input_buffer   = mjpeg_src_fill;
-st->mjpeg_src.skip_input_data = mjpeg_src_skip;
-st->mjpeg_src.resync_to_restart   = jpeg_resync_to_restart;
-st->mjpeg_src.term_source = mjpeg_src_term;
-st->mjpeg_cinfo.src   = &st->mjpeg_src;
-}
 
-G_GNUC_INTERNAL
-void stream_mjpeg_data(display_stream *st)
+/* -- VideoDecoder's public API -- */
+
+static uint8_t* mjpeg_decoder_decode_frame(VideoDecoder *video_decoder,
+   SpiceMsgIn *frame_msg)
 {
-gboolean back_compat = st->channel->priv->peer_hdr.major_version == 1;
+MJpegDecoder *decoder = (MJpegDecoder*)video_decoder;
+gboolean back_compat = 
decoder->base.stream->channel->priv->peer_hdr.major_version == 1;
 int width;
 int height;
 uint8_t *dest;
 uint8_t *lines[4];
 
-stream_get_dimensions(st, &width, &height);
-dest = g_malloc0(width * height * 4);
+decoder->frame_msg = frame_msg;
+stream_get_dimensions(decoder->base.stream, frame_msg, &width, &height);
+g_free(decoder->out_frame);
+dest = decoder->out_frame = g_malloc0(width * height * 4);
 
-g_free(st->out_frame);
-st->out_frame = dest;
-
-jpeg_read_header(&st->mjpeg_cinfo, 1);
+jpeg_read_header(&decoder->mjpeg_cinfo, 1);
 #ifdef JCS_EXTENSIONS
 // requires jpeg-turbo
 if (back_compat)
-st->mjpeg_cinfo.out_color_space = JCS_EXT_RGBX;
+decoder->mjpeg_cinfo.out_color_space = JCS_EXT_RGBX;
 else
-st->mjpeg_cinfo.out_color_space = JCS_EXT_BGRX;
+decoder->mjpeg_cinfo.out_color_space = JCS_EXT_BGRX;
 #else
 #warning "You should consider building with libjpeg-turbo"
-st->mjpeg_cinfo.out_color_space = JCS_RGB;
+decoder->mjpeg_cinfo.out_color_space = JCS_RGB;
 #endif
 
 #ifndef SPICE_QUALITY
-st->mjpeg_cinfo.dct_method = JDCT_IFAST;
-st->mjpeg_cinfo.do_fancy_upsampling = FALSE;
-st->mjpeg_cinfo.do_block_smoothing = FALSE;
-st->mjpeg_cinfo.dither_mode = JDITHER_ORDERED;
+decoder->mjpeg_cinfo.dct_method = JDCT_IFAST;
+decoder->mjpeg_cinfo.do_fancy_upsampling = FALSE;
+decoder->mjpeg_cinfo.do_block_smoothing = FALSE;
+decoder->mjpeg_cinfo.dither_mode = JDITHER_ORDERED;
 #endif
 // TODO: in theory should check cinfo.output_height match with our height
-jpeg_start_decompress(&st->mjpeg_cinfo);
+jpeg_start_decompress(&decoder->mjpeg_cinfo);
 /* rec_outbuf_height is the recommended size of the output buffer we
  * pass to libjpeg for optimum performance
  */
-if (st->mjpeg_cinfo.rec_outbuf_height > G_N_ELEMENTS(lines)) {
-jpeg_abort_decompress(&st->mjpeg_cinfo);
-g_return_if_reached();
+if (decoder->mjpeg_cinfo.rec_outbuf_height > G_N_ELEMENTS(lines)) {
+jpeg_abort_decompress(&decoder->mjpeg_cinfo);
+g_return_val_if_reached(NULL);
 }
 
-while (s

[Spice-devel] [spice v9 15/24] server: Add support for GStreamer 0.10

2016-01-18 Thread Francois Gouget
configure will use GStreamer 1.0 if present and fall back to
GStreamer 0.10 otherwise.

Signed-off-by: Francois Gouget 
---
 configure.ac   |  36 
 server/Makefile.am |   8 
 server/gstreamer-encoder.c | 102 +
 server/reds.c  |   2 +-
 server/video-encoder.h |   2 +-
 5 files changed, 123 insertions(+), 27 deletions(-)

diff --git a/configure.ac b/configure.ac
index a902e84..865d6e9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -70,28 +70,48 @@ dnl Check optional features
 SPICE_CHECK_SMARTCARD
 
 AC_ARG_ENABLE(gstreamer,
-  AS_HELP_STRING([--enable-gstreamer=@<:@auto/yes/no@:>@],
- [Enable GStreamer 1.0 support]),,
+  AS_HELP_STRING([--enable-gstreamer=@<:@auto/0.10/1.0/yes/no@:>@],
+ [Enable GStreamer support]),,
   [enable_gstreamer="auto"])
 
-if test "x$enable_gstreamer" != "xno"; then
+if test "x$enable_gstreamer" != "xno" && test "x$enable_gstreamer" != "x0.10"; 
then
 SPICE_CHECK_GSTREAMER(GSTREAMER_1_0, 1.0, [gstreamer-1.0 
gstreamer-base-1.0 gstreamer-app-1.0 gstreamer-video-1.0],
-[enable_gstreamer="yes"
+[enable_gstreamer="1.0"
  SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_1_0, [gst-plugins-base 
1.0], [appsrc videoconvert appsink])
  SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_1_0, [gstreamer-libav 
1.0], [avenc_mjpeg])
  SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_1_0, [gst-plugins-good 
1.0], [vp8enc])
  SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_1_0, [gst-plugins-ugly 
1.0], [x264enc])
  ],
- [if test "x$enable_gstreamer" = "xyes"; then
+ [if test "x$enable_gstreamer" = "x1.0"; then
   AC_MSG_ERROR([GStreamer 1.0 support requested but not found. You 
may set GSTREAMER_1_0_CFLAGS and GSTREAMER_1_0_LIBS to avoid the need to call 
pkg-config.])
   fi
 ])
 fi
 AM_CONDITIONAL(HAVE_GSTREAMER_1_0, test "x$have_gstreamer_1_0" = "xyes")
 
-if test x"$gstreamer_missing" != x; then
-SPICE_WARNING([The following GStreamer $enable_gstreamer tools/elements 
are missing:$gstreamer_missing. The GStreamer video encoder can be built but 
may not work.])
+if test "x$enable_gstreamer" != "xno" && test "x$enable_gstreamer" != "x1.0"; 
then
+SPICE_CHECK_GSTREAMER(GSTREAMER_0_10, 0.10, [gstreamer-0.10 
gstreamer-base-0.10 gstreamer-app-0.10 gstreamer-video-0.10],
+[enable_gstreamer="0.10"
+ SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_0_10, [gst-plugins-base 
0.10], [appsrc appsink])
+ SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_0_10, [gstreamer-ffmpeg 
0.10], [ffmpegcolorspace ffenc_mjpeg])
+ SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_0_10, [gst-plugins-bad 
0.10], [vp8enc])
+ SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_0_10, [gst-plugins-ugly 
0.10], [x264enc])
+],
+[if test "x$enable_gstreamer" = "x0.10"; then
+ AC_MSG_ERROR([GStreamer 0.10 support requested but not found. You 
may set GSTREAMER_0_10_CFLAGS and GSTREAMER_0_10_LIBS to avoid the need to call 
pkg-config.])
+ fi
+])
 fi
+AM_CONDITIONAL(HAVE_GSTREAMER_0_10, test "x$have_gstreamer_0_10" = "xyes")
+
+AS_IF([test "x$enable_gstreamer" = "xyes"],
+  [AC_MSG_ERROR("GStreamer support requested but not found")],
+  [test "x$enable_gstreamer" = "xauto"],
+  [enable_gstreamer="no"
+])
+AS_IF([test x"$missing_gstreamer_elements" = xyes],
+[SPICE_WARNING([The GStreamer video encoder can be built but may not 
work.])
+])
 
 AC_ARG_ENABLE([automated_tests],
   AS_HELP_STRING([--enable-automated-tests], [Enable automated 
tests using spicy-screenshot (part of spice--gtk)]),,
@@ -266,7 +286,7 @@ AC_MSG_NOTICE([
 
 LZ4 support:  ${enable_lz4}
 Smartcard:${have_smartcard}
-GStreamer 1.0:${have_gstreamer_1_0}
+GStreamer:${enable_gstreamer}
 SASL support: ${have_sasl}
 Automated tests:  ${enable_automated_tests}
 Manual:   ${have_asciidoc}
diff --git a/server/Makefile.am b/server/Makefile.am
index 9f33c93..d955a44 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -11,6 +11,7 @@ AM_CPPFLAGS = \
$(SASL_CFLAGS)  \
$(SLIRP_CFLAGS) \
$(SMARTCARD_CFLAGS) \
+   $(GSTREAMER_0_10_CFLAGS)\
$(GSTREAMER_1_0_CFLAGS) \
$(SPICE_PROTOCOL_CFLAGS)\
$(SSL_CFLAGS)   \
@@ -44,6 +45,7 @@ libserver_la_LIBADD = 
\
$(PIXMAN_LIBS)  \
$(SASL_LIBS)\
  

[Spice-devel] [PATCH] Change some functions to take RedsState arg

2016-01-18 Thread Frediano Ziglio
From: Jonathon Jongsma 

In preparation for getting rid of the global 'reds' variable, we need to
pass the RedsState variable to all functions where it is needed. For now
the callers just pass in the global reds variable.

Functions changed:
- reds_register_channel;
- reds_unregister_channel;
- reds_get_mouse_mode;
- reds_set_mouse_mode;
- reds_update_mouse_mode;
- reds_agent_remove;
- reds_find_channel;
- reds_mig_cleanup;
- reds_reset_vdp;
- reds_main_channel_connected;
- reds_client_disconnect;
- reds_disconnect;
- reds_mig_disconnect.

Acked-by: Frediano Ziglio 
---
 server/inputs-channel.c  |  10 ++---
 server/main-dispatcher.c |   2 +-
 server/red-dispatcher.c  |   4 +-
 server/reds.c| 104 +++
 server/reds.h|   8 ++--
 server/smartcard.c   |   2 +-
 server/sound.c   |   6 +--
 server/spicevmc.c|   4 +-
 8 files changed, 70 insertions(+), 70 deletions(-)

diff --git a/server/inputs-channel.c b/server/inputs-channel.c
index c21cab8..bb5b203 100644
--- a/server/inputs-channel.c
+++ b/server/inputs-channel.c
@@ -364,7 +364,7 @@ static int inputs_channel_handle_parsed(RedChannelClient 
*rcc, uint32_t size, ui
 red_channel_client_pipe_add_type(rcc, PIPE_ITEM_MOUSE_MOTION_ACK);
 icc->motion_count = 0;
 }
-if (mouse && reds_get_mouse_mode() == SPICE_MOUSE_MODE_SERVER) {
+if (mouse && reds_get_mouse_mode(reds) == SPICE_MOUSE_MODE_SERVER) {
 SpiceMouseInterface *sif;
 sif = SPICE_CONTAINEROF(mouse->base.sif, SpiceMouseInterface, 
base);
 sif->motion(mouse,
@@ -381,7 +381,7 @@ static int inputs_channel_handle_parsed(RedChannelClient 
*rcc, uint32_t size, ui
 red_channel_client_pipe_add_type(rcc, PIPE_ITEM_MOUSE_MOTION_ACK);
 icc->motion_count = 0;
 }
-if (reds_get_mouse_mode() != SPICE_MOUSE_MODE_CLIENT) {
+if (reds_get_mouse_mode(reds) != SPICE_MOUSE_MODE_CLIENT) {
 break;
 }
 spice_assert((reds_get_agent_mouse() && reds_has_vdagent()) || tablet);
@@ -407,7 +407,7 @@ static int inputs_channel_handle_parsed(RedChannelClient 
*rcc, uint32_t size, ui
 } else if (mouse_press->button == SPICE_MOUSE_BUTTON_DOWN) {
 dz = 1;
 }
-if (reds_get_mouse_mode() == SPICE_MOUSE_MODE_CLIENT) {
+if (reds_get_mouse_mode(reds) == SPICE_MOUSE_MODE_CLIENT) {
 if (reds_get_agent_mouse() && reds_has_vdagent()) {
 inputs_channel->mouse_state.buttons =
 
RED_MOUSE_BUTTON_STATE_TO_AGENT(mouse_press->buttons_state) |
@@ -429,7 +429,7 @@ static int inputs_channel_handle_parsed(RedChannelClient 
*rcc, uint32_t size, ui
 }
 case SPICE_MSGC_INPUTS_MOUSE_RELEASE: {
 SpiceMsgcMouseRelease *mouse_release = message;
-if (reds_get_mouse_mode() == SPICE_MOUSE_MODE_CLIENT) {
+if (reds_get_mouse_mode(reds) == SPICE_MOUSE_MODE_CLIENT) {
 if (reds_get_agent_mouse() && reds_has_vdagent()) {
 inputs_channel->mouse_state.buttons =
 
RED_MOUSE_BUTTON_STATE_TO_AGENT(mouse_release->buttons_state);
@@ -672,7 +672,7 @@ void inputs_init(void)
 red_channel_register_client_cbs(&g_inputs_channel->base, &client_cbs);
 
 red_channel_set_cap(&g_inputs_channel->base, 
SPICE_INPUTS_CAP_KEY_SCANCODE);
-reds_register_channel(&g_inputs_channel->base);
+reds_register_channel(reds, &g_inputs_channel->base);
 
 if (!(key_modifiers_timer = core->timer_add(core, key_modifiers_sender, 
NULL))) {
 spice_error("key modifiers timer create failed");
diff --git a/server/main-dispatcher.c b/server/main-dispatcher.c
index 2cb53ef..db87e05 100644
--- a/server/main-dispatcher.c
+++ b/server/main-dispatcher.c
@@ -136,7 +136,7 @@ static void main_dispatcher_handle_client_disconnect(void 
*opaque,
 MainDispatcherClientDisconnectMessage *msg = payload;
 
 spice_debug("client=%p", msg->client);
-reds_client_disconnect(msg->client);
+reds_client_disconnect(reds, msg->client);
 red_client_unref(msg->client);
 }
 
diff --git a/server/red-dispatcher.c b/server/red-dispatcher.c
index 0810798..dc958d9 100644
--- a/server/red-dispatcher.c
+++ b/server/red-dispatcher.c
@@ -1044,7 +1044,7 @@ void red_dispatcher_init(QXLInstance *qxl)
 client_cbs.migrate = red_dispatcher_cursor_migrate;
 red_channel_register_client_cbs(channel, &client_cbs);
 red_channel_set_data(channel, red_dispatcher);
-reds_register_channel(channel);
+reds_register_channel(reds, channel);
 
 channel = red_worker_get_display_channel(worker);
 client_cbs.connect = red_dispatcher_set_display_peer;
@@ -1055,7 +1055,7 @@ void red_dispatcher_init(QXLInstance *qxl)
 red_channel_set_cap(channel, SPICE_DISPLAY_CAP_MONITORS_CONFIG);
 red_channel_set_cap(channel, SPICE_DISPLAY_CAP_PREF_COMPRESSION);
 red_channel_set_cap(channel, SPICE_DISPLAY_

[Spice-devel] [client v9 19/24] spice-gtk: Optimize handling of the decoded frame buffer

2016-01-18 Thread Francois Gouget
The MJPEG decoder does not need a zero-filled buffer.

Signed-off-by: Francois Gouget 
---
 src/channel-display-mjpeg.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/channel-display-mjpeg.c b/src/channel-display-mjpeg.c
index 78e3d5a..6271cfb 100644
--- a/src/channel-display-mjpeg.c
+++ b/src/channel-display-mjpeg.c
@@ -39,6 +39,7 @@ typedef struct MJpegDecoder {
 /* -- Output frame data -- */
 
 uint8_t *out_frame;
+uint32_t out_size;
 } MJpegDecoder;
 
 
@@ -85,8 +86,12 @@ static uint8_t* mjpeg_decoder_decode_frame(VideoDecoder 
*video_decoder,
 
 decoder->frame_msg = frame_msg;
 stream_get_dimensions(decoder->base.stream, frame_msg, &width, &height);
-g_free(decoder->out_frame);
-dest = decoder->out_frame = g_malloc0(width * height * 4);
+if (decoder->out_size < width * height * 4) {
+g_free(decoder->out_frame);
+decoder->out_size = width * height * 4;
+decoder->out_frame = g_malloc(decoder->out_size);
+}
+dest = decoder->out_frame;
 
 jpeg_read_header(&decoder->mjpeg_cinfo, 1);
 #ifdef JCS_EXTENSIONS
-- 
2.6.4

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [spice v9 14/24] server: Respect the GStreamer encoder's valid bit rate range

2016-01-18 Thread Francois Gouget
Otherwise it may get wrapped to a much lower value than intended.

Signed-off-by: Francois Gouget 
---
 server/gstreamer-encoder.c | 65 +++---
 1 file changed, 62 insertions(+), 3 deletions(-)

diff --git a/server/gstreamer-encoder.c b/server/gstreamer-encoder.c
index 3c1e86e..bcf28e7 100644
--- a/server/gstreamer-encoder.c
+++ b/server/gstreamer-encoder.c
@@ -20,6 +20,8 @@
 #include 
 #endif
 
+#include 
+
 #include 
 #include 
 #include 
@@ -777,6 +779,65 @@ static gboolean create_pipeline(SpiceGstEncoder *encoder)
 return TRUE;
 }
 
+/* A helper for configure_pipeline() */
+static void set_gstenc_bitrate(SpiceGstEncoder *encoder)
+{
+GObjectClass *class = G_OBJECT_GET_CLASS(encoder->gstenc);
+GParamSpec *param = g_object_class_find_property(class, "bitrate");
+if (param == NULL) {
+param = g_object_class_find_property(class, "target-bitrate");
+}
+if (param) {
+uint64_t gst_bit_rate = encoder->video_bit_rate;
+if (strstr(g_param_spec_get_blurb(param), "kbit")) {
+gst_bit_rate = gst_bit_rate / 1024;
+}
+switch (param->value_type) {
+case G_TYPE_ULONG: {
+GParamSpecULong *range = G_PARAM_SPEC_ULONG(param);
+gst_bit_rate = MAX(range->minimum, MIN(range->maximum, 
gst_bit_rate));
+break;
+}
+case G_TYPE_LONG: {
+GParamSpecLong *range = G_PARAM_SPEC_LONG(param);
+gst_bit_rate = MAX(range->minimum, MIN(range->maximum, 
gst_bit_rate));
+break;
+}
+case G_TYPE_UINT: {
+GParamSpecUInt *range = G_PARAM_SPEC_UINT(param);
+gst_bit_rate = MAX(range->minimum, MIN(range->maximum, 
gst_bit_rate));
+break;
+}
+case G_TYPE_INT: {
+GParamSpecInt *range = G_PARAM_SPEC_INT(param);
+gst_bit_rate = MAX(range->minimum, MIN(range->maximum, 
gst_bit_rate));
+break;
+}
+case G_TYPE_UINT64: {
+GParamSpecUInt64 *range = G_PARAM_SPEC_UINT64(param);
+gst_bit_rate = MAX(range->minimum, MIN(range->maximum, 
gst_bit_rate));
+break;
+}
+case G_TYPE_INT64: {
+GParamSpecInt64 *range = G_PARAM_SPEC_INT64(param);
+gst_bit_rate = MAX(range->minimum, MIN(range->maximum, 
gst_bit_rate));
+break;
+}
+default:
+spice_debug("the %s property has an unsupported type %zu",
+g_param_spec_get_name(param), param->value_type);
+}
+spice_debug("setting the GStreamer %s to %"PRIu64,
+g_param_spec_get_name(param), gst_bit_rate);
+g_object_set(G_OBJECT(encoder->gstenc),
+ g_param_spec_get_name(param), gst_bit_rate,
+ NULL);
+} else {
+spice_printerr("Could not find the bit rate property for %s",
+   get_gst_codec_name(encoder));
+}
+}
+
 /* A helper for spice_gst_encoder_encode_frame() */
 static gboolean configure_pipeline(SpiceGstEncoder *encoder,
const SpiceBitmap *bitmap)
@@ -786,10 +847,10 @@ static gboolean configure_pipeline(SpiceGstEncoder 
*encoder,
 }
 
 /* Configure the encoder bitrate, frame latency, etc. */
+set_gstenc_bitrate(encoder);
 switch (encoder->base.codec_type) {
 case SPICE_VIDEO_CODEC_TYPE_MJPEG:
 g_object_set(G_OBJECT(encoder->gstenc),
- "bitrate", encoder->video_bit_rate,
  "max-threads", 1, /* zero-frame latency */
  NULL);
 
@@ -807,7 +868,6 @@ static gboolean configure_pipeline(SpiceGstEncoder *encoder,
 g_object_set(G_OBJECT(encoder->gstenc),
  "resize-allowed", TRUE, /* for very low bit rates */
  "min-quantizer", 10, /* seems virtually lossless */
- "target-bitrate", encoder->video_bit_rate,
  "end-usage", 1, /* CBR */
  "lag-in-frames", 0, /* zero-frame latency */
  "error-resilient", 1, /* for client frame drops */
@@ -818,7 +878,6 @@ static gboolean configure_pipeline(SpiceGstEncoder *encoder,
 }
 case SPICE_VIDEO_CODEC_TYPE_H264:
 g_object_set(G_OBJECT(encoder->gstenc),
- "bitrate", encoder->video_bit_rate / 1024,
  "qp-min", 15, /* virtually lossless */
  "byte-stream", TRUE,
  "aud", FALSE,
-- 
2.6.4

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [spice v9 13/24] server: Cap the VP8 and h264 video quality to limit the bit rate

2016-01-18 Thread Francois Gouget
This prevents the bit rate from going insanely high on fast networks
for no visible video quality improvement.

Signed-off-by: Francois Gouget 
---
 server/gstreamer-encoder.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/server/gstreamer-encoder.c b/server/gstreamer-encoder.c
index bf60773..3c1e86e 100644
--- a/server/gstreamer-encoder.c
+++ b/server/gstreamer-encoder.c
@@ -806,6 +806,7 @@ static gboolean configure_pipeline(SpiceGstEncoder *encoder,
 #endif
 g_object_set(G_OBJECT(encoder->gstenc),
  "resize-allowed", TRUE, /* for very low bit rates */
+ "min-quantizer", 10, /* seems virtually lossless */
  "target-bitrate", encoder->video_bit_rate,
  "end-usage", 1, /* CBR */
  "lag-in-frames", 0, /* zero-frame latency */
@@ -818,6 +819,7 @@ static gboolean configure_pipeline(SpiceGstEncoder *encoder,
 case SPICE_VIDEO_CODEC_TYPE_H264:
 g_object_set(G_OBJECT(encoder->gstenc),
  "bitrate", encoder->video_bit_rate / 1024,
+ "qp-min", 15, /* virtually lossless */
  "byte-stream", TRUE,
  "aud", FALSE,
  "tune", 4, /* zero-frame latency */
-- 
2.6.4

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [spice v9 12/24] server: Give up after a while if GStreamer cannot handle the video

2016-01-18 Thread Francois Gouget
This typically happens when sending very small frames (less than
16 pixels in one dimension) to the x264enc encoder.
This avoids repeatedly wasting time rebuilding the pipeline.

Signed-off-by: Francois Gouget 
---
 server/gstreamer-encoder.c | 46 +-
 1 file changed, 37 insertions(+), 9 deletions(-)

diff --git a/server/gstreamer-encoder.c b/server/gstreamer-encoder.c
index 44072f0..bf60773 100644
--- a/server/gstreamer-encoder.c
+++ b/server/gstreamer-encoder.c
@@ -74,6 +74,9 @@ typedef struct SpiceGstEncoder {
 SpiceFormatForGStreamer *format;
 SpiceBitmapFmt spice_format;
 
+/* Number of consecutive frame encoding errors. */
+uint32_t errors;
+
 /* -- GStreamer pipeline -- */
 
 /* Pointers to the GStreamer pipeline elements. If pipeline is NULL the
@@ -730,24 +733,27 @@ static void set_appsrc_caps(SpiceGstEncoder *encoder)
 g_object_set(G_OBJECT(encoder->appsrc), "caps", encoder->src_caps, NULL);
 }
 
-/* A helper for spice_gst_encoder_encode_frame() */
-static gboolean create_pipeline(SpiceGstEncoder *encoder)
+static const gchar* get_gst_codec_name(SpiceGstEncoder *encoder)
 {
-const gchar* gstenc_name;
 switch (encoder->base.codec_type)
 {
 case SPICE_VIDEO_CODEC_TYPE_MJPEG:
-gstenc_name = "avenc_mjpeg";
-break;
+return "avenc_mjpeg";
 case SPICE_VIDEO_CODEC_TYPE_VP8:
-gstenc_name = "vp8enc";
-break;
+return "vp8enc";
 case SPICE_VIDEO_CODEC_TYPE_H264:
-gstenc_name = "x264enc";
-break;
+return "x264enc";
 default:
 /* gstreamer_encoder_new() should have rejected this codec type */
 spice_warning("unsupported codec type %d", encoder->base.codec_type);
+return NULL;
+}
+}
+
+static gboolean create_pipeline(SpiceGstEncoder *encoder)
+{
+const gchar* gstenc_name = get_gst_codec_name(encoder);
+if (!gstenc_name) {
 return FALSE;
 }
 
@@ -1148,6 +1154,7 @@ static int spice_gst_encoder_encode_frame(VideoEncoder 
*video_encoder,
 encoder->format = map_format(bitmap->format);
 if (!encoder->format) {
 spice_debug("unable to map format type %d", bitmap->format);
+encoder->errors = 4;
 return VIDEO_ENCODER_FRAME_UNSUPPORTED;
 }
 encoder->spice_format = bitmap->format;
@@ -1163,6 +1170,19 @@ static int spice_gst_encoder_encode_frame(VideoEncoder 
*video_encoder,
 } else if (encoder->pipeline) {
 reconfigure_pipeline(encoder);
 }
+encoder->errors = 0;
+} else if (encoder->errors >= 3) {
+/* The pipeline keeps failing to handle the frames we send it, which is
+ * usually because they are too small (mouse pointer-sized).
+ * So give up until something changes.
+ */
+if (encoder->errors == 3) {
+spice_debug("%s cannot compress %dx%d:%dbpp frames",
+get_gst_codec_name(encoder), encoder->width,
+encoder->height, encoder->format->bpp);
+encoder->errors++;
+}
+return VIDEO_ENCODER_FRAME_UNSUPPORTED;
 }
 
 if (rate_control_is_active(encoder) &&
@@ -1174,12 +1194,20 @@ static int spice_gst_encoder_encode_frame(VideoEncoder 
*video_encoder,
 
 if (!is_pipeline_configured(encoder) &&
 !configure_pipeline(encoder, bitmap)) {
+encoder->errors++;
 return VIDEO_ENCODER_FRAME_UNSUPPORTED;
 }
 
 int rc = push_raw_frame(encoder, bitmap, src, top_down);
 if (rc == VIDEO_ENCODER_FRAME_ENCODE_DONE) {
 rc = pull_compressed_buffer(encoder, video_buffer);
+if (rc != VIDEO_ENCODER_FRAME_ENCODE_DONE) {
+/* The input buffer will be stuck in the pipeline, preventing
+ * later ones from being processed. So reset the pipeline.
+ */
+free_pipeline(encoder);
+encoder->errors++;
+}
 #ifdef DO_ZERO_COPY
 /* GStreamer should have released the source frame buffer by now */
 if (encoder->needs_bitmap) {
-- 
2.6.4

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [spice v9 09/24] server: Add h264 support to the GStreamer video encoder

2016-01-18 Thread Francois Gouget
Signed-off-by: Francois Gouget 
---
 server/gstreamer-encoder.c | 17 -
 server/reds.c  |  2 ++
 server/video-encoder.h |  2 +-
 3 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/server/gstreamer-encoder.c b/server/gstreamer-encoder.c
index 11be91b..fe07852 100644
--- a/server/gstreamer-encoder.c
+++ b/server/gstreamer-encoder.c
@@ -231,6 +231,9 @@ static gboolean create_pipeline(SpiceGstEncoder *encoder)
 case SPICE_VIDEO_CODEC_TYPE_VP8:
 gstenc_name = "vp8enc";
 break;
+case SPICE_VIDEO_CODEC_TYPE_H264:
+gstenc_name = "x264enc";
+break;
 default:
 /* gstreamer_encoder_new() should have rejected this codec type */
 spice_warning("unsupported codec type %d", encoder->base.codec_type);
@@ -296,6 +299,17 @@ static gboolean configure_pipeline(SpiceGstEncoder 
*encoder,
  NULL);
 break;
 }
+case SPICE_VIDEO_CODEC_TYPE_H264:
+g_object_set(G_OBJECT(encoder->gstenc),
+ "bitrate", encoder->bit_rate / 1024,
+ "byte-stream", TRUE,
+ "aud", FALSE,
+ "tune", 4, /* zero-frame latency */
+ "sliced-threads", TRUE, /* zero-frame latency */
+ "speed-preset", 1, /* ultrafast */
+ "intra-refresh", TRUE, /* uniform compressed frame sizes 
*/
+ NULL);
+break;
 default:
 /* gstreamer_encoder_new() should have rejected this codec type */
 spice_warning("unknown encoder type %d", encoder->base.codec_type);
@@ -700,7 +714,8 @@ VideoEncoder *gstreamer_encoder_new(SpiceVideoCodecType 
codec_type,
 void *cbs_opaque)
 {
 spice_return_val_if_fail(codec_type == SPICE_VIDEO_CODEC_TYPE_MJPEG ||
- codec_type == SPICE_VIDEO_CODEC_TYPE_VP8, NULL);
+ codec_type == SPICE_VIDEO_CODEC_TYPE_VP8 ||
+ codec_type == SPICE_VIDEO_CODEC_TYPE_H264, NULL);
 
 GError *err = NULL;
 if (!gst_init_check(NULL, NULL, &err)) {
diff --git a/server/reds.c b/server/reds.c
index a5f600c..18d8bb1 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -3494,12 +3494,14 @@ static new_video_encoder_t video_encoder_procs[] = {
 static const EnumNames video_codec_names[] = {
 {SPICE_VIDEO_CODEC_TYPE_MJPEG, "mjpeg"},
 {SPICE_VIDEO_CODEC_TYPE_VP8, "vp8"},
+{SPICE_VIDEO_CODEC_TYPE_H264, "h264"},
 {0, NULL},
 };
 
 static const EnumNames video_cap_names[] = {
 {SPICE_DISPLAY_CAP_CODEC_MJPEG, "mjpeg"},
 {SPICE_DISPLAY_CAP_CODEC_VP8, "vp8"},
+{SPICE_DISPLAY_CAP_CODEC_H264, "h264"},
 {0, NULL},
 };
 
diff --git a/server/video-encoder.h b/server/video-encoder.h
index db520eb..edfb392 100644
--- a/server/video-encoder.h
+++ b/server/video-encoder.h
@@ -193,6 +193,6 @@ VideoEncoder* gstreamer_encoder_new(SpiceVideoCodecType 
codec_type,
 void *cbs_opaque);
 #endif
 
-#define VIDEO_ENCODER_DEFAULT_PREFERENCE 
"spice:mjpeg;gstreamer:mjpeg;gstreamer:vp8"
+#define VIDEO_ENCODER_DEFAULT_PREFERENCE 
"spice:mjpeg;gstreamer:mjpeg;gstreamer:h264;gstreamer:vp8"
 
 #endif
-- 
2.6.4

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [spice v9 08/24] server: Avoid copying the input frame in the GStreamer encoder

2016-01-18 Thread Francois Gouget
This relies on the GStreamer buffer's lifetime being short enough which
it is because:
 - We encode frames one by one.
 - For all encoders but MJPEG, the first element of the pipeline will
   convert the bitmap to another image format which entails copying it.
   So by the time the encoder starts its work, this buffer will not be
   needed anymore.
 - The MJPEG encoder does not perform inter-frame compression and thus
   does not need to keep hold of this buffer once it has processed it.

Note that we can only avoid copies for the first 1 Mpixels or so.
That's because Spice splits larger frames into more chunks than we can
fit GstMemory fragments in a GStreamer buffer. So if there are more
pixels we will avoid copies for the first 3840 KB and copy the rest.

Signed-off-by: Francois Gouget 
---
 server/gstreamer-encoder.c | 171 -
 1 file changed, 152 insertions(+), 19 deletions(-)

diff --git a/server/gstreamer-encoder.c b/server/gstreamer-encoder.c
index d1a1d27..11be91b 100644
--- a/server/gstreamer-encoder.c
+++ b/server/gstreamer-encoder.c
@@ -30,6 +30,8 @@
 
 #define SPICE_GST_DEFAULT_FPS 30
 
+#define DO_ZERO_COPY
+
 
 typedef struct {
 SpiceBitmapFmt spice_format;
@@ -73,6 +75,11 @@ typedef struct SpiceGstEncoder {
 /* If src_caps is NULL the pipeline has not been configured yet. */
 GstCaps *src_caps;
 
+#ifdef DO_ZERO_COPY
+/* Set to TRUE until GStreamer no longer needs the raw bitmap buffer. */
+gboolean needs_bitmap;
+#endif
+
 /* The frame counter for GStreamer buffers */
 uint32_t frame;
 
@@ -336,6 +343,17 @@ static void reconfigure_pipeline(SpiceGstEncoder *encoder)
 }
 }
 
+static int is_chunk_padded(const SpiceBitmap *bitmap, uint32_t index)
+{
+SpiceChunks *chunks = bitmap->data;
+if (chunks->chunk[index].len % bitmap->stride != 0) {
+spice_warning("chunk %d/%d is padded",
+  index, chunks->num_chunks);
+return TRUE;
+}
+return FALSE;
+}
+
 /* A helper for push_raw_frame() */
 static inline int line_copy(SpiceGstEncoder *encoder, const SpiceBitmap 
*bitmap,
 uint32_t chunk_offset, uint32_t stream_stride,
@@ -349,10 +367,7 @@ static inline int line_copy(SpiceGstEncoder *encoder, 
const SpiceBitmap *bitmap,
   * time around.
   */
  while (chunk_offset >= chunks->chunk[chunk_index].len) {
- /* Make sure that the chunk is not padded */
- if (chunks->chunk[chunk_index].len % bitmap->stride != 0) {
- spice_warning("chunk %d/%d is padded, cannot copy line %d/%d",
-   chunk_index, chunks->num_chunks, l, height);
+ if (is_chunk_padded(bitmap, chunk_index)) {
  return FALSE;
  }
  chunk_offset -= chunks->chunk[chunk_index].len;
@@ -369,18 +384,83 @@ static inline int line_copy(SpiceGstEncoder *encoder, 
const SpiceBitmap *bitmap,
  return TRUE;
 }
 
+#ifdef DO_ZERO_COPY
+/* A helper for zero_copy() */
+static void unref_bitmap(gpointer mem)
+{
+SpiceGstEncoder *encoder = (SpiceGstEncoder*)mem;
+encoder->needs_bitmap = FALSE;
+}
+
+/* A helper for push_raw_frame() */
+static inline int zero_copy(SpiceGstEncoder *encoder, const SpiceBitmap 
*bitmap,
+GstBuffer *buffer, uint32_t *chunk_index,
+uint32_t *chunk_offset, uint32_t *len)
+{
+/* We cannot control the lifetime of the bitmap but we can wrap it in
+ * the buffer anyway because:
+ * - Before returning from gst_encoder_encode_frame() we wait for the
+ *   pipeline to have converted this frame into a compressed buffer.
+ *   So it has to have gone through the frame at least once.
+ * - For all encoders but MJPEG, the first element of the pipeline will
+ *   convert the bitmap to another image format which entails copying
+ *   it. So by the time the encoder starts its work, this buffer will
+ *   not be needed anymore.
+ * - The MJPEG encoder does not perform inter-frame compression and thus
+ *   does not need to keep hold of this buffer once it has processed it.
+ * encoder->needs_bitmap lets us verify that these conditions still hold
+ * true through an assert.
+ */
+SpiceChunks *chunks = bitmap->data;
+while (*chunk_offset >= chunks->chunk[*chunk_index].len) {
+if (is_chunk_padded(bitmap, *chunk_index)) {
+return FALSE;
+}
+*chunk_offset -= chunks->chunk[*chunk_index].len;
+(*chunk_index)++;
+}
+
+int max_mem = gst_buffer_get_max_memory();
+if (chunks->num_chunks - *chunk_index > max_mem) {
+/* There are more chunks than we can fit memory objects in a
+ * buffer. This will cause the buffer to merge memory objects to
+ * fit the extra chunks, which means doing wasteful memory copies.
+ * So use the zero-copy approach for the first max

[Spice-devel] [spice v9 10/24] server: Shape the bit rate of the GStreamer codecs output

2016-01-18 Thread Francois Gouget
The GStreamer codecs don't follow the specified bit rate very closely:
they can decide to exceed it for ten seconds or more if they consider
the scene deserves it. Such long bursts are enough to cause network
congestion, resulting in many lost frames which cause significant
display corruption.
So the GStreamer video encoder now uses a short 300ms virtual buffer
to shape the compressed video output and ensure we don't exceed the
target bit rate for any significant length of time.
It could instead rely on the network feedback (when available) to lower
the bit rate. However frequent GStreamer bit rate changes lower the
overall compression level and also result in a lower average bit rate,
both of which result in lower video quality.
The GStreamer video encoder also keeps track of the encoded frame size
so it can gather statistics and call update_client_playback_delay()
with accurate information and also annotate the client report debug
traces with the corresponding bit rate information.

Signed-off-by: Francois Gouget 
---
 server/gstreamer-encoder.c | 291 +++--
 1 file changed, 284 insertions(+), 7 deletions(-)

diff --git a/server/gstreamer-encoder.c b/server/gstreamer-encoder.c
index fe07852..d384135 100644
--- a/server/gstreamer-encoder.c
+++ b/server/gstreamer-encoder.c
@@ -26,6 +26,7 @@
 
 #include "red-common.h"
 #include "video-encoder.h"
+#include "utils.h"
 
 
 #define SPICE_GST_DEFAULT_FPS 30
@@ -45,6 +46,11 @@ typedef struct SpiceGstVideoBuffer {
 GstMapInfo map;
 } SpiceGstVideoBuffer;
 
+typedef struct {
+uint32_t mm_time;
+uint32_t size;
+} SpiceGstFrameInformation;
+
 typedef struct SpiceGstEncoder {
 VideoEncoder base;
 
@@ -83,6 +89,45 @@ typedef struct SpiceGstEncoder {
 /* The frame counter for GStreamer buffers */
 uint32_t frame;
 
+
+/* -- Encoded frame statistics -- */
+
+/* Should be >= than FRAME_STATISTICS_COUNT. This is also used to annotate
+ * the client report debug traces with bit rate information.
+ */
+#   define SPICE_GST_HISTORY_SIZE 60
+
+/* A circular buffer containing the past encoded frames information. */
+SpiceGstFrameInformation history[SPICE_GST_HISTORY_SIZE];
+
+/* The indices of the oldest and newest frames in the history buffer. */
+uint32_t history_first;
+uint32_t history_last;
+
+/* How many frames to take into account when computing the effective
+ * bit rate, average frame size, etc. This should be large enough so the
+ * I and P frames average out, and short enough for it to reflect the
+ * current situation.
+ */
+#   define SPICE_GST_FRAME_STATISTICS_COUNT 21
+
+/* The index of the oldest frame taken into account for the statistics. */
+uint32_t stat_first;
+
+/* Used to compute the average frame size. */
+uint64_t stat_sum;
+
+/* Tracks the maximum frame size. */
+uint32_t stat_maximum;
+
+
+/* -- Encoder bit rate control --
+ *
+ * GStreamer encoders don't follow the specified bit rate very
+ * closely. These fields are used to ensure we don't exceed the desired
+ * stream bit rate, regardless of the GStreamer encoder's output.
+ */
+
 /* The bit rate target for the outgoing network stream. (bits per second) 
*/
 uint64_t bit_rate;
 
@@ -91,6 +136,27 @@ typedef struct SpiceGstEncoder {
 
 /* The default bit rate */
 #   define SPICE_GST_DEFAULT_BITRATE (8 * 1024 * 1024)
+
+/* The bit rate control is performed using a virtual buffer to allow short
+ * term variations: bursts are allowed until the virtual buffer is full.
+ * Then frames are dropped to limit the bit rate. VBUFFER_SIZE defines the
+ * size of the virtual buffer in milliseconds worth of data.
+ */
+#   define SPICE_GST_VBUFFER_SIZE 300
+
+int32_t vbuffer_size;
+int32_t vbuffer_free;
+
+/* When dropping frames, this is set to the minimum mm_time of the next
+ * frame to encode. Otherwise set to zero.
+ */
+uint32_t next_frame;
+
+/* Defines the minimum allowed fps. */
+#   define SPICE_GST_MAX_PERIOD (NSEC_PER_SEC / 3)
+
+/* How big of a margin to take to cover for latency jitter. */
+#   define SPICE_GST_LATENCY_MARGIN 0.1
 } SpiceGstEncoder;
 
 
@@ -127,6 +193,18 @@ static uint32_t get_source_fps(SpiceGstEncoder *encoder)
 encoder->cbs.get_source_fps(encoder->cbs_opaque) : 
SPICE_GST_DEFAULT_FPS;
 }
 
+static uint32_t get_network_latency(SpiceGstEncoder *encoder)
+{
+/* Assume that the network latency is symmetric */
+return encoder->cbs.get_roundtrip_ms ?
+encoder->cbs.get_roundtrip_ms(encoder->cbs_opaque) / 2 : 0;
+}
+
+static inline int rate_control_is_active(SpiceGstEncoder* encoder)
+{
+return encoder->cbs.get_roundtrip_ms != NULL;
+}
+
 static inline int is_pipeline_configured(SpiceGstEncoder *encoder)
 {
 return encoder->src_caps != NULL;
@@ -148,6 +226,182 @@ static void free_pipeline(SpiceGs

[Spice-devel] [spice v9 11/24] server: Adjust the GStreamer encoder bit rate to the network

2016-01-18 Thread Francois Gouget
The video encoder uses the client reports and/or notifications of
server frame drops as its feedback mechanisms. In particular it keeps
track of the maximum video margin and reduces the bit rate whenever the
margin goes below certain thresholds or decreases too sharply.
It uses these to figure out the lowest bit rate that causes negative
feedback, and the highest bit rate that allows a return to positive
feedbacks. It then works to narrow this range and settles on the lower
end once the spread has gone below a given threshold.
All the while it monitors the effective bit rate to ensure the target
bit rate does not grow significantly beyond what the GStreamer encoder
will produce: this avoids target bit rate 'bubbles' which would
invariably be followed by a bit rate crash with accompanying frame loss.
As soon as the network feedback indicates a significant degradation the
bit rate is lowered to minimize the risk of frame loss and/or long
freezes.
It also relies on the existing shaping of the GStreamer output bit rate
to minimize the pipeline reconfigurations.

Signed-off-by: Francois Gouget 
---
 server/gstreamer-encoder.c | 407 ++---
 1 file changed, 383 insertions(+), 24 deletions(-)

diff --git a/server/gstreamer-encoder.c b/server/gstreamer-encoder.c
index d384135..44072f0 100644
--- a/server/gstreamer-encoder.c
+++ b/server/gstreamer-encoder.c
@@ -51,6 +51,12 @@ typedef struct {
 uint32_t size;
 } SpiceGstFrameInformation;
 
+typedef enum SpiceGstBitRateStatus {
+SPICE_GST_BITRATE_DECREASING,
+SPICE_GST_BITRATE_INCREASING,
+SPICE_GST_BITRATE_STABLE,
+} SpiceGstBitRateStatus;
+
 typedef struct SpiceGstEncoder {
 VideoEncoder base;
 
@@ -89,6 +95,12 @@ typedef struct SpiceGstEncoder {
 /* The frame counter for GStreamer buffers */
 uint32_t frame;
 
+/* The GStreamer bit rate. */
+uint64_t video_bit_rate;
+
+/* Don't bother changing the GStreamer bit rate if close enough. */
+#   define SPICE_GST_VIDEO_BITRATE_MARGIN 0.05
+
 
 /* -- Encoded frame statistics -- */
 
@@ -123,7 +135,7 @@ typedef struct SpiceGstEncoder {
 
 /* -- Encoder bit rate control --
  *
- * GStreamer encoders don't follow the specified bit rate very
+ * GStreamer encoders don't follow the specified video_bit_rate very
  * closely. These fields are used to ensure we don't exceed the desired
  * stream bit rate, regardless of the GStreamer encoder's output.
  */
@@ -131,7 +143,7 @@ typedef struct SpiceGstEncoder {
 /* The bit rate target for the outgoing network stream. (bits per second) 
*/
 uint64_t bit_rate;
 
-/* The minimum bit rate */
+/* The minimum bit rate / bit rate increment. */
 #   define SPICE_GST_MIN_BITRATE (128 * 1024)
 
 /* The default bit rate */
@@ -157,6 +169,89 @@ typedef struct SpiceGstEncoder {
 
 /* How big of a margin to take to cover for latency jitter. */
 #   define SPICE_GST_LATENCY_MARGIN 0.1
+
+
+/* -- Network bit rate control --
+ *
+ * State information for figuring out the optimal bit rate for the current
+ * network conditions.
+ */
+
+/* The mm_time of the last bit rate change. */
+uint32_t last_change;
+
+/* How much to reduce the bit rate in case of network congestion. */
+#   define SPICE_GST_BITRATE_CUT 2
+#   define SPICE_GST_BITRATE_REDUCE (4.0 / 3.0)
+
+/* Never increase the bit rate by more than this amount (bits per second). 
*/
+#   define SPICE_GST_BITRATE_MAX_STEP (1024 * 1024)
+
+/* The maximum bit rate that one can maybe use without causing network
+ * congestion.
+ */
+uint64_t max_bit_rate;
+
+/* The last bit rate that let us recover from network congestion. */
+uint64_t min_bit_rate;
+
+/* Defines when the spread between max_bit_rate and min_bit_rate has been
+ * narrowed down enough. Note that this value should be large enough for
+ * min_bit_rate to allow recovery from network congestion in a reasonable
+ * time frame, and to absorb transient traffic spikes (potentially from
+ * other sources).
+ * This is also used as a multiplier for the video_bit_rate so it does not
+ * have to be changed too often.
+ */
+#   define SPICE_GST_BITRATE_MARGIN SPICE_GST_BITRATE_REDUCE
+
+/* Whether the bit rate was last decreased, increased or kept stable. */
+SpiceGstBitRateStatus status;
+
+/* The network bit rate control uses an AIMD scheme (Additive Increase,
+ * Multiplicative Decrease). The increment step depends on the spread
+ * between the minimum and maximum bit rates.
+ */
+uint64_t bit_rate_step;
+
+/* How often to increase the bit rate. */
+uint32_t increase_interval;
+
+#   define SPICE_GST_BITRATE_UP_INTERVAL (MSEC_PER_SEC * 2)
+#   define SPICE_GST_BITRATE_UP_CLIENT_STABLE (MSEC_PER_SEC * 60 * 2)
+#   define SPICE_GST_BITRATE_UP_SERVER_STABLE (MSEC_PER_SEC * 3600 * 4)
+#   def

[Spice-devel] [spice v9 07/24] server: Let the video encoder manage the compressed buffer

2016-01-18 Thread Francois Gouget
This way the video encoder is not forced to use malloc()/free().
This also allows more flexibility in how the video encoder manages the
buffer which allows for a zero-copy implementation in both video
encoders.

Signed-off-by: Francois Gouget 
---
 server/dcc-send.c  | 24 +++--
 server/dcc.c   |  5 ---
 server/dcc.h   |  3 --
 server/gstreamer-encoder.c | 55 ++---
 server/mjpeg-encoder.c | 87 +-
 server/video-encoder.h | 28 +++
 6 files changed, 124 insertions(+), 78 deletions(-)

diff --git a/server/dcc-send.c b/server/dcc-send.c
index e13f04f..e360018 100644
--- a/server/dcc-send.c
+++ b/server/dcc-send.c
@@ -1649,6 +1649,12 @@ static void 
red_lossy_marshall_qxl_draw_text(RedChannelClient *rcc,
 }
 }
 
+static void red_release_video_encoder_buffer(uint8_t *data, void *opaque)
+{
+VideoBuffer *buffer = (VideoBuffer*)opaque;
+buffer->free(buffer);
+}
+
 static int red_marshall_stream_data(RedChannelClient *rcc,
 SpiceMarshaller *base_marshaller, Drawable 
*drawable)
 {
@@ -1657,7 +1663,7 @@ static int red_marshall_stream_data(RedChannelClient *rcc,
 Stream *stream = drawable->stream;
 SpiceImage *image;
 uint32_t frame_mm_time;
-int n;
+VideoBuffer *outbuf;
 int width, height;
 int ret;
 
@@ -1689,7 +1695,6 @@ static int red_marshall_stream_data(RedChannelClient *rcc,
 
 StreamAgent *agent = &dcc->stream_agents[get_stream_id(display, stream)];
 uint64_t time_now = spice_get_monotonic_time_ns();
-size_t outbuf_size;
 
 if (!dcc->use_video_encoder_rate_control) {
 if (time_now - agent->last_send_time < (1000 * 1000 * 1000) / 
agent->fps) {
@@ -1705,13 +1710,11 @@ static int red_marshall_stream_data(RedChannelClient 
*rcc,
 frame_mm_time =  drawable->red_drawable->mm_time ?
 drawable->red_drawable->mm_time :
 reds_get_mm_time();
-outbuf_size = dcc->send_data.stream_outbuf_size;
 ret = agent->video_encoder->encode_frame(agent->video_encoder,
  &image->u.bitmap, width, height,
  
&drawable->red_drawable->u.copy.src_area,
  stream->top_down, frame_mm_time,
- &dcc->send_data.stream_outbuf,
- &outbuf_size, &n);
+ &outbuf);
 switch (ret) {
 case VIDEO_ENCODER_FRAME_DROP:
 spice_assert(dcc->use_video_encoder_rate_control);
@@ -1727,7 +1730,6 @@ static int red_marshall_stream_data(RedChannelClient *rcc,
 spice_error("bad return value (%d) from VideoEncoder::encode_frame", 
ret);
 return FALSE;
 }
-dcc->send_data.stream_outbuf_size = outbuf_size;
 
 if (!drawable->sized_stream) {
 SpiceMsgDisplayStreamData stream_data;
@@ -1736,7 +1738,7 @@ static int red_marshall_stream_data(RedChannelClient *rcc,
 
 stream_data.base.id = get_stream_id(display, stream);
 stream_data.base.multi_media_time = frame_mm_time;
-stream_data.data_size = n;
+stream_data.data_size = outbuf->size;
 
 spice_marshall_msg_display_stream_data(base_marshaller, &stream_data);
 } else {
@@ -1746,7 +1748,7 @@ static int red_marshall_stream_data(RedChannelClient *rcc,
 
 stream_data.base.id = get_stream_id(display, stream);
 stream_data.base.multi_media_time = frame_mm_time;
-stream_data.data_size = n;
+stream_data.data_size = outbuf->size;
 stream_data.width = width;
 stream_data.height = height;
 stream_data.dest = drawable->red_drawable->bbox;
@@ -1755,12 +1757,12 @@ static int red_marshall_stream_data(RedChannelClient 
*rcc,
 rect_debug(&stream_data.dest);
 spice_marshall_msg_display_stream_data_sized(base_marshaller, 
&stream_data);
 }
-spice_marshaller_add_ref(base_marshaller,
- dcc->send_data.stream_outbuf, n);
+spice_marshaller_add_ref_full(base_marshaller, outbuf->data, outbuf->size,
+  &red_release_video_encoder_buffer, outbuf);
 agent->last_send_time = time_now;
 #ifdef STREAM_STATS
 agent->stats.num_frames_sent++;
-agent->stats.size_sent += n;
+agent->stats.size_sent += outbuf->size;
 agent->stats.end = frame_mm_time;
 #endif
 
diff --git a/server/dcc.c b/server/dcc.c
index ed4598f..26fc754 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -384,10 +384,6 @@ DisplayChannelClient *dcc_new(DisplayChannel *display,
 // TODO: tune quality according to bandwidth
 dcc->jpeg_quality = 85;
 
-size_t stream_buf_size;
-stream_buf_size = 32*1024;
-dcc->send_data.stream_outbuf = spice_malloc(stream_buf_size);
-dcc->send_data.stream_out

[Spice-devel] [spice v9 06/24] server: Add VP8 support to the GStreamer video encoder

2016-01-18 Thread Francois Gouget
Signed-off-by: Francois Gouget 
---
 configure.ac   |  4 +++
 server/gstreamer-encoder.c | 73 +++---
 server/video-encoder.h |  2 +-
 3 files changed, 68 insertions(+), 11 deletions(-)

diff --git a/configure.ac b/configure.ac
index 174f01f..a902e84 100644
--- a/configure.ac
+++ b/configure.ac
@@ -130,6 +130,10 @@ AC_SUBST([SPICE_PROTOCOL_MIN_VER])
 PKG_CHECK_MODULES([GLIB2], [glib-2.0 >= 2.22])
 AS_VAR_APPEND([SPICE_REQUIRES], [" glib-2.0 >= 2.22"])
 
+AC_CHECK_LIB(glib-2.0, g_get_num_processors,
+ AC_DEFINE([HAVE_G_GET_NUMPROCESSORS], 1, [Defined if we have 
g_get_num_processors()]),,
+ $GLIB2_LIBS)
+
 PKG_CHECK_MODULES(PIXMAN, pixman-1 >= 0.17.7)
 AC_SUBST(PIXMAN_CFLAGS)
 AC_SUBST(PIXMAN_LIBS)
diff --git a/server/gstreamer-encoder.c b/server/gstreamer-encoder.c
index edf87df..6dab5f9 100644
--- a/server/gstreamer-encoder.c
+++ b/server/gstreamer-encoder.c
@@ -192,10 +192,26 @@ static void set_appsrc_caps(SpiceGstEncoder *encoder)
 /* A helper for spice_gst_encoder_encode_frame() */
 static gboolean create_pipeline(SpiceGstEncoder *encoder)
 {
+const gchar* gstenc_name;
+switch (encoder->base.codec_type)
+{
+case SPICE_VIDEO_CODEC_TYPE_MJPEG:
+gstenc_name = "avenc_mjpeg";
+break;
+case SPICE_VIDEO_CODEC_TYPE_VP8:
+gstenc_name = "vp8enc";
+break;
+default:
+/* gstreamer_encoder_new() should have rejected this codec type */
+spice_warning("unsupported codec type %d", encoder->base.codec_type);
+return FALSE;
+}
+
 GError *err = NULL;
-const gchar *desc = "appsrc name=src format=2 do-timestamp=true ! 
videoconvert ! avenc_mjpeg name=encoder ! appsink name=sink";
+gchar *desc = g_strdup_printf("appsrc name=src format=2 do-timestamp=true 
! videoconvert ! %s name=encoder ! appsink name=sink", gstenc_name);
 spice_debug("GStreamer pipeline: %s", desc);
 encoder->pipeline = gst_parse_launch_full(desc, NULL, 
GST_PARSE_FLAG_FATAL_ERRORS, &err);
+g_free(desc);
 if (!encoder->pipeline || err) {
 spice_warning("GStreamer error: %s", err->message);
 g_clear_error(&err);
@@ -221,18 +237,45 @@ static gboolean configure_pipeline(SpiceGstEncoder 
*encoder,
 
 /* Configure the encoder bitrate, frame latency, etc. */
 adjust_bit_rate(encoder);
-g_object_set(G_OBJECT(encoder->gstenc),
- "bitrate", encoder->bit_rate,
- "max-threads", 1, /* zero-frame latency */
- NULL);
+switch (encoder->base.codec_type) {
+case SPICE_VIDEO_CODEC_TYPE_MJPEG:
+g_object_set(G_OBJECT(encoder->gstenc),
+ "bitrate", encoder->bit_rate,
+ "max-threads", 1, /* zero-frame latency */
+ NULL);
+
+/* See https://bugzilla.gnome.org/show_bug.cgi?id=753257 */
+spice_debug("removing the pipeline clock");
+gst_pipeline_use_clock(GST_PIPELINE(encoder->pipeline), NULL);
+break;
+case SPICE_VIDEO_CODEC_TYPE_VP8: {
+/* See http://www.webmproject.org/docs/encoder-parameters/ */
+#ifdef HAVE_G_GET_NUMPROCESSORS
+int core_count = g_get_num_processors();
+#else
+int core_count = 1;
+#endif
+g_object_set(G_OBJECT(encoder->gstenc),
+ "resize-allowed", TRUE, /* for very low bit rates */
+ "target-bitrate", encoder->bit_rate,
+ "end-usage", 1, /* CBR */
+ "lag-in-frames", 0, /* zero-frame latency */
+ "error-resilient", 1, /* for client frame drops */
+ "deadline", 100 / get_source_fps(encoder) / 2, /* 
usec */
+ "threads", core_count - 1,
+ NULL);
+break;
+}
+default:
+/* gstreamer_encoder_new() should have rejected this codec type */
+spice_warning("unknown encoder type %d", encoder->base.codec_type);
+free_pipeline(encoder);
+return FALSE;
+}
 
 /* Set the source caps */
 set_appsrc_caps(encoder);
 
-/* See https://bugzilla.gnome.org/show_bug.cgi?id=753257 */
-spice_debug("removing the pipeline clock");
-gst_pipeline_use_clock(GST_PIPELINE(encoder->pipeline), NULL);
-
 /* Start playing */
 spice_debug("setting state to PLAYING");
 if (gst_element_set_state(encoder->pipeline, GST_STATE_PLAYING) == 
GST_STATE_CHANGE_FAILURE) {
@@ -250,6 +293,15 @@ static void reconfigure_pipeline(SpiceGstEncoder *encoder)
 if (!is_pipeline_configured(encoder)) {
 return;
 }
+if (encoder->base.codec_type == SPICE_VIDEO_CODEC_TYPE_VP8) {
+/* vp8enc fails to account for caps changes that modify the frame size
+ * and complains about the buffer size.
+ * So recreate the pipeline from scratch.
+ */
+free_pipeline(encoder);
+return;
+}
+
 if (gst_element_set_state(

[Spice-devel] [spice v9 04/24] server: Check the client video codec capabilities

2016-01-18 Thread Francois Gouget
Signed-off-by: Francois Gouget 
---
 configure.ac|  2 +-
 server/dcc.c|  5 -
 server/dcc.h|  2 +-
 server/stream.c | 41 +
 4 files changed, 35 insertions(+), 15 deletions(-)

diff --git a/configure.ac b/configure.ac
index f80178e..174f01f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -123,7 +123,7 @@ AS_IF([test x"$have_smartcard" = "xyes"], [
 AS_VAR_APPEND([SPICE_REQUIRES], [" libcacard >= 0.1.2"])
 ])
 
-SPICE_PROTOCOL_MIN_VER=0.12.10
+SPICE_PROTOCOL_MIN_VER=0.12.11
 PKG_CHECK_MODULES([SPICE_PROTOCOL], [spice-protocol >= 
$SPICE_PROTOCOL_MIN_VER])
 AC_SUBST([SPICE_PROTOCOL_MIN_VER])
 
diff --git a/server/dcc.c b/server/dcc.c
index 21e91c0..ed4598f 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -407,7 +407,10 @@ static void dcc_create_all_streams(DisplayChannelClient 
*dcc)
 
 while ((item = ring_next(ring, item))) {
 Stream *stream = SPICE_CONTAINEROF(item, Stream, link);
-dcc_create_stream(dcc, stream);
+if (!dcc_create_stream(dcc, stream)) {
+stream_stop(DCC_TO_DC(dcc), stream);
+return;
+}
 }
 }
 
diff --git a/server/dcc.h b/server/dcc.h
index b510254..34ca346 100644
--- a/server/dcc.h
+++ b/server/dcc.h
@@ -173,7 +173,7 @@ void   dcc_destroy_surface  
 (DisplayCha
   uint32_t 
surface_id);
 void   dcc_stream_agent_clip 
(DisplayChannelClient* dcc,
   
StreamAgent *agent);
-void   dcc_create_stream 
(DisplayChannelClient *dcc,
+gboolean   dcc_create_stream 
(DisplayChannelClient *dcc,
   Stream 
*stream);
 void   dcc_create_surface
(DisplayChannelClient *dcc,
   int 
surface_id);
diff --git a/server/stream.c b/server/stream.c
index 9c335b6..bbc7003 100644
--- a/server/stream.c
+++ b/server/stream.c
@@ -440,7 +440,12 @@ static void display_channel_create_stream(DisplayChannel 
*display, Drawable *dra
 display->streams_size_total += stream->width * stream->height;
 display->stream_count++;
 FOREACH_DCC(display, dcc_ring_item, next, dcc) {
-dcc_create_stream(dcc, stream);
+if (!dcc_create_stream(dcc, stream)) {
+drawable->stream = NULL;
+stream->current = NULL;
+stream_stop(display, stream);
+return;
+}
 }
 spice_debug("stream %d %dx%d (%d, %d) (%d, %d) %u fps",
 (int)(stream - display->streams_buf), stream->width,
@@ -695,25 +700,32 @@ static void update_client_playback_delay(void *opaque, 
uint32_t delay_ms)
 }
 
 /* A helper for dcc_create_stream(). */
-static VideoEncoder* dcc_create_video_encoder(uint64_t starting_bit_rate,
+static VideoEncoder* dcc_create_video_encoder(DisplayChannelClient *dcc,
+  uint64_t starting_bit_rate,
   VideoEncoderRateControlCbs *cbs,
   void *cbs_opaque)
 {
+RedChannelClient *rcc = RED_CHANNEL_CLIENT(dcc);
+int client_has_multi_codec = red_channel_client_test_remote_cap(rcc, 
SPICE_DISPLAY_CAP_MULTI_CODEC);
+if (!client_has_multi_codec || red_channel_client_test_remote_cap(rcc, 
SPICE_DISPLAY_CAP_CODEC_MJPEG)) {
 #ifdef HAVE_GSTREAMER_1_0
-VideoEncoder* video_encoder = gstreamer_encoder_new(starting_bit_rate, 
cbs, cbs_opaque);
-if (video_encoder) {
-return video_encoder;
-}
+VideoEncoder* video_encoder = gstreamer_encoder_new(starting_bit_rate, 
cbs, cbs_opaque);
+if (video_encoder) {
+return video_encoder;
+}
 #endif
-/* Use the builtin MJPEG video encoder as a fallback */
-return mjpeg_encoder_new(starting_bit_rate, cbs, cbs_opaque);
+/* Use the builtin MJPEG video encoder as a fallback */
+return mjpeg_encoder_new(starting_bit_rate, cbs, cbs_opaque);
+}
+
+return NULL;
 }
 
-void dcc_create_stream(DisplayChannelClient *dcc, Stream *stream)
+gboolean dcc_create_stream(DisplayChannelClient *dcc, Stream *stream)
 {
 StreamAgent *agent = &dcc->stream_agents[get_stream_id(DCC_TO_DC(dcc), 
stream)];
 
-spice_return_if_fail(region_is_empty(&agent->vis_region));
+spice_return_val_if_fail(region_is_empty(&agent->vis_region), FALSE);
 
 stream->refs++;
 if (stream->current) {
@@ -736,9 +748,13 @@ void dcc_create_stream(DisplayChannelClient *dcc, Stream 
*stream)
 video_cbs.update_client_playback_delay = update_client_playback_delay;
 
 initial_bit_rate = get_initial_bit_rate(dcc, stream);
-agent->video_e

[Spice-devel] [spice v9 05/24] server: Let the administrator pick the video encoder and codec

2016-01-18 Thread Francois Gouget
The Spice server administrator can specify the preferred encoder and
codec preferences to optimize for CPU or bandwidth usage. Preferences
are described in a semi-colon separated list of encoder:codec pairs.
The server has a default preference list which can explicitly be
selected by specifying 'auto'.

The server then picks a codec supported by the client based on the
following new client capabilities:
 * SPICE_DISPLAY_CAP_MULTI_CODEC which denotes a recent client that
   supports multiple codecs. This capability is needed to not have to
   hardcode that MJPEG is supported. This makes it possible to write
   clients that don't support MJPEG.
 * SPICE_DISPLAY_CAP_CODEC_XXX, where XXX is a supported codec. Note
   that for now the server only supports the MJPEG codec.

Signed-off-by: Francois Gouget 
---
 server/dcc-send.c  |   2 +-
 server/display-channel.c   |  13 
 server/display-channel.h   |   5 ++
 server/gstreamer-encoder.c |   6 +-
 server/mjpeg-encoder.c |   6 +-
 server/red-dispatcher.c|  17 +
 server/red-dispatcher.h|   8 +++
 server/red-worker.c|  14 
 server/reds.c  | 155 -
 server/reds.h  |  13 
 server/spice-server.h  |   1 +
 server/spice-server.syms   |   5 ++
 server/stream.c|  29 +++--
 server/video-encoder.h |  23 ++-
 14 files changed, 269 insertions(+), 28 deletions(-)

diff --git a/server/dcc-send.c b/server/dcc-send.c
index fd11b09..e13f04f 100644
--- a/server/dcc-send.c
+++ b/server/dcc-send.c
@@ -2189,7 +2189,7 @@ static void marshall_stream_start(RedChannelClient *rcc,
 stream_create.surface_id = 0;
 stream_create.id = get_stream_id(DCC_TO_DC(dcc), stream);
 stream_create.flags = stream->top_down ? SPICE_STREAM_FLAGS_TOP_DOWN : 0;
-stream_create.codec_type = SPICE_VIDEO_CODEC_TYPE_MJPEG;
+stream_create.codec_type = agent->video_encoder->codec_type;
 
 stream_create.src_width = stream->width;
 stream_create.src_height = stream->height;
diff --git a/server/display-channel.c b/server/display-channel.c
index 3bf065c..e81e697 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -219,6 +219,17 @@ void display_channel_set_stream_video(DisplayChannel 
*display, int stream_video)
 display->stream_video = stream_video;
 }
 
+void display_channel_set_video_codecs(DisplayChannel *display,
+  int num_video_codecs,
+  RedVideoCodec *video_codecs)
+{
+spice_return_if_fail(display);
+spice_return_if_fail(num_video_codecs > RED_MAX_VIDEO_CODECS);
+
+display->num_video_codecs = num_video_codecs;
+memcpy(display->video_codecs, video_codecs, sizeof(display->video_codecs));
+}
+
 static void stop_streams(DisplayChannel *display)
 {
 Ring *ring = &display->streams;
@@ -2072,6 +2083,8 @@ DisplayChannel* display_channel_new(RedWorker *worker, 
int migrate, int stream_v
 drawables_init(display);
 image_cache_init(&display->image_cache);
 display->stream_video = stream_video;
+display->num_video_codecs = num_video_codecs;
+memcpy(display->video_codecs, video_codecs, sizeof(display->video_codecs));
 display_channel_init_streams(display);
 
 return display;
diff --git a/server/display-channel.h b/server/display-channel.h
index bf29cd3..f55d23b 100644
--- a/server/display-channel.h
+++ b/server/display-channel.h
@@ -185,6 +185,8 @@ struct DisplayChannel {
 uint32_t glz_drawable_count;
 
 int stream_video;
+uint32_t num_video_codecs;
+RedVideoCodec video_codecs[RED_MAX_VIDEO_CODECS];
 uint32_t stream_count;
 Stream streams_buf[NUM_STREAMS];
 Stream *free_streams;
@@ -273,6 +275,9 @@ void   display_channel_update   
 (DisplayCha
 void   display_channel_free_some 
(DisplayChannel *display);
 void   display_channel_set_stream_video  
(DisplayChannel *display,
   int 
stream_video);
+void   display_channel_set_video_codecs  
(DisplayChannel *display,
+  int 
num_video_codecs,
+  
RedVideoCodec *video_codecs);
 intdisplay_channel_get_streams_timeout   
(DisplayChannel *display);
 void   display_channel_compress_stats_print  (const 
DisplayChannel *display);
 void   display_channel_compress_stats_reset  
(DisplayChannel *display);
diff --git a/server/gstreamer-encoder.c b/server/gstreamer-encoder.c
index e934180..edf87df 100644
--- a/server/gstreamer-encoder.c
+++ b/server/gstreamer-encoder.c
@@ -494,10 +494,13 @@ static void spice_gst_encoder_get_stats(VideoEncoder 
*video_encoder,

[Spice-devel] [spice v9 03/24] server: Add a GStreamer 1.0 MJPEG video encoder and use it by default

2016-01-18 Thread Francois Gouget
This introduces a pared down GStreamer-based video encoder to serve as
the basis for later enhancements.
In this form the new encoder supports both regular and sized streams
but lacks any rate control. It should still work fine if bandwidth is
sufficient such as on LANs.

Signed-off-by: Francois Gouget 
---
 configure.ac   |  25 +++
 server/Makefile.am |   8 +
 server/gstreamer-encoder.c | 530 +
 server/stream.c|  19 +-
 server/video-encoder.h |   5 +
 5 files changed, 585 insertions(+), 2 deletions(-)
 create mode 100644 server/gstreamer-encoder.c

diff --git a/configure.ac b/configure.ac
index 2b09ec7..f80178e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -69,6 +69,30 @@ dnl 
=
 dnl Check optional features
 SPICE_CHECK_SMARTCARD
 
+AC_ARG_ENABLE(gstreamer,
+  AS_HELP_STRING([--enable-gstreamer=@<:@auto/yes/no@:>@],
+ [Enable GStreamer 1.0 support]),,
+  [enable_gstreamer="auto"])
+
+if test "x$enable_gstreamer" != "xno"; then
+SPICE_CHECK_GSTREAMER(GSTREAMER_1_0, 1.0, [gstreamer-1.0 
gstreamer-base-1.0 gstreamer-app-1.0 gstreamer-video-1.0],
+[enable_gstreamer="yes"
+ SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_1_0, [gst-plugins-base 
1.0], [appsrc videoconvert appsink])
+ SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_1_0, [gstreamer-libav 
1.0], [avenc_mjpeg])
+ SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_1_0, [gst-plugins-good 
1.0], [vp8enc])
+ SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_1_0, [gst-plugins-ugly 
1.0], [x264enc])
+ ],
+ [if test "x$enable_gstreamer" = "xyes"; then
+  AC_MSG_ERROR([GStreamer 1.0 support requested but not found. You 
may set GSTREAMER_1_0_CFLAGS and GSTREAMER_1_0_LIBS to avoid the need to call 
pkg-config.])
+  fi
+])
+fi
+AM_CONDITIONAL(HAVE_GSTREAMER_1_0, test "x$have_gstreamer_1_0" = "xyes")
+
+if test x"$gstreamer_missing" != x; then
+SPICE_WARNING([The following GStreamer $enable_gstreamer tools/elements 
are missing:$gstreamer_missing. The GStreamer video encoder can be built but 
may not work.])
+fi
+
 AC_ARG_ENABLE([automated_tests],
   AS_HELP_STRING([--enable-automated-tests], [Enable automated 
tests using spicy-screenshot (part of spice--gtk)]),,
   [enable_automated_tests="no"])
@@ -238,6 +262,7 @@ AC_MSG_NOTICE([
 
 LZ4 support:  ${enable_lz4}
 Smartcard:${have_smartcard}
+GStreamer 1.0:${have_gstreamer_1_0}
 SASL support: ${have_sasl}
 Automated tests:  ${enable_automated_tests}
 Manual:   ${have_asciidoc}
diff --git a/server/Makefile.am b/server/Makefile.am
index edeca99..9f33c93 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -11,6 +11,7 @@ AM_CPPFLAGS = \
$(SASL_CFLAGS)  \
$(SLIRP_CFLAGS) \
$(SMARTCARD_CFLAGS) \
+   $(GSTREAMER_1_0_CFLAGS) \
$(SPICE_PROTOCOL_CFLAGS)\
$(SSL_CFLAGS)   \
$(VISIBILITY_HIDDEN_CFLAGS) \
@@ -43,6 +44,7 @@ libserver_la_LIBADD = 
\
$(PIXMAN_LIBS)  \
$(SASL_LIBS)\
$(SLIRP_LIBS)   \
+   $(GSTREAMER_1_0_LIBS)   \
$(SSL_LIBS) \
$(Z_LIBS)   \
$(SPICE_NONPKGCONFIG_LIBS)  \
@@ -151,6 +153,12 @@ libserver_la_SOURCES +=\
$(NULL)
 endif
 
+if HAVE_GSTREAMER_1_0
+libserver_la_SOURCES +=\
+   gstreamer-encoder.c \
+   $(NULL)
+endif
+
 libspice_server_la_LIBADD = libserver.la
 libspice_server_la_SOURCES =
 
diff --git a/server/gstreamer-encoder.c b/server/gstreamer-encoder.c
new file mode 100644
index 000..e934180
--- /dev/null
+++ b/server/gstreamer-encoder.c
@@ -0,0 +1,530 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 2015 Jeremy White
+   Copyright (C) 2015 Francois Gouget
+
+   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

[Spice-devel] [spice v9 02/24] server: Enable adding alternative MJPEG video encoders

2016-01-18 Thread Francois Gouget
This replaces the original mjpeg_encoder API with a VideoEncoder base
class which can be reimplemented by other encoders.
This also renames the members and enums from mjpeg_* to video_*.

Signed-off-by: Francois Gouget 
---
 server/Makefile.am |   2 +-
 server/dcc-send.c  |  24 
 server/dcc.c   |  24 
 server/dcc.h   |   2 +-
 server/mjpeg-encoder.c |  84 +++---
 server/mjpeg-encoder.h | 100 ---
 server/stream.c|  40 ++---
 server/stream.h|   4 +-
 server/video-encoder.h | 160 +
 9 files changed, 258 insertions(+), 182 deletions(-)
 delete mode 100644 server/mjpeg-encoder.h
 create mode 100644 server/video-encoder.h

diff --git a/server/Makefile.am b/server/Makefile.am
index b20beec..edeca99 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -84,7 +84,6 @@ libserver_la_SOURCES =\
main-channel.c  \
main-channel.h  \
mjpeg-encoder.c \
-   mjpeg-encoder.h \
red-channel.c   \
red-channel.h   \
red-common.h\
@@ -122,6 +121,7 @@ libserver_la_SOURCES =  \
spicevmc.c  \
spice_timer_queue.c \
spice_timer_queue.h \
+   video-encoder.h \
zlib-encoder.c  \
zlib-encoder.h  \
image-cache.h   \
diff --git a/server/dcc-send.c b/server/dcc-send.c
index c3f79ef..fd11b09 100644
--- a/server/dcc-send.c
+++ b/server/dcc-send.c
@@ -1691,7 +1691,7 @@ static int red_marshall_stream_data(RedChannelClient *rcc,
 uint64_t time_now = spice_get_monotonic_time_ns();
 size_t outbuf_size;
 
-if (!dcc->use_mjpeg_encoder_rate_control) {
+if (!dcc->use_video_encoder_rate_control) {
 if (time_now - agent->last_send_time < (1000 * 1000 * 1000) / 
agent->fps) {
 agent->frames--;
 #ifdef STREAM_STATS
@@ -1706,25 +1706,25 @@ static int red_marshall_stream_data(RedChannelClient 
*rcc,
 drawable->red_drawable->mm_time :
 reds_get_mm_time();
 outbuf_size = dcc->send_data.stream_outbuf_size;
-ret = mjpeg_encoder_encode_frame(agent->mjpeg_encoder,
- &image->u.bitmap, width, height,
- &drawable->red_drawable->u.copy.src_area,
- stream->top_down, frame_mm_time,
-&dcc->send_data.stream_outbuf,
- &outbuf_size, &n);
+ret = agent->video_encoder->encode_frame(agent->video_encoder,
+ &image->u.bitmap, width, height,
+ 
&drawable->red_drawable->u.copy.src_area,
+ stream->top_down, frame_mm_time,
+ &dcc->send_data.stream_outbuf,
+ &outbuf_size, &n);
 switch (ret) {
-case MJPEG_ENCODER_FRAME_DROP:
-spice_assert(dcc->use_mjpeg_encoder_rate_control);
+case VIDEO_ENCODER_FRAME_DROP:
+spice_assert(dcc->use_video_encoder_rate_control);
 #ifdef STREAM_STATS
 agent->stats.num_drops_fps++;
 #endif
 return TRUE;
-case MJPEG_ENCODER_FRAME_UNSUPPORTED:
+case VIDEO_ENCODER_FRAME_UNSUPPORTED:
 return FALSE;
-case MJPEG_ENCODER_FRAME_ENCODE_DONE:
+case VIDEO_ENCODER_FRAME_ENCODE_DONE:
 break;
 default:
-spice_error("bad return value (%d) from mjpeg_encoder_encode_frame", 
ret);
+spice_error("bad return value (%d) from VideoEncoder::encode_frame", 
ret);
 return FALSE;
 }
 dcc->send_data.stream_outbuf_size = outbuf_size;
diff --git a/server/dcc.c b/server/dcc.c
index 2568e24..21e91c0 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -350,7 +350,7 @@ static void dcc_init_stream_agents(DisplayChannelClient 
*dcc)
 red_channel_pipe_item_init(channel, &agent->create_item, 
PIPE_ITEM_TYPE_STREAM_CREATE);
 red_channel_pipe_item_init(channel, &agent->destroy_item, 
PIPE_ITEM_TYPE_STREAM_DESTROY);
 }
-dcc->use_mjpeg_encoder_rate_control =
+dcc->use_video_encoder_rate_control =
 red_channel_client_test_remote_cap(RED_CHANNEL_CLIENT(dcc), 
SPICE_DISPLAY_CAP_STREAM_REPORT);
 }
 
@@ -474,9 +474,9 @@ static void dcc_destroy_stream_agents(DisplayChannelClient 
*dcc)
 StreamAgent *agent = &dcc->stream_agents[i];
 region_destroy(&agent->vis_region);
 region_destroy(&agent->clip);
-i

[Spice-devel] [protocol v9 01/24] protocol: Add support for the VP8 and h264 video codecs

2016-01-18 Thread Francois Gouget
Clients that support multiple codecs must advertise the
SPICE_DISPLAY_CAP_MULTI_CODEC capability and one
SPICE_DISPLAY_CAP_CODEC_XXX per supported codec.

Signed-off-by: Francois Gouget 
---
 spice.proto  | 2 ++
 spice/enums.h| 2 ++
 spice/protocol.h | 4 
 3 files changed, 8 insertions(+)

diff --git a/spice.proto b/spice.proto
index af970f2..4a0778d 100644
--- a/spice.proto
+++ b/spice.proto
@@ -329,6 +329,8 @@ flags8 path_flags { /* TODO: C enum names changes */
 
 enum8 video_codec_type {
 MJPEG = 1,
+VP8,
+H264,
 };
 
 flags8 stream_flags {
diff --git a/spice/enums.h b/spice/enums.h
index 613db52..c6e9840 100644
--- a/spice/enums.h
+++ b/spice/enums.h
@@ -139,6 +139,8 @@ typedef enum SpicePathFlags {
 
 typedef enum SpiceVideoCodecType {
 SPICE_VIDEO_CODEC_TYPE_MJPEG = 1,
+SPICE_VIDEO_CODEC_TYPE_VP8,
+SPICE_VIDEO_CODEC_TYPE_H264,
 
 SPICE_VIDEO_CODEC_TYPE_ENUM_END
 } SpiceVideoCodecType;
diff --git a/spice/protocol.h b/spice/protocol.h
index 3e6c624..f4a2259 100644
--- a/spice/protocol.h
+++ b/spice/protocol.h
@@ -137,6 +137,10 @@ enum {
 SPICE_DISPLAY_CAP_LZ4_COMPRESSION,
 SPICE_DISPLAY_CAP_PREF_COMPRESSION,
 SPICE_DISPLAY_CAP_GL_SCANOUT,
+SPICE_DISPLAY_CAP_MULTI_CODEC,
+SPICE_DISPLAY_CAP_CODEC_MJPEG,
+SPICE_DISPLAY_CAP_CODEC_VP8,
+SPICE_DISPLAY_CAP_CODEC_H264,
 };
 
 enum {
-- 
2.6.4
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH v9 00/24] Add GStreamer support for video streaming

2016-01-18 Thread Francois Gouget

The source changed so here is the new revision of this patchset.

This patch series adds support for using GStreamer to encode and decode 
the video streams, adding support for VP8 and h264 codecs. As before the 
patches can also be grabbed from the repositories below:

spice:  https://github.com/fgouget/spice
spice-gtk:  https://github.com/fgouget/spice-gtk
xf86-video-qxl: https://github.com/fgouget/xf86-video-qxl
spice-protocol: https://github.com/fgouget/spice-protocol

(there's also 'extras' branches with more experimental/future patches 
for the curious)


Changes from v8:
* Rebased on the current source.
* Adjusted the Spice protocol version requirement.
 
Changes from v7:
* When the client has support for GStreamer video codecs it now 
  checks the presence of each supported codec before advertising support 
  for it.

Changes from v6:
* configure.ac uses the new m4 macros to check for GStreamer support 
  and the presence of the needed plugins.
* It separates adding checks for the client codec support from 
  specifying which codec to use in the server and from adding VP8 
  support.


-- 
Francois Gouget 

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH 05/14] smartcard-manager: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Christophe Fergeau
On Mon, Jan 18, 2016 at 10:05:41AM +0100, Fabiano Fidêncio wrote:
> Instead of using GSimpleAsyncResult, use the new GTask API, which is
> much more straightforward.
> ---
>  src/smartcard-manager.c | 33 +
>  1 file changed, 13 insertions(+), 20 deletions(-)
> 
> diff --git a/src/smartcard-manager.c b/src/smartcard-manager.c
> index 6578328..2310ab6 100644
> --- a/src/smartcard-manager.c
> +++ b/src/smartcard-manager.c
> @@ -476,8 +476,9 @@ end:
>  return retval;
>  }
>  
> -static void smartcard_manager_init_helper(GSimpleAsyncResult *res,
> -  GObject *object,
> +static void smartcard_manager_init_helper(GTask *task,
> +  gpointer object,
> +  gpointer task_data,
>GCancellable *cancellable)
>  {
>  static GOnce smartcard_manager_once = G_ONCE_INIT;
> @@ -492,8 +493,10 @@ static void 
> smartcard_manager_init_helper(GSimpleAsyncResult *res,
> (GThreadFunc)smartcard_manager_init,
> &args);
>  if (args.err != NULL) {
> -g_simple_async_result_set_from_error(res, args.err);
> +g_task_return_error(task, args.err);
>  g_error_free(args.err);

g_task_return_error() takes ownership of args.err, you cannot/do not
need to free it afterwards.

> +} else {
> +g_task_return_boolean(task, TRUE);
>  }
>  }
>  
> @@ -504,17 +507,10 @@ void spice_smartcard_manager_init_async(SpiceSession 
> *session,
>  GAsyncReadyCallback callback,
>  gpointer opaque)
>  {
> -GSimpleAsyncResult *res;
> +GTask *task = g_task_new(session, cancellable, callback, opaque);
>  
> -res = g_simple_async_result_new(G_OBJECT(session),
> -callback,
> -opaque,
> -spice_smartcard_manager_init);
> -g_simple_async_result_run_in_thread(res,
> -smartcard_manager_init_helper,
> -G_PRIORITY_DEFAULT,
> -cancellable);
> -g_object_unref(res);
> +g_task_run_in_thread(task, smartcard_manager_init_helper);
> +g_object_unref(task);
>  }
>  
>  G_GNUC_INTERNAL
> @@ -522,21 +518,18 @@ gboolean 
> spice_smartcard_manager_init_finish(SpiceSession *session,
>   GAsyncResult *result,
>   GError **err)
>  {
> -GSimpleAsyncResult *simple;
> +GTask *task = G_TASK(result);
>  
>  g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE);
> -g_return_val_if_fail(G_IS_SIMPLE_ASYNC_RESULT(result), FALSE);
> +g_return_val_if_fail(G_IS_TASK(task), FALSE);
>  
>  SPICE_DEBUG("smartcard_manager_finish");
>  
> -simple = G_SIMPLE_ASYNC_RESULT(result);
> -g_return_val_if_fail(g_simple_async_result_get_source_tag(simple) == 
> spice_smartcard_manager_init, FALSE);
> -if (g_simple_async_result_propagate_error(simple, err))
> -return FALSE;
> +g_return_val_if_fail(g_task_get_source_tag(task) == 
> spice_smartcard_manager_init, FALSE);

Is this check working? Don't you need to call g_task_set_source_tag()
for it to work?

Christophe


signature.asc
Description: PGP signature
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH 04/14] channel-usbredir: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Christophe Fergeau
Acked-by: Christophe Fergeau 

On Mon, Jan 18, 2016 at 10:05:40AM +0100, Fabiano Fidêncio wrote:
> Instead of using GSimpleAsyncResult, use the new GTask API, which is
> much more straightforward.
> ---
>  src/channel-usbredir.c | 39 +--
>  1 file changed, 17 insertions(+), 22 deletions(-)
> 
> diff --git a/src/channel-usbredir.c b/src/channel-usbredir.c
> index 0be72ba..4ddf7bf 100644
> --- a/src/channel-usbredir.c
> +++ b/src/channel-usbredir.c
> @@ -76,7 +76,7 @@ struct _SpiceUsbredirChannelPrivate {
>  int read_buf_size;
>  enum SpiceUsbredirChannelState state;
>  #if USE_POLKIT
> -GSimpleAsyncResult *result;
> +GTask *task;
>  SpiceUsbAclHelper *acl_helper;
>  #endif
>  };
> @@ -297,12 +297,14 @@ static void spice_usbredir_channel_open_acl_cb(
>  spice_usbredir_channel_open_device(channel, &err);
>  }
>  if (err) {
> -g_simple_async_result_take_error(priv->result, err);
> +g_task_return_error(priv->task, err);
>  libusb_unref_device(priv->device);
>  priv->device = NULL;
>  g_boxed_free(spice_usb_device_get_type(), priv->spice_device);
>  priv->spice_device = NULL;
>  priv->state  = STATE_DISCONNECTED;
> +} else {
> +g_task_return_boolean(priv->task, TRUE);
>  }
>  
>  spice_usb_acl_helper_close_acl(priv->acl_helper);
> @@ -310,8 +312,7 @@ static void spice_usbredir_channel_open_acl_cb(
>  g_object_set(spice_channel_get_session(SPICE_CHANNEL(channel)),
>   "inhibit-keyboard-grab", FALSE, NULL);
>  
> -g_simple_async_result_complete_in_idle(priv->result);
> -g_clear_object(&priv->result);
> +g_clear_object(&priv->task);
>  }
>  #endif
>  
> @@ -325,7 +326,7 @@ void spice_usbredir_channel_connect_device_async(
>gpointer  user_data)
>  {
>  SpiceUsbredirChannelPrivate *priv = channel->priv;
> -GSimpleAsyncResult *result;
> +GTask *task;
>  #if ! USE_POLKIT
>  GError *err = NULL;
>  #endif
> @@ -338,18 +339,17 @@ void spice_usbredir_channel_connect_device_async(
>spice_usb_device_get_pid(spice_device),
>spice_device, channel);
>  
> -result = g_simple_async_result_new(G_OBJECT(channel), callback, 
> user_data,
> - 
> spice_usbredir_channel_connect_device_async);
> +task = g_task_new(channel, cancellable, callback, user_data);
>  
>  if (!priv->host) {
> -g_simple_async_result_set_error(result,
> +g_task_return_new_error(task,
>  SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
>  "Error libusb context not set");
>  goto done;
>  }
>  
>  if (priv->state != STATE_DISCONNECTED) {
> -g_simple_async_result_set_error(result,
> +g_task_return_new_error(task,
>  SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
>  "Error channel is busy");
>  goto done;
> @@ -359,7 +359,7 @@ void spice_usbredir_channel_connect_device_async(
>  priv->spice_device = g_boxed_copy(spice_usb_device_get_type(),
>spice_device);
>  #if USE_POLKIT
> -priv->result = result;
> +priv->task = task;
>  priv->state  = STATE_WAITING_FOR_ACL_HELPER;
>  priv->acl_helper = spice_usb_acl_helper_new();
>  g_object_set(spice_channel_get_session(SPICE_CHANNEL(channel)),
> @@ -373,17 +373,17 @@ void spice_usbredir_channel_connect_device_async(
>  return;
>  #else
>  if (!spice_usbredir_channel_open_device(channel, &err)) {
> -g_simple_async_result_take_error(result, err);
> +g_task_return_error(task, err);
>  libusb_unref_device(priv->device);
>  priv->device = NULL;
>  g_boxed_free(spice_usb_device_get_type(), priv->spice_device);
>  priv->spice_device = NULL;
> -}
> +} else {
> +g_task_return_boolean(task, TRUE);
>  #endif
>  
>  done:
> -g_simple_async_result_complete_in_idle(result);
> -g_object_unref(result);
> +g_object_unref(task);
>  }
>  
>  G_GNUC_INTERNAL
> @@ -392,16 +392,11 @@ gboolean spice_usbredir_channel_connect_device_finish(
> GAsyncResult *res,
> GError  **err)
>  {
> -GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT(res);
> +GTask *task = G_TASK(res);
>  
> -g_return_val_if_fail(g_simple_async_result_is_valid(res, 
> G_OBJECT(channel),
> - 
> spice_usbredir_channel_connect_device_async),
> - FALSE);
> +g_return_val_if_fail(g_task_is_valid(task, channel), FALSE);
>  
> -if (g_simple_async_result_propagate_error(result, err))
> -return FALSE;
> -
> -return TRUE;
> +return g_task_propagate_bool

Re: [Spice-devel] [PATCH 03/14] channel-port: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Christophe Fergeau
On Mon, Jan 18, 2016 at 10:05:39AM +0100, Fabiano Fidêncio wrote:
> Instead of using GSimpleAsyncResult, use the new GTask API, which is
> much more straightforward.
> ---
>  src/channel-port.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/src/channel-port.c b/src/channel-port.c
> index 6e01caa..20ee2fa 100644
> --- a/src/channel-port.c
> +++ b/src/channel-port.c
> @@ -292,7 +292,8 @@ void spice_port_write_async(SpicePortChannel *self,
>  c = self->priv;
>  
>  if (!c->opened) {
> -g_simple_async_report_error_in_idle(G_OBJECT(self), callback, 
> user_data,
> +g_task_report_new_error(self, callback,
> +user_data, spice_port_write_async,
>  SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
>  "The port is not opened");
>  return;

ACK.

Christophe


signature.asc
Description: PGP signature
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH 02/14] channel-main: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Christophe Fergeau
On Mon, Jan 18, 2016 at 10:05:38AM +0100, Fabiano Fidêncio wrote:
> Instead of using GSimpleAsyncResult, use the new GTask API, which is
> much more straightforward.
> ---
>  src/channel-main.c | 83 
> ++
>  1 file changed, 34 insertions(+), 49 deletions(-)
> 
> diff --git a/src/channel-main.c b/src/channel-main.c
> index 06dd121..6c0f238 100644
> --- a/src/channel-main.c
> +++ b/src/channel-main.c
> @@ -923,10 +923,9 @@ static gboolean flush_foreach_remove(gpointer key 
> G_GNUC_UNUSED,
>   gpointer value, gpointer user_data)
>  {
>  gboolean success = GPOINTER_TO_UINT(user_data);
> -GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT(value);
> +GTask *result = value;
> +g_task_return_boolean(result, success);
>  
> -g_simple_async_result_set_op_res_gboolean(result, success);
> -g_simple_async_result_complete_in_idle(result);
>  return TRUE;
>  }
>  
> @@ -940,38 +939,31 @@ static void file_xfer_flushed(SpiceMainChannel 
> *channel, gboolean success)
>  static void file_xfer_flush_async(SpiceMainChannel *channel, GCancellable 
> *cancellable,
>GAsyncReadyCallback callback, gpointer 
> user_data)
>  {
> -GSimpleAsyncResult *simple;
> +GTask *task;
>  SpiceMainChannelPrivate *c = channel->priv;
>  gboolean was_empty;
>  
> -simple = g_simple_async_result_new(G_OBJECT(channel), callback, 
> user_data,
> -   file_xfer_flush_async);
> +task = g_task_new(channel, cancellable, callback, user_data);
>  
>  was_empty = g_queue_is_empty(c->agent_msg_queue);
>  if (was_empty) {
> -g_simple_async_result_set_op_res_gboolean(simple, TRUE);
> -g_simple_async_result_complete_in_idle(simple);
> -g_object_unref(simple);
> +g_task_return_boolean(task, TRUE);
> +g_object_unref(task);
>  return;
>  }
>  
>  /* wait until the last message currently in the queue has been sent */
> -g_hash_table_insert(c->flushing, g_queue_peek_tail(c->agent_msg_queue), 
> simple);
> +g_hash_table_insert(c->flushing, g_queue_peek_tail(c->agent_msg_queue), 
> task);
>  }
>  
>  static gboolean file_xfer_flush_finish(SpiceMainChannel *channel, 
> GAsyncResult *result,
> GError **error)
>  {
> -GSimpleAsyncResult *simple = (GSimpleAsyncResult *)result;
> +GTask *task = G_TASK(result);
>  
> -g_return_val_if_fail(g_simple_async_result_is_valid(result,
> -G_OBJECT(channel), file_xfer_flush_async), FALSE);
> +g_return_val_if_fail(g_task_is_valid(result, channel), FALSE);
>  
> -if (g_simple_async_result_propagate_error(simple, error)) {
> -return FALSE;
> -}
> -
> -return g_simple_async_result_get_op_res_gboolean(simple);
> +return g_task_propagate_boolean(task, error);
>  }
>  
>  /* coroutine context */
> @@ -982,16 +974,15 @@ static void agent_send_msg_queue(SpiceMainChannel 
> *channel)
>  
>  while (c->agent_tokens > 0 &&
> !g_queue_is_empty(c->agent_msg_queue)) {
> -GSimpleAsyncResult *simple;
> +GTask *task;
>  c->agent_tokens--;
>  out = g_queue_pop_head(c->agent_msg_queue);
>  spice_msg_out_send_internal(out);
>  
> -simple = g_hash_table_lookup(c->flushing, out);
> -if (simple) {
> +task = g_hash_table_lookup(c->flushing, out);
> +if (task) {
>  /* if there's a flush task waiting for this message, finish it */
> -g_simple_async_result_set_op_res_gboolean(simple, TRUE);
> -g_simple_async_result_complete_in_idle(simple);
> +g_task_return_boolean(task, TRUE);
>  g_hash_table_remove(c->flushing, out);
>  }
>  }
> @@ -1776,7 +1767,7 @@ static void file_xfer_close_cb(GObject  *object,
> GAsyncResult *close_res,
> gpointer  user_data)
>  {
> -GSimpleAsyncResult *res;
> +GTask *task;
>  SpiceFileTransferTask *self;
>  GError *error = NULL;
>  
> @@ -1794,15 +1785,15 @@ static void file_xfer_close_cb(GObject  *object,
>  
>  /* Notify to user that files have been transferred or something error
> happened. */
> -res = g_simple_async_result_new(G_OBJECT(self->priv->channel),
> -self->priv->callback,
> -self->priv->user_data,
> -spice_main_file_copy_async);
> +task = g_task_new(self->priv->channel,
> +  self->priv->cancellable,
> +  self->priv->callback,
> +  self->priv->user_data);
>  if (self->priv->error) {
> -g_simple_async_result_take_error(res, self->priv->error);
> -g_simple_async_result_set_op_res_gboolean(res, FALSE);
> +

Re: [Spice-devel] [PATCH 01/14] channel-base: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Christophe Fergeau
On Mon, Jan 18, 2016 at 10:05:37AM +0100, Fabiano Fidêncio wrote:
> Instead of using GSimpleAsyncResult, use the new GTask API, which is
> much more straightforward.
> For using the new GTask API, let's bump GIO (part of GLib) dependency
> version to 2.36, which is safe based on major distro support:
> - Debian Jessie: glib-2.42
> - RHEL-7.1: glib-2.40
> - SLES12: glib-2.38
> - Ubuntu LTS 14.04: glib-2.40
> ---
>  configure.ac   |  6 +++---
>  src/channel-base.c | 26 ++
>  2 files changed, 13 insertions(+), 19 deletions(-)
> 
> diff --git a/configure.ac b/configure.ac
> index 38db8b5..e113487 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -201,7 +201,7 @@ fi
>  
>  AC_CHECK_FUNCS(clearenv strtok_r)
>  
> -PKG_CHECK_MODULES(GLIB2, glib-2.0 >= 2.28)
> +PKG_CHECK_MODULES(GLIB2, glib-2.0)
>  AC_SUBST(GLIB2_CFLAGS)
>  AC_SUBST(GLIB2_LIBS)
>  
> @@ -209,7 +209,7 @@ PKG_CHECK_MODULES(GOBJECT2, gobject-2.0)
>  AC_SUBST(GOBJECT2_CFLAGS)
>  AC_SUBST(GOBJECT2_LIBS)
>  
> -PKG_CHECK_MODULES(GIO, gio-2.0 >= 2.10.0 $gio_os)
> +PKG_CHECK_MODULES(GIO, gio-2.0 >= 2.36 $gio_os)
>  AC_SUBST(GIO_CFLAGS)
>  AC_SUBST(GIO_LIBS)
>  
> @@ -217,7 +217,7 @@ PKG_CHECK_MODULES(CAIRO, cairo >= 1.2.0)
>  AC_SUBST(CAIRO_CFLAGS)
>  AC_SUBST(CAIRO_LIBS)
>  
> -PKG_CHECK_MODULES(GTHREAD, gthread-2.0 > 2.0.0)
> +PKG_CHECK_MODULES(GTHREAD, gthread-2.0)
>  AC_SUBST(GTHREAD_CFLAGS)
>  AC_SUBST(GTHREAD_LIBS)
>  
> diff --git a/src/channel-base.c b/src/channel-base.c
> index 13e4ced..517e7b2 100644
> --- a/src/channel-base.c
> +++ b/src/channel-base.c
> @@ -240,10 +240,9 @@ void spice_channel_set_handlers(SpiceChannelClass *klass,
>  static void
>  vmc_write_free_cb(uint8_t *data, void *user_data)
>  {
> -GSimpleAsyncResult *result = user_data;
> +GTask *task = user_data;
>  
> -g_simple_async_result_complete_in_idle(result);

The callback for the async call was called after vmc_write_free_cb()
runs (ie after the message has been sent in spice_channel_write_msg)...

> -g_object_unref(result);
> +g_object_unref(task);
>  }
>  
>  G_GNUC_INTERNAL
> @@ -254,15 +253,14 @@ void spice_vmc_write_async(SpiceChannel *self,
> gpointer user_data)
>  {
>  SpiceMsgOut *msg;
> -GSimpleAsyncResult *simple;
> +GTask *task;
>  
> -simple = g_simple_async_result_new(G_OBJECT(self), callback, user_data,
> -   spice_port_write_async);
> -g_simple_async_result_set_op_res_gssize(simple, count);
> +task = g_task_new(self, cancellable, callback, user_data);
> +g_task_return_int(task, count);

... but with this call here, I suspect the ordering of the async
callback being called, and spice_channel_write_msg() being called become
unspecified.
Have you checked that it's actually a non-issue? If yes, this would
deserve detailed explanations in the commit log.

Christophe


signature.asc
Description: PGP signature
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH] Remove GSLice usage

2016-01-18 Thread Fabiano Fidêncio
On Mon, Jan 18, 2016 at 11:10 AM, Christophe Fergeau
 wrote:
> On Mon, Jan 18, 2016 at 04:15:36AM -0500, Marc-André Lureau wrote:
>> Hi
>>
>> - Original Message -
>> > It's being slowly deprecated im glib
>
> s/im/in/
>
>> > https://bugzilla.gnome.org/show_bug.cgi?id=754687
>> > ---
>> >  src/channel-display.c | 6 +++---
>> >  src/channel-smartcard.c   | 4 ++--
>> >  src/spice-channel-cache.h | 8 
>> >  src/spice-channel.c   | 8 
>> >  src/spice-grabsequence.c  | 8 
>> >  src/spice-util.c  | 4 ++--
>> >  src/wocky-http-proxy.c| 4 ++--
>> >  7 files changed, 21 insertions(+), 21 deletions(-)
>> >
>> > diff --git a/src/channel-display.c b/src/channel-display.c
>> > index dc73235..6a474b1 100644
>> > --- a/src/channel-display.c
>> > +++ b/src/channel-display.c
>> > @@ -635,7 +635,7 @@ static void destroy_surface(gpointer data)
>> >  display_surface *surface = data;
>> >
>> >  destroy_canvas(surface);
>> > -g_slice_free(display_surface, surface);
>> > +g_free(surface);
>> >  }
>> >
>> >  static void spice_display_channel_init(SpiceDisplayChannel *channel)
>> > @@ -869,7 +869,7 @@ static void display_handle_mode(SpiceChannel *channel,
>> > SpiceMsgIn *in)
>> >
>> >  g_warn_if_fail(c->mark == FALSE);
>> >
>> > -surface = g_slice_new0(display_surface);
>> > +surface = g_new0(display_surface, 1);
>> >  surface->format  = mode->bits == 32 ?
>> >  SPICE_SURFACE_FMT_32_xRGB : SPICE_SURFACE_FMT_16_555;
>> >  surface->width   = mode->x_res;
>> > @@ -1674,7 +1674,7 @@ static void 
>> > display_handle_surface_create(SpiceChannel
>> > *channel, SpiceMsgIn *in)
>> >  {
>> >  SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
>> >  SpiceMsgSurfaceCreate *create = spice_msg_in_parsed(in);
>> > -display_surface *surface = g_slice_new0(display_surface);
>> > +display_surface *surface = g_new0(display_surface, 1);
>> >
>> >  surface->surface_id = create->surface_id;
>> >  surface->format = create->format;
>> > diff --git a/src/channel-smartcard.c b/src/channel-smartcard.c
>> > index b5535e6..e2e1aad 100644
>> > --- a/src/channel-smartcard.c
>> > +++ b/src/channel-smartcard.c
>> > @@ -241,7 +241,7 @@ smartcard_message_free(SpiceSmartcardChannelMessage
>> > *message)
>> >  {
>> >  if (message->message)
>> >  spice_msg_out_unref(message->message);
>> > -g_slice_free(SpiceSmartcardChannelMessage, message);
>> > +g_free(message);
>> >  }
>> >
>> >  #if USE_SMARTCARD
>> > @@ -301,7 +301,7 @@ smartcard_message_new(VSCMsgType msg_type, SpiceMsgOut
>> > *msg_out)
>> >  {
>> >  SpiceSmartcardChannelMessage *message;
>> >
>> > -message = g_slice_new0(SpiceSmartcardChannelMessage);
>> > +message = g_new0(SpiceSmartcardChannelMessage, 1);
>> >  message->message = msg_out;
>> >  message->message_type = msg_type;
>> >
>> > diff --git a/src/spice-channel-cache.h b/src/spice-channel-cache.h
>> > index e609a67..75cc2cd 100644
>> > --- a/src/spice-channel-cache.h
>> > +++ b/src/spice-channel-cache.h
>> > @@ -37,7 +37,7 @@ typedef struct display_cache {
>> >
>> >  static inline display_cache_item* cache_item_new(guint64 id, gboolean 
>> > lossy)
>> >  {
>> > -display_cache_item *self = g_slice_new(display_cache_item);
>> > +display_cache_item *self = g_new(display_cache_item, 1);
>> >  self->id = id;
>> >  self->lossy = lossy;
>> >  self->ref_count = 1;
>> > @@ -46,12 +46,12 @@ static inline display_cache_item* 
>> > cache_item_new(guint64
>> > id, gboolean lossy)
>> >
>> >  static inline void cache_item_free(display_cache_item *self)
>> >  {
>> > -g_slice_free(display_cache_item, self);
>> > +g_free(self);
>> >  }
>> >
>> >  static inline display_cache* cache_new(GDestroyNotify value_destroy)
>> >  {
>> > -display_cache * self = g_slice_new(display_cache);
>> > +display_cache * self = g_new(display_cache, 1);
>> >  self->table = g_hash_table_new_full(g_int64_hash, g_int64_equal,
>> > (GDestroyNotify) cache_item_free,
>> > value_destroy);
>> > @@ -131,7 +131,7 @@ static inline void cache_clear(display_cache *cache)
>> >  static inline void cache_free(display_cache *cache)
>> >  {
>> >  g_hash_table_unref(cache->table);
>> > -g_slice_free(display_cache, cache);
>> > +g_free(cache);
>> >  }
>> >
>> >  G_END_DECLS
>> > diff --git a/src/spice-channel.c b/src/spice-channel.c
>> > index 41c94d0..ff85715 100644
>> > --- a/src/spice-channel.c
>> > +++ b/src/spice-channel.c
>> > @@ -471,7 +471,7 @@ SpiceMsgIn *spice_msg_in_new(SpiceChannel *channel)
>> >
>> >  g_return_val_if_fail(channel != NULL, NULL);
>> >
>> > -in = g_slice_new0(SpiceMsgIn);
>> > +in = g_new0(SpiceMsgIn, 1);
>> >  in->refcount = 1;
>> >  in->channel  = channel;
>> >
>> > @@ -519,7 +519,7 @@ void spice_msg_in_unref(SpiceMsgIn *in)
>> >  } else {
>> >

Re: [Spice-devel] [PATCH] Remove GSLice usage

2016-01-18 Thread Christophe Fergeau
On Mon, Jan 18, 2016 at 04:15:36AM -0500, Marc-André Lureau wrote:
> Hi
> 
> - Original Message -
> > It's being slowly deprecated im glib

s/im/in/

> > https://bugzilla.gnome.org/show_bug.cgi?id=754687
> > ---
> >  src/channel-display.c | 6 +++---
> >  src/channel-smartcard.c   | 4 ++--
> >  src/spice-channel-cache.h | 8 
> >  src/spice-channel.c   | 8 
> >  src/spice-grabsequence.c  | 8 
> >  src/spice-util.c  | 4 ++--
> >  src/wocky-http-proxy.c| 4 ++--
> >  7 files changed, 21 insertions(+), 21 deletions(-)
> > 
> > diff --git a/src/channel-display.c b/src/channel-display.c
> > index dc73235..6a474b1 100644
> > --- a/src/channel-display.c
> > +++ b/src/channel-display.c
> > @@ -635,7 +635,7 @@ static void destroy_surface(gpointer data)
> >  display_surface *surface = data;
> >  
> >  destroy_canvas(surface);
> > -g_slice_free(display_surface, surface);
> > +g_free(surface);
> >  }
> >  
> >  static void spice_display_channel_init(SpiceDisplayChannel *channel)
> > @@ -869,7 +869,7 @@ static void display_handle_mode(SpiceChannel *channel,
> > SpiceMsgIn *in)
> >  
> >  g_warn_if_fail(c->mark == FALSE);
> >  
> > -surface = g_slice_new0(display_surface);
> > +surface = g_new0(display_surface, 1);
> >  surface->format  = mode->bits == 32 ?
> >  SPICE_SURFACE_FMT_32_xRGB : SPICE_SURFACE_FMT_16_555;
> >  surface->width   = mode->x_res;
> > @@ -1674,7 +1674,7 @@ static void display_handle_surface_create(SpiceChannel
> > *channel, SpiceMsgIn *in)
> >  {
> >  SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
> >  SpiceMsgSurfaceCreate *create = spice_msg_in_parsed(in);
> > -display_surface *surface = g_slice_new0(display_surface);
> > +display_surface *surface = g_new0(display_surface, 1);
> >  
> >  surface->surface_id = create->surface_id;
> >  surface->format = create->format;
> > diff --git a/src/channel-smartcard.c b/src/channel-smartcard.c
> > index b5535e6..e2e1aad 100644
> > --- a/src/channel-smartcard.c
> > +++ b/src/channel-smartcard.c
> > @@ -241,7 +241,7 @@ smartcard_message_free(SpiceSmartcardChannelMessage
> > *message)
> >  {
> >  if (message->message)
> >  spice_msg_out_unref(message->message);
> > -g_slice_free(SpiceSmartcardChannelMessage, message);
> > +g_free(message);
> >  }
> >  
> >  #if USE_SMARTCARD
> > @@ -301,7 +301,7 @@ smartcard_message_new(VSCMsgType msg_type, SpiceMsgOut
> > *msg_out)
> >  {
> >  SpiceSmartcardChannelMessage *message;
> >  
> > -message = g_slice_new0(SpiceSmartcardChannelMessage);
> > +message = g_new0(SpiceSmartcardChannelMessage, 1);
> >  message->message = msg_out;
> >  message->message_type = msg_type;
> >  
> > diff --git a/src/spice-channel-cache.h b/src/spice-channel-cache.h
> > index e609a67..75cc2cd 100644
> > --- a/src/spice-channel-cache.h
> > +++ b/src/spice-channel-cache.h
> > @@ -37,7 +37,7 @@ typedef struct display_cache {
> >  
> >  static inline display_cache_item* cache_item_new(guint64 id, gboolean 
> > lossy)
> >  {
> > -display_cache_item *self = g_slice_new(display_cache_item);
> > +display_cache_item *self = g_new(display_cache_item, 1);
> >  self->id = id;
> >  self->lossy = lossy;
> >  self->ref_count = 1;
> > @@ -46,12 +46,12 @@ static inline display_cache_item* cache_item_new(guint64
> > id, gboolean lossy)
> >  
> >  static inline void cache_item_free(display_cache_item *self)
> >  {
> > -g_slice_free(display_cache_item, self);
> > +g_free(self);
> >  }
> >  
> >  static inline display_cache* cache_new(GDestroyNotify value_destroy)
> >  {
> > -display_cache * self = g_slice_new(display_cache);
> > +display_cache * self = g_new(display_cache, 1);
> >  self->table = g_hash_table_new_full(g_int64_hash, g_int64_equal,
> > (GDestroyNotify) cache_item_free,
> > value_destroy);
> > @@ -131,7 +131,7 @@ static inline void cache_clear(display_cache *cache)
> >  static inline void cache_free(display_cache *cache)
> >  {
> >  g_hash_table_unref(cache->table);
> > -g_slice_free(display_cache, cache);
> > +g_free(cache);
> >  }
> >  
> >  G_END_DECLS
> > diff --git a/src/spice-channel.c b/src/spice-channel.c
> > index 41c94d0..ff85715 100644
> > --- a/src/spice-channel.c
> > +++ b/src/spice-channel.c
> > @@ -471,7 +471,7 @@ SpiceMsgIn *spice_msg_in_new(SpiceChannel *channel)
> >  
> >  g_return_val_if_fail(channel != NULL, NULL);
> >  
> > -in = g_slice_new0(SpiceMsgIn);
> > +in = g_new0(SpiceMsgIn, 1);
> >  in->refcount = 1;
> >  in->channel  = channel;
> >  
> > @@ -519,7 +519,7 @@ void spice_msg_in_unref(SpiceMsgIn *in)
> >  } else {
> >  g_free(in->data);
> >  }
> > -g_slice_free(SpiceMsgIn, in);
> > +g_free(in);
> >  }
> >  
> >  G_GNUC_INTERNAL
> > @@ -624,7 +624,7 @@ SpiceMsgOut *spice_msg_ou

Re: [Spice-devel] [PATCH 14/14] Add strings for translation

2016-01-18 Thread Christophe Fergeau
On Mon, Jan 18, 2016 at 10:05:50AM +0100, Fabiano Fidêncio wrote:
> While doing the work to use GTask isntead of GSimpleAsyncResult I've

instead

> noticed a few error strings that were not marked to be translated.
> I am not exactly sure if it was intentional or not, but I do believe
> that our error messages should be translated.
> ---
>  po/POTFILES.in   |  6 ++
>  src/channel-main.c   |  4 +++-
>  src/channel-port.c   |  4 +++-
>  src/channel-usbredir.c   |  4 ++--
>  src/spice-channel.c  |  2 +-
>  src/spice-pulse.c|  8 +---
>  src/usb-acl-helper.c | 10 ++
>  src/usb-device-manager.c |  4 ++--
>  src/vmcstream.c  |  4 +++-
>  src/win-usb-driver-install.c | 16 +---
>  10 files changed, 40 insertions(+), 22 deletions(-)
> 
> diff --git a/po/POTFILES.in b/po/POTFILES.in
> index ad12609..7c79541 100644
> --- a/po/POTFILES.in
> +++ b/po/POTFILES.in
> @@ -1,8 +1,14 @@
> +src/channel-main.c
> +src/channel-port.c
>  src/channel-usbredir.c
>  src/desktop-integration.c
>  src/spice-channel.c
>  src/spice-cmdline.c
>  src/spice-option.c
> +src/spice-pulse.c
> +src/usb-acl-helper.c
>  src/usb-device-manager.c
>  src/usb-device-widget.c
>  src/usbutil.c
> +src/vmcstream.c
> +src/win-usb-driver-install.c
> diff --git a/src/channel-main.c b/src/channel-main.c
> index 6c0f238..40d5cff 100644
> --- a/src/channel-main.c
> +++ b/src/channel-main.c
> @@ -21,6 +21,8 @@
>  #include 
>  #include 
>  
> +#include 
> +
>  #include "glib-compat.h"
>  #include "spice-client.h"
>  #include "spice-common.h"
> @@ -3143,7 +3145,7 @@ void spice_main_file_copy_async(SpiceMainChannel 
> *channel,
>  spice_main_file_copy_async,
>  SPICE_CLIENT_ERROR,
>  SPICE_CLIENT_ERROR_FAILED,
> -"The agent is not connected");
> +_("The agent is not connected"));
>  return;
>  }
>  
> diff --git a/src/channel-port.c b/src/channel-port.c
> index 20ee2fa..86194ab 100644
> --- a/src/channel-port.c
> +++ b/src/channel-port.c
> @@ -23,6 +23,8 @@
>  #include "spice-marshal.h"
>  #include "glib-compat.h"
>  
> +#include 
> +
>  /**
>   * SECTION:channel-port
>   * @short_description: private communication channel
> @@ -295,7 +297,7 @@ void spice_port_write_async(SpicePortChannel *self,
>  g_task_report_new_error(self, callback,
>  user_data, spice_port_write_async,
>  SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
> -"The port is not opened");
> +_("The port is not opened"));
>  return;
>  }
>  
> diff --git a/src/channel-usbredir.c b/src/channel-usbredir.c
> index 4ddf7bf..824bc43 100644
> --- a/src/channel-usbredir.c
> +++ b/src/channel-usbredir.c
> @@ -344,14 +344,14 @@ void spice_usbredir_channel_connect_device_async(
>  if (!priv->host) {
>  g_task_return_new_error(task,
>  SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
> -"Error libusb context not set");
> +_("Error libusb context not set"));
>  goto done;
>  }
>  
>  if (priv->state != STATE_DISCONNECTED) {
>  g_task_return_new_error(task,
>  SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
> -"Error channel is busy");
> +_("Error channel is busy"));
>  goto done;
>  }
>  
> diff --git a/src/spice-channel.c b/src/spice-channel.c
> index dd32818..246609a 100644
> --- a/src/spice-channel.c
> +++ b/src/spice-channel.c
> @@ -2979,7 +2979,7 @@ void spice_channel_flush_async(SpiceChannel *self, 
> GCancellable *cancellable,
>  g_task_report_new_error(self, callback, user_data,
>  spice_channel_flush_async,
>  SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
> -"The channel is not ready yet");
> +_("The channel is not ready yet"));
>  return;
>  }
>  
> diff --git a/src/spice-pulse.c b/src/spice-pulse.c
> index 60a037c..5c3cfb7 100644
> --- a/src/spice-pulse.c
> +++ b/src/spice-pulse.c
> @@ -28,6 +28,8 @@
>  #include 
>  #include 
>  
> +#include 
> +
>  #define SPICE_PULSE_GET_PRIVATE(obj)  \
>  (G_TYPE_INSTANCE_GET_PRIVATE((obj), SPICE_TYPE_PULSE, SpicePulsePrivate))
>  
> @@ -995,7 +997,7 @@ static void complete_task(SpicePulse *pulse, struct 
> async_task *task, const gcha
>  g_task_return_new_error(task->task,
>  SPICE_CLIENT_ERROR,
>  SPICE_CLIENT_ERROR_FAILED,
> -"restore-info failed due %s",
> +_("restore-info failed due %s"),
>  err_msg);
>  /* Volume-info does not change if strea

Re: [Spice-devel] [PATCH 14/14] Add strings for translation

2016-01-18 Thread Marc-André Lureau
ack

- Original Message -
> While doing the work to use GTask isntead of GSimpleAsyncResult I've
> noticed a few error strings that were not marked to be translated.
> I am not exactly sure if it was intentional or not, but I do believe
> that our error messages should be translated.
> ---
>  po/POTFILES.in   |  6 ++
>  src/channel-main.c   |  4 +++-
>  src/channel-port.c   |  4 +++-
>  src/channel-usbredir.c   |  4 ++--
>  src/spice-channel.c  |  2 +-
>  src/spice-pulse.c|  8 +---
>  src/usb-acl-helper.c | 10 ++
>  src/usb-device-manager.c |  4 ++--
>  src/vmcstream.c  |  4 +++-
>  src/win-usb-driver-install.c | 16 +---
>  10 files changed, 40 insertions(+), 22 deletions(-)
> 
> diff --git a/po/POTFILES.in b/po/POTFILES.in
> index ad12609..7c79541 100644
> --- a/po/POTFILES.in
> +++ b/po/POTFILES.in
> @@ -1,8 +1,14 @@
> +src/channel-main.c
> +src/channel-port.c
>  src/channel-usbredir.c
>  src/desktop-integration.c
>  src/spice-channel.c
>  src/spice-cmdline.c
>  src/spice-option.c
> +src/spice-pulse.c
> +src/usb-acl-helper.c
>  src/usb-device-manager.c
>  src/usb-device-widget.c
>  src/usbutil.c
> +src/vmcstream.c
> +src/win-usb-driver-install.c
> diff --git a/src/channel-main.c b/src/channel-main.c
> index 6c0f238..40d5cff 100644
> --- a/src/channel-main.c
> +++ b/src/channel-main.c
> @@ -21,6 +21,8 @@
>  #include 
>  #include 
>  
> +#include 
> +
>  #include "glib-compat.h"
>  #include "spice-client.h"
>  #include "spice-common.h"
> @@ -3143,7 +3145,7 @@ void spice_main_file_copy_async(SpiceMainChannel
> *channel,
>  spice_main_file_copy_async,
>  SPICE_CLIENT_ERROR,
>  SPICE_CLIENT_ERROR_FAILED,
> -"The agent is not connected");
> +_("The agent is not connected"));
>  return;
>  }
>  
> diff --git a/src/channel-port.c b/src/channel-port.c
> index 20ee2fa..86194ab 100644
> --- a/src/channel-port.c
> +++ b/src/channel-port.c
> @@ -23,6 +23,8 @@
>  #include "spice-marshal.h"
>  #include "glib-compat.h"
>  
> +#include 
> +
>  /**
>   * SECTION:channel-port
>   * @short_description: private communication channel
> @@ -295,7 +297,7 @@ void spice_port_write_async(SpicePortChannel *self,
>  g_task_report_new_error(self, callback,
>  user_data, spice_port_write_async,
>  SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
> -"The port is not opened");
> +_("The port is not opened"));
>  return;
>  }
>  
> diff --git a/src/channel-usbredir.c b/src/channel-usbredir.c
> index 4ddf7bf..824bc43 100644
> --- a/src/channel-usbredir.c
> +++ b/src/channel-usbredir.c
> @@ -344,14 +344,14 @@ void spice_usbredir_channel_connect_device_async(
>  if (!priv->host) {
>  g_task_return_new_error(task,
>  SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
> -"Error libusb context not set");
> +_("Error libusb context not set"));
>  goto done;
>  }
>  
>  if (priv->state != STATE_DISCONNECTED) {
>  g_task_return_new_error(task,
>  SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
> -"Error channel is busy");
> +_("Error channel is busy"));
>  goto done;
>  }
>  
> diff --git a/src/spice-channel.c b/src/spice-channel.c
> index dd32818..246609a 100644
> --- a/src/spice-channel.c
> +++ b/src/spice-channel.c
> @@ -2979,7 +2979,7 @@ void spice_channel_flush_async(SpiceChannel *self,
> GCancellable *cancellable,
>  g_task_report_new_error(self, callback, user_data,
>  spice_channel_flush_async,
>  SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
> -"The channel is not ready yet");
> +_("The channel is not ready yet"));
>  return;
>  }
>  
> diff --git a/src/spice-pulse.c b/src/spice-pulse.c
> index 60a037c..5c3cfb7 100644
> --- a/src/spice-pulse.c
> +++ b/src/spice-pulse.c
> @@ -28,6 +28,8 @@
>  #include 
>  #include 
>  
> +#include 
> +
>  #define SPICE_PULSE_GET_PRIVATE(obj)  \
>  (G_TYPE_INSTANCE_GET_PRIVATE((obj), SPICE_TYPE_PULSE,
>  SpicePulsePrivate))
>  
> @@ -995,7 +997,7 @@ static void complete_task(SpicePulse *pulse, struct
> async_task *task, const gcha
>  g_task_return_new_error(task->task,
>  SPICE_CLIENT_ERROR,
>  SPICE_CLIENT_ERROR_FAILED,
> -"restore-info failed due %s",
> +_("restore-info failed due %s"),
>  err_msg);
>  /* Volume-info does not change if stream is not found */
>  } else if ((t

Re: [Spice-devel] [PATCH] Remove GSLice usage

2016-01-18 Thread Marc-André Lureau
Hi

- Original Message -
> It's being slowly deprecated im glib
> https://bugzilla.gnome.org/show_bug.cgi?id=754687
> ---
>  src/channel-display.c | 6 +++---
>  src/channel-smartcard.c   | 4 ++--
>  src/spice-channel-cache.h | 8 
>  src/spice-channel.c   | 8 
>  src/spice-grabsequence.c  | 8 
>  src/spice-util.c  | 4 ++--
>  src/wocky-http-proxy.c| 4 ++--
>  7 files changed, 21 insertions(+), 21 deletions(-)
> 
> diff --git a/src/channel-display.c b/src/channel-display.c
> index dc73235..6a474b1 100644
> --- a/src/channel-display.c
> +++ b/src/channel-display.c
> @@ -635,7 +635,7 @@ static void destroy_surface(gpointer data)
>  display_surface *surface = data;
>  
>  destroy_canvas(surface);
> -g_slice_free(display_surface, surface);
> +g_free(surface);
>  }
>  
>  static void spice_display_channel_init(SpiceDisplayChannel *channel)
> @@ -869,7 +869,7 @@ static void display_handle_mode(SpiceChannel *channel,
> SpiceMsgIn *in)
>  
>  g_warn_if_fail(c->mark == FALSE);
>  
> -surface = g_slice_new0(display_surface);
> +surface = g_new0(display_surface, 1);
>  surface->format  = mode->bits == 32 ?
>  SPICE_SURFACE_FMT_32_xRGB : SPICE_SURFACE_FMT_16_555;
>  surface->width   = mode->x_res;
> @@ -1674,7 +1674,7 @@ static void display_handle_surface_create(SpiceChannel
> *channel, SpiceMsgIn *in)
>  {
>  SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
>  SpiceMsgSurfaceCreate *create = spice_msg_in_parsed(in);
> -display_surface *surface = g_slice_new0(display_surface);
> +display_surface *surface = g_new0(display_surface, 1);
>  
>  surface->surface_id = create->surface_id;
>  surface->format = create->format;
> diff --git a/src/channel-smartcard.c b/src/channel-smartcard.c
> index b5535e6..e2e1aad 100644
> --- a/src/channel-smartcard.c
> +++ b/src/channel-smartcard.c
> @@ -241,7 +241,7 @@ smartcard_message_free(SpiceSmartcardChannelMessage
> *message)
>  {
>  if (message->message)
>  spice_msg_out_unref(message->message);
> -g_slice_free(SpiceSmartcardChannelMessage, message);
> +g_free(message);
>  }
>  
>  #if USE_SMARTCARD
> @@ -301,7 +301,7 @@ smartcard_message_new(VSCMsgType msg_type, SpiceMsgOut
> *msg_out)
>  {
>  SpiceSmartcardChannelMessage *message;
>  
> -message = g_slice_new0(SpiceSmartcardChannelMessage);
> +message = g_new0(SpiceSmartcardChannelMessage, 1);
>  message->message = msg_out;
>  message->message_type = msg_type;
>  
> diff --git a/src/spice-channel-cache.h b/src/spice-channel-cache.h
> index e609a67..75cc2cd 100644
> --- a/src/spice-channel-cache.h
> +++ b/src/spice-channel-cache.h
> @@ -37,7 +37,7 @@ typedef struct display_cache {
>  
>  static inline display_cache_item* cache_item_new(guint64 id, gboolean lossy)
>  {
> -display_cache_item *self = g_slice_new(display_cache_item);
> +display_cache_item *self = g_new(display_cache_item, 1);
>  self->id = id;
>  self->lossy = lossy;
>  self->ref_count = 1;
> @@ -46,12 +46,12 @@ static inline display_cache_item* cache_item_new(guint64
> id, gboolean lossy)
>  
>  static inline void cache_item_free(display_cache_item *self)
>  {
> -g_slice_free(display_cache_item, self);
> +g_free(self);
>  }
>  
>  static inline display_cache* cache_new(GDestroyNotify value_destroy)
>  {
> -display_cache * self = g_slice_new(display_cache);
> +display_cache * self = g_new(display_cache, 1);
>  self->table = g_hash_table_new_full(g_int64_hash, g_int64_equal,
> (GDestroyNotify) cache_item_free,
> value_destroy);
> @@ -131,7 +131,7 @@ static inline void cache_clear(display_cache *cache)
>  static inline void cache_free(display_cache *cache)
>  {
>  g_hash_table_unref(cache->table);
> -g_slice_free(display_cache, cache);
> +g_free(cache);
>  }
>  
>  G_END_DECLS
> diff --git a/src/spice-channel.c b/src/spice-channel.c
> index 41c94d0..ff85715 100644
> --- a/src/spice-channel.c
> +++ b/src/spice-channel.c
> @@ -471,7 +471,7 @@ SpiceMsgIn *spice_msg_in_new(SpiceChannel *channel)
>  
>  g_return_val_if_fail(channel != NULL, NULL);
>  
> -in = g_slice_new0(SpiceMsgIn);
> +in = g_new0(SpiceMsgIn, 1);
>  in->refcount = 1;
>  in->channel  = channel;
>  
> @@ -519,7 +519,7 @@ void spice_msg_in_unref(SpiceMsgIn *in)
>  } else {
>  g_free(in->data);
>  }
> -g_slice_free(SpiceMsgIn, in);
> +g_free(in);
>  }
>  
>  G_GNUC_INTERNAL
> @@ -624,7 +624,7 @@ SpiceMsgOut *spice_msg_out_new(SpiceChannel *channel, int
> type)
>  
>  g_return_val_if_fail(c != NULL, NULL);
>  
> -out = g_slice_new0(SpiceMsgOut);
> +out = g_new0(SpiceMsgOut, 1);
>  out->refcount = 1;
>  out->channel  = channel;
>  out->ro_check = msg_check_read_only(c->channel_type, type);
> @@ -660,7 +660,7 @@ void spice_msg_out_unref(Spice

[Spice-devel] [PATCH 07/14] spice-gstaudio: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Fabiano Fidêncio
Instead of using GSimpleAsyncResult, use the new GTask API, which is
much more straightforward.
---
 src/spice-gstaudio.c | 48 ++--
 1 file changed, 10 insertions(+), 38 deletions(-)

diff --git a/src/spice-gstaudio.c b/src/spice-gstaudio.c
index 096fea4..65fc173 100644
--- a/src/spice-gstaudio.c
+++ b/src/spice-gstaudio.c
@@ -570,16 +570,9 @@ static void 
spice_gstaudio_get_playback_volume_info_async(SpiceAudio *audio,
   GAsyncReadyCallback 
callback,
   gpointer user_data)
 {
-GSimpleAsyncResult *simple;
+GTask *task = g_task_new(audio, cancellable, callback, user_data);
 
-simple = g_simple_async_result_new(G_OBJECT(audio),
-   callback,
-   user_data,
-   
spice_gstaudio_get_playback_volume_info_async);
-g_simple_async_result_set_check_cancellable (simple, cancellable);
-
-g_simple_async_result_set_op_res_gboolean(simple, TRUE);
-g_simple_async_result_complete_in_idle(simple);
+g_task_return_boolean(task, TRUE);
 }
 
 static gboolean spice_gstaudio_get_playback_volume_info_finish(SpiceAudio 
*audio,
@@ -594,14 +587,9 @@ static gboolean 
spice_gstaudio_get_playback_volume_info_finish(SpiceAudio *audio
 gboolean lmute;
 gdouble vol;
 gboolean fake_channel = FALSE;
-GSimpleAsyncResult *simple = (GSimpleAsyncResult *) res;
-
-g_return_val_if_fail(g_simple_async_result_is_valid(res,
-G_OBJECT(audio), spice_gstaudio_get_playback_volume_info_async), 
FALSE);
+GTask *task = G_TASK(res);
 
-if (g_simple_async_result_propagate_error(simple, error)) {
-return FALSE;
-}
+g_return_val_if_fail(g_task_is_valid(task, audio), FALSE);
 
 if (p->playback.sink == NULL || p->playback.channels == 0) {
 SPICE_DEBUG("PlaybackChannel not created yet, force start");
@@ -647,7 +635,7 @@ static gboolean 
spice_gstaudio_get_playback_volume_info_finish(SpiceAudio *audio
 }
 }
 
-return g_simple_async_result_get_op_res_gboolean(simple);
+return g_task_propagate_boolean(task, error);
 }
 
 static void spice_gstaudio_get_record_volume_info_async(SpiceAudio *audio,
@@ -656,16 +644,9 @@ static void 
spice_gstaudio_get_record_volume_info_async(SpiceAudio *audio,
 GAsyncReadyCallback 
callback,
 gpointer user_data)
 {
-GSimpleAsyncResult *simple;
-
-simple = g_simple_async_result_new(G_OBJECT(audio),
-   callback,
-   user_data,
-   
spice_gstaudio_get_record_volume_info_async);
-g_simple_async_result_set_check_cancellable (simple, cancellable);
+GTask *task = g_task_new(audio, cancellable, callback, user_data);
 
-g_simple_async_result_set_op_res_gboolean(simple, TRUE);
-g_simple_async_result_complete_in_idle(simple);
+g_task_return_boolean(task, TRUE);
 }
 
 static gboolean spice_gstaudio_get_record_volume_info_finish(SpiceAudio *audio,
@@ -680,18 +661,9 @@ static gboolean 
spice_gstaudio_get_record_volume_info_finish(SpiceAudio *audio,
 gboolean lmute;
 gdouble vol;
 gboolean fake_channel = FALSE;
-GSimpleAsyncResult *simple = (GSimpleAsyncResult *) res;
+GTask *task = G_TASK(res);
 
-g_return_val_if_fail(g_simple_async_result_is_valid(res,
-G_OBJECT(audio), spice_gstaudio_get_record_volume_info_async), FALSE);
-
-if (g_simple_async_result_propagate_error(simple, error)) {
-/* set out args that should have new alloc'ed memory to NULL */
-if (volume != NULL) {
-*volume = NULL;
-}
-return FALSE;
-}
+g_return_val_if_fail(g_task_is_valid(task, audio), FALSE);
 
 if (p->record.src == NULL || p->record.channels == 0) {
 SPICE_DEBUG("RecordChannel not created yet, force start");
@@ -737,5 +709,5 @@ static gboolean 
spice_gstaudio_get_record_volume_info_finish(SpiceAudio *audio,
 }
 }
 
-return g_simple_async_result_get_op_res_gboolean(simple);
+return g_task_propagate_boolean(task, error);
 }
-- 
2.5.0

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH 05/14] smartcard-manager: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Fabiano Fidêncio
Instead of using GSimpleAsyncResult, use the new GTask API, which is
much more straightforward.
---
 src/smartcard-manager.c | 33 +
 1 file changed, 13 insertions(+), 20 deletions(-)

diff --git a/src/smartcard-manager.c b/src/smartcard-manager.c
index 6578328..2310ab6 100644
--- a/src/smartcard-manager.c
+++ b/src/smartcard-manager.c
@@ -476,8 +476,9 @@ end:
 return retval;
 }
 
-static void smartcard_manager_init_helper(GSimpleAsyncResult *res,
-  GObject *object,
+static void smartcard_manager_init_helper(GTask *task,
+  gpointer object,
+  gpointer task_data,
   GCancellable *cancellable)
 {
 static GOnce smartcard_manager_once = G_ONCE_INIT;
@@ -492,8 +493,10 @@ static void 
smartcard_manager_init_helper(GSimpleAsyncResult *res,
(GThreadFunc)smartcard_manager_init,
&args);
 if (args.err != NULL) {
-g_simple_async_result_set_from_error(res, args.err);
+g_task_return_error(task, args.err);
 g_error_free(args.err);
+} else {
+g_task_return_boolean(task, TRUE);
 }
 }
 
@@ -504,17 +507,10 @@ void spice_smartcard_manager_init_async(SpiceSession 
*session,
 GAsyncReadyCallback callback,
 gpointer opaque)
 {
-GSimpleAsyncResult *res;
+GTask *task = g_task_new(session, cancellable, callback, opaque);
 
-res = g_simple_async_result_new(G_OBJECT(session),
-callback,
-opaque,
-spice_smartcard_manager_init);
-g_simple_async_result_run_in_thread(res,
-smartcard_manager_init_helper,
-G_PRIORITY_DEFAULT,
-cancellable);
-g_object_unref(res);
+g_task_run_in_thread(task, smartcard_manager_init_helper);
+g_object_unref(task);
 }
 
 G_GNUC_INTERNAL
@@ -522,21 +518,18 @@ gboolean spice_smartcard_manager_init_finish(SpiceSession 
*session,
  GAsyncResult *result,
  GError **err)
 {
-GSimpleAsyncResult *simple;
+GTask *task = G_TASK(result);
 
 g_return_val_if_fail(SPICE_IS_SESSION(session), FALSE);
-g_return_val_if_fail(G_IS_SIMPLE_ASYNC_RESULT(result), FALSE);
+g_return_val_if_fail(G_IS_TASK(task), FALSE);
 
 SPICE_DEBUG("smartcard_manager_finish");
 
-simple = G_SIMPLE_ASYNC_RESULT(result);
-g_return_val_if_fail(g_simple_async_result_get_source_tag(simple) == 
spice_smartcard_manager_init, FALSE);
-if (g_simple_async_result_propagate_error(simple, err))
-return FALSE;
+g_return_val_if_fail(g_task_get_source_tag(task) == 
spice_smartcard_manager_init, FALSE);
 
 spice_smartcard_manager_update_monitor();
 
-return TRUE;
+return g_task_propagate_boolean(task, err);
 }
 
 /**
-- 
2.5.0

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH 12/14] win-usb-driver-install: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Fabiano Fidêncio
Instead of using GSimpleAsyncResult, use the new GTask API, which is
much more straightforward.
---
 src/win-usb-driver-install.c | 86 +---
 1 file changed, 41 insertions(+), 45 deletions(-)

diff --git a/src/win-usb-driver-install.c b/src/win-usb-driver-install.c
index 54e9b14..a7c4864 100644
--- a/src/win-usb-driver-install.c
+++ b/src/win-usb-driver-install.c
@@ -44,8 +44,7 @@
 
 struct _SpiceWinUsbDriverPrivate {
 USBClerkReply reply;
-GSimpleAsyncResult*result;
-GCancellable  *cancellable;
+GTask *task;
 HANDLEhandle;
 SpiceUsbDevice*device;
 };
@@ -144,16 +143,16 @@ void win_usb_driver_handle_reply_cb(GObject *gobject,
 
 if (err) {
 g_warning("failed to read reply from usbclerk (%s)", err->message);
-g_simple_async_result_take_error(priv->result, err);
+g_task_return_error(priv->task, err);
 goto failed_reply;
 }
 
 if (bytes == 0) {
 g_warning("unexpected EOF from usbclerk");
-g_simple_async_result_set_error(priv->result,
-SPICE_WIN_USB_DRIVER_ERROR,
-SPICE_WIN_USB_DRIVER_ERROR_FAILED,
-"unexpected EOF from usbclerk");
+g_task_return_new_error(priv->task,
+SPICE_WIN_USB_DRIVER_ERROR,
+SPICE_WIN_USB_DRIVER_ERROR_FAILED,
+"unexpected EOF from usbclerk");
 goto failed_reply;
 }
 
@@ -167,52 +166,53 @@ void win_usb_driver_handle_reply_cb(GObject *gobject,
 if (priv->reply.hdr.magic != USB_CLERK_MAGIC) {
 g_warning("usbclerk magic mismatch: mine=0x%04x  server=0x%04x",
   USB_CLERK_MAGIC, priv->reply.hdr.magic);
-g_simple_async_result_set_error(priv->result,
-SPICE_WIN_USB_DRIVER_ERROR,
-SPICE_WIN_USB_DRIVER_ERROR_MESSAGE,
-"usbclerk magic mismatch");
+g_task_return_new_error(priv->task,
+SPICE_WIN_USB_DRIVER_ERROR,
+SPICE_WIN_USB_DRIVER_ERROR_MESSAGE,
+"usbclerk magic mismatch");
 goto failed_reply;
 }
 
 if (priv->reply.hdr.version != USB_CLERK_VERSION) {
 g_warning("usbclerk version mismatch: mine=0x%04x  server=0x%04x",
   USB_CLERK_VERSION, priv->reply.hdr.version);
-g_simple_async_result_set_error(priv->result,
-SPICE_WIN_USB_DRIVER_ERROR,
-SPICE_WIN_USB_DRIVER_ERROR_MESSAGE,
-"usbclerk version mismatch");
+g_task_return_new_error(priv->task,
+SPICE_WIN_USB_DRIVER_ERROR,
+SPICE_WIN_USB_DRIVER_ERROR_MESSAGE,
+"usbclerk version mismatch");
 }
 
 if (priv->reply.hdr.type != USB_CLERK_REPLY) {
 g_warning("usbclerk message with unexpected type %d",
   priv->reply.hdr.type);
-g_simple_async_result_set_error(priv->result,
-SPICE_WIN_USB_DRIVER_ERROR,
-SPICE_WIN_USB_DRIVER_ERROR_MESSAGE,
-"usbclerk message with unexpected 
type");
+g_task_return_new_error(priv->task,
+SPICE_WIN_USB_DRIVER_ERROR,
+SPICE_WIN_USB_DRIVER_ERROR_MESSAGE,
+"usbclerk message with unexpected type");
 goto failed_reply;
 }
 
 if (priv->reply.hdr.size != bytes) {
 g_warning("usbclerk message size mismatch: read %"G_GSSIZE_FORMAT" 
bytes  hdr.size=%d",
   bytes, priv->reply.hdr.size);
-g_simple_async_result_set_error(priv->result,
-SPICE_WIN_USB_DRIVER_ERROR,
-SPICE_WIN_USB_DRIVER_ERROR_MESSAGE,
-"usbclerk message with unexpected 
size");
+g_task_return_new_error(priv->task,
+SPICE_WIN_USB_DRIVER_ERROR,
+SPICE_WIN_USB_DRIVER_ERROR_MESSAGE,
+"usbclerk message with unexpected size");
 goto failed_reply;
 }
 
 if (priv->reply.status == 0) {
-g_simple_async_result_set_error(priv->result,
-SPICE_WIN_USB_DRIVER_ERROR,
-SPICE_WIN_USB_DRIVER_ERROR_MESSAGE,
-"usbclerk error reply");
+g_task_return_new_error(priv->task,
+  

[Spice-devel] [PATCH 09/14] usb-acl-helper: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Fabiano Fidêncio
Instead of using GSimpleAsyncResult, use the new GTask API, which is
much more straightforward.
---
 src/usb-acl-helper.c | 76 
 1 file changed, 35 insertions(+), 41 deletions(-)

diff --git a/src/usb-acl-helper.c b/src/usb-acl-helper.c
index 6a49627..17e2b3c 100644
--- a/src/usb-acl-helper.c
+++ b/src/usb-acl-helper.c
@@ -35,10 +35,9 @@
 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), SPICE_TYPE_USB_ACL_HELPER, 
SpiceUsbAclHelperPrivate))
 
 struct _SpiceUsbAclHelperPrivate {
-GSimpleAsyncResult *result;
+GTask *task;
 GIOChannel *in_ch;
 GIOChannel *out_ch;
-GCancellable *cancellable;
 gulong cancellable_id;
 };
 
@@ -53,11 +52,11 @@ static void spice_usb_acl_helper_cleanup(SpiceUsbAclHelper 
*self)
 {
 SpiceUsbAclHelperPrivate *priv = self->priv;
 
-g_cancellable_disconnect(priv->cancellable, priv->cancellable_id);
-priv->cancellable = NULL;
+g_cancellable_disconnect(g_task_get_cancellable(priv->task),
+ priv->cancellable_id);
 priv->cancellable_id = 0;
 
-g_clear_object(&priv->result);
+g_clear_object(&priv->task);
 
 if (priv->in_ch) {
 g_io_channel_unref(priv->in_ch);
@@ -90,9 +89,9 @@ static void 
spice_usb_acl_helper_class_init(SpiceUsbAclHelperClass *klass)
 /* -- */
 /* callbacks  */
 
-static void async_result_set_cancelled(GSimpleAsyncResult *result)
+static void async_result_set_cancelled(GTask *task)
 {
-g_simple_async_result_set_error(result,
+g_task_return_new_error(task,
 G_IO_ERROR, G_IO_ERROR_CANCELLED,
 "Setting USB device node ACL cancelled");
 }
@@ -105,12 +104,13 @@ static gboolean cb_out_watch(GIOChannel*channel,
 SpiceUsbAclHelperPrivate *priv = self->priv;
 gboolean success = FALSE;
 GError *err = NULL;
+GCancellable *cancellable;
 GIOStatus status;
 gchar *string;
 gsize size;
 
 /* Check that we've not been cancelled */
-if (priv->result == NULL)
+if (priv->task == NULL)
 goto done;
 
 g_return_val_if_fail(channel == priv->out_ch, FALSE);
@@ -121,10 +121,11 @@ static gboolean cb_out_watch(GIOChannel*channel,
 string[strlen(string) - 1] = 0;
 if (!strcmp(string, "SUCCESS")) {
 success = TRUE;
+g_task_return_boolean(priv->task, TRUE);
 } else if (!strcmp(string, "CANCELED")) {
-async_result_set_cancelled(priv->result);
+async_result_set_cancelled(priv->task);
 } else {
-g_simple_async_result_set_error(priv->result,
+g_task_return_new_error(priv->task,
 SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
 "Error setting USB device node ACL: '%s'",
 string);
@@ -132,10 +133,10 @@ static gboolean cb_out_watch(GIOChannel*channel,
 g_free(string);
 break;
 case G_IO_STATUS_ERROR:
-g_simple_async_result_take_error(priv->result, err);
+g_task_return_error(priv->task, err);
 break;
 case G_IO_STATUS_EOF:
-g_simple_async_result_set_error(priv->result,
+g_task_return_new_error(priv->task,
 SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
 "Unexpected EOF reading from acl helper stdout");
 break;
@@ -143,16 +144,16 @@ static gboolean cb_out_watch(GIOChannel*channel,
 return TRUE; /* Wait for more input */
 }
 
-g_cancellable_disconnect(priv->cancellable, priv->cancellable_id);
-priv->cancellable = NULL;
+cancellable = g_task_get_cancellable(priv->task);
+g_cancellable_disconnect(cancellable, priv->cancellable_id);
+cancellable = NULL;
 priv->cancellable_id = 0;
 
-g_simple_async_result_complete_in_idle(priv->result);
-g_clear_object(&priv->result);
-
 if (!success)
 spice_usb_acl_helper_cleanup(self);
 
+g_clear_object(&priv->task);
+
 done:
 g_object_unref(self);
 return FALSE;
@@ -193,7 +194,7 @@ void spice_usb_acl_helper_open_acl(SpiceUsbAclHelper *self,
 g_return_if_fail(SPICE_IS_USB_ACL_HELPER(self));
 
 SpiceUsbAclHelperPrivate *priv = self->priv;
-GSimpleAsyncResult *result;
+GTask *task;
 GError *err = NULL;
 GIOStatus status;
 GPid helper_pid;
@@ -202,25 +203,24 @@ void spice_usb_acl_helper_open_acl(SpiceUsbAclHelper 
*self,
 gint in, out;
 gchar buf[128];
 
-result = g_simple_async_result_new(G_OBJECT(self), callback, user_data,
-   spice_usb_acl_helper_open_acl);
+task = g_task_new(self, cancellable, callback, user_data);
 
 if (priv->out_ch) {
-g_simple_async_result_set_error(result,
+  

[Spice-devel] [PATCH 03/14] channel-port: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Fabiano Fidêncio
Instead of using GSimpleAsyncResult, use the new GTask API, which is
much more straightforward.
---
 src/channel-port.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/channel-port.c b/src/channel-port.c
index 6e01caa..20ee2fa 100644
--- a/src/channel-port.c
+++ b/src/channel-port.c
@@ -292,7 +292,8 @@ void spice_port_write_async(SpicePortChannel *self,
 c = self->priv;
 
 if (!c->opened) {
-g_simple_async_report_error_in_idle(G_OBJECT(self), callback, 
user_data,
+g_task_report_new_error(self, callback,
+user_data, spice_port_write_async,
 SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
 "The port is not opened");
 return;
-- 
2.5.0

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH 06/14] spice-channel: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Fabiano Fidêncio
Instead of using GSimpleAsyncResult, use the new GTask API, which is
much more straightforward.
---
 src/spice-channel.c | 32 +---
 1 file changed, 13 insertions(+), 19 deletions(-)

diff --git a/src/spice-channel.c b/src/spice-channel.c
index ff85715..dd32818 100644
--- a/src/spice-channel.c
+++ b/src/spice-channel.c
@@ -2124,9 +2124,7 @@ static void spice_channel_flushed(SpiceChannel *channel, 
gboolean success)
 GSList *l;
 
 for (l = c->flushing; l != NULL; l = l->next) {
-GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT(l->data);
-g_simple_async_result_set_op_res_gboolean(result, success);
-g_simple_async_result_complete_in_idle(result);
+g_task_return_boolean(G_TASK(l->data), success);
 }
 
 g_slist_free_full(c->flushing, g_object_unref);
@@ -2970,7 +2968,7 @@ static void 
spice_channel_send_migration_handshake(SpiceChannel *channel)
 void spice_channel_flush_async(SpiceChannel *self, GCancellable *cancellable,
GAsyncReadyCallback callback, gpointer 
user_data)
 {
-GSimpleAsyncResult *simple;
+GTask *task;
 SpiceChannelPrivate *c;
 gboolean was_empty;
 
@@ -2978,26 +2976,25 @@ void spice_channel_flush_async(SpiceChannel *self, 
GCancellable *cancellable,
 c = self->priv;
 
 if (c->state != SPICE_CHANNEL_STATE_READY) {
-g_simple_async_report_error_in_idle(G_OBJECT(self), callback, 
user_data,
+g_task_report_new_error(self, callback, user_data,
+spice_channel_flush_async,
 SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
 "The channel is not ready yet");
 return;
 }
 
-simple = g_simple_async_result_new(G_OBJECT(self), callback, user_data,
-   spice_channel_flush_async);
+task = g_task_new(self, cancellable, callback, user_data);
 
 STATIC_MUTEX_LOCK(c->xmit_queue_lock);
 was_empty = g_queue_is_empty(&c->xmit_queue);
 STATIC_MUTEX_UNLOCK(c->xmit_queue_lock);
 if (was_empty) {
-g_simple_async_result_set_op_res_gboolean(simple, TRUE);
-g_simple_async_result_complete_in_idle(simple);
-g_object_unref(simple);
+g_task_return_boolean(task, TRUE);
+g_object_unref(task);
 return;
 }
 
-c->flushing = g_slist_append(c->flushing, simple);
+c->flushing = g_slist_append(c->flushing, task);
 }
 
 /**
@@ -3015,19 +3012,16 @@ void spice_channel_flush_async(SpiceChannel *self, 
GCancellable *cancellable,
 gboolean spice_channel_flush_finish(SpiceChannel *self, GAsyncResult *result,
 GError **error)
 {
-GSimpleAsyncResult *simple;
+GTask *task;
 
 g_return_val_if_fail(SPICE_IS_CHANNEL(self), FALSE);
 g_return_val_if_fail(result != NULL, FALSE);
 
-simple = (GSimpleAsyncResult *)result;
+task = G_TASK(result);
 
-if (g_simple_async_result_propagate_error(simple, error))
-return -1;
-
-g_return_val_if_fail(g_simple_async_result_is_valid(result, G_OBJECT(self),
-
spice_channel_flush_async), FALSE);
+g_return_val_if_fail(g_task_is_valid(task, self),
+ FALSE);
 
 CHANNEL_DEBUG(self, "flushed finished!");
-return g_simple_async_result_get_op_res_gboolean(simple);
+return g_task_propagate_boolean(task, error);
 }
-- 
2.5.0

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH 11/14] vmcstream: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Fabiano Fidêncio
Instead of using GSimpleAsyncResult, use the new GTask API, which is
much more straightforward.
---
 src/vmcstream.c | 129 +++-
 1 file changed, 52 insertions(+), 77 deletions(-)

diff --git a/src/vmcstream.c b/src/vmcstream.c
index 483dd5a..d9b62a0 100644
--- a/src/vmcstream.c
+++ b/src/vmcstream.c
@@ -27,7 +27,7 @@
 struct _SpiceVmcInputStream
 {
 GInputStream parent_instance;
-GSimpleAsyncResult *result;
+GTask *task;
 struct coroutine *coroutine;
 
 SpiceChannel *channel;
@@ -36,7 +36,6 @@ struct _SpiceVmcInputStream
 gsize count;
 gsize pos;
 
-GCancellable *cancellable;
 gulong cancel_id;
 };
 
@@ -118,11 +117,12 @@ spice_vmc_input_stream_co_data(SpiceVmcInputStream *self,
 self->coroutine = coroutine_self();
 
 while (size > 0) {
-SPICE_DEBUG("spicevmc co_data %p", self->result);
-if (!self->result)
+GCancellable *cancellable;
+SPICE_DEBUG("spicevmc co_data %p", self->task);
+if (!self->task)
 coroutine_yield(NULL);
 
-g_return_if_fail(self->result != NULL);
+g_return_if_fail(self->task != NULL);
 
 gsize min = MIN(self->count, size);
 memcpy(self->buffer, data, min);
@@ -139,14 +139,13 @@ spice_vmc_input_stream_co_data(SpiceVmcInputStream *self,
 if (self->all && min > 0 && self->pos != self->count)
 continue;
 
-g_simple_async_result_set_op_res_gssize(self->result, self->pos);
+g_task_return_int(self->task, self->pos);
+
+cancellable = g_task_get_cancellable(self->task);
+if (cancellable)
+g_cancellable_disconnect(cancellable, self->cancel_id);
 
-g_simple_async_result_complete_in_idle(self->result);
-g_clear_object(&self->result);
-if (self->cancellable) {
-g_cancellable_disconnect(self->cancellable, self->cancel_id);
-g_clear_object(&self->cancellable);
-}
+g_clear_object(&self->task);
 }
 
 self->coroutine = NULL;
@@ -158,13 +157,12 @@ read_cancelled(GCancellable *cancellable,
 {
 SpiceVmcInputStream *self = SPICE_VMC_INPUT_STREAM(user_data);
 
-SPICE_DEBUG("read cancelled, %p", self->result);
-g_simple_async_result_set_error(self->result,
-G_IO_ERROR, G_IO_ERROR_CANCELLED,
-"read cancelled");
-g_simple_async_result_complete_in_idle(self->result);
+SPICE_DEBUG("read cancelled, %p", self->task);
+g_task_return_new_error(self->task,
+G_IO_ERROR, G_IO_ERROR_CANCELLED,
+"read cancelled");
 
-g_clear_object(&self->result);
+g_clear_object(&self->task);
 
 /* See FIXME */
 /* if (self->cancellable) { */
@@ -183,21 +181,20 @@ spice_vmc_input_stream_read_all_async(GInputStream
*stream,
   gpointer user_data)
 {
 SpiceVmcInputStream *self = SPICE_VMC_INPUT_STREAM(stream);
-GSimpleAsyncResult *result;
+GTask *task;
 
 /* no concurrent read permitted by ginputstream */
-g_return_if_fail(self->result == NULL);
-g_return_if_fail(self->cancellable == NULL);
+g_return_if_fail(self->task == NULL);
+g_return_if_fail(g_task_get_cancellable(self->task) == NULL);
 self->all = TRUE;
 self->buffer = buffer;
 self->count = count;
 self->pos = 0;
-result = g_simple_async_result_new(G_OBJECT(self),
-   callback,
-   user_data,
-   spice_vmc_input_stream_read_async);
-self->result = result;
-self->cancellable = g_object_ref(cancellable);
+task = g_task_new(self,
+  cancellable,
+  callback,
+  user_data);
+self->task = task;
 if (cancellable)
 self->cancel_id =
 g_cancellable_connect(cancellable, G_CALLBACK(read_cancelled), 
self, NULL);
@@ -211,27 +208,19 @@ spice_vmc_input_stream_read_all_finish(GInputStream 
*stream,
GAsyncResult *result,
GError **error)
 {
-GSimpleAsyncResult *simple;
+GTask *task = G_TASK(result);
+GCancellable *cancellable;
 SpiceVmcInputStream *self = SPICE_VMC_INPUT_STREAM(stream);
 
-g_return_val_if_fail(g_simple_async_result_is_valid(result,
-G_OBJECT(self),
-
spice_vmc_input_stream_read_async),
- -1);
-
-simple = (GSimpleAsyncResult *)result;
+g_return_val_if_fail(g_task_is_valid(task, self), -1);
 
 /* FIXME: calling _finish() is required. Disconnecting in
read_cancelled() causes a deadlock. #705395 */
-if (self->cancellable) {
-g_cancellable_d

[Spice-devel] [PATCH 02/14] channel-main: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Fabiano Fidêncio
Instead of using GSimpleAsyncResult, use the new GTask API, which is
much more straightforward.
---
 src/channel-main.c | 83 ++
 1 file changed, 34 insertions(+), 49 deletions(-)

diff --git a/src/channel-main.c b/src/channel-main.c
index 06dd121..6c0f238 100644
--- a/src/channel-main.c
+++ b/src/channel-main.c
@@ -923,10 +923,9 @@ static gboolean flush_foreach_remove(gpointer key 
G_GNUC_UNUSED,
  gpointer value, gpointer user_data)
 {
 gboolean success = GPOINTER_TO_UINT(user_data);
-GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT(value);
+GTask *result = value;
+g_task_return_boolean(result, success);
 
-g_simple_async_result_set_op_res_gboolean(result, success);
-g_simple_async_result_complete_in_idle(result);
 return TRUE;
 }
 
@@ -940,38 +939,31 @@ static void file_xfer_flushed(SpiceMainChannel *channel, 
gboolean success)
 static void file_xfer_flush_async(SpiceMainChannel *channel, GCancellable 
*cancellable,
   GAsyncReadyCallback callback, gpointer 
user_data)
 {
-GSimpleAsyncResult *simple;
+GTask *task;
 SpiceMainChannelPrivate *c = channel->priv;
 gboolean was_empty;
 
-simple = g_simple_async_result_new(G_OBJECT(channel), callback, user_data,
-   file_xfer_flush_async);
+task = g_task_new(channel, cancellable, callback, user_data);
 
 was_empty = g_queue_is_empty(c->agent_msg_queue);
 if (was_empty) {
-g_simple_async_result_set_op_res_gboolean(simple, TRUE);
-g_simple_async_result_complete_in_idle(simple);
-g_object_unref(simple);
+g_task_return_boolean(task, TRUE);
+g_object_unref(task);
 return;
 }
 
 /* wait until the last message currently in the queue has been sent */
-g_hash_table_insert(c->flushing, g_queue_peek_tail(c->agent_msg_queue), 
simple);
+g_hash_table_insert(c->flushing, g_queue_peek_tail(c->agent_msg_queue), 
task);
 }
 
 static gboolean file_xfer_flush_finish(SpiceMainChannel *channel, GAsyncResult 
*result,
GError **error)
 {
-GSimpleAsyncResult *simple = (GSimpleAsyncResult *)result;
+GTask *task = G_TASK(result);
 
-g_return_val_if_fail(g_simple_async_result_is_valid(result,
-G_OBJECT(channel), file_xfer_flush_async), FALSE);
+g_return_val_if_fail(g_task_is_valid(result, channel), FALSE);
 
-if (g_simple_async_result_propagate_error(simple, error)) {
-return FALSE;
-}
-
-return g_simple_async_result_get_op_res_gboolean(simple);
+return g_task_propagate_boolean(task, error);
 }
 
 /* coroutine context */
@@ -982,16 +974,15 @@ static void agent_send_msg_queue(SpiceMainChannel 
*channel)
 
 while (c->agent_tokens > 0 &&
!g_queue_is_empty(c->agent_msg_queue)) {
-GSimpleAsyncResult *simple;
+GTask *task;
 c->agent_tokens--;
 out = g_queue_pop_head(c->agent_msg_queue);
 spice_msg_out_send_internal(out);
 
-simple = g_hash_table_lookup(c->flushing, out);
-if (simple) {
+task = g_hash_table_lookup(c->flushing, out);
+if (task) {
 /* if there's a flush task waiting for this message, finish it */
-g_simple_async_result_set_op_res_gboolean(simple, TRUE);
-g_simple_async_result_complete_in_idle(simple);
+g_task_return_boolean(task, TRUE);
 g_hash_table_remove(c->flushing, out);
 }
 }
@@ -1776,7 +1767,7 @@ static void file_xfer_close_cb(GObject  *object,
GAsyncResult *close_res,
gpointer  user_data)
 {
-GSimpleAsyncResult *res;
+GTask *task;
 SpiceFileTransferTask *self;
 GError *error = NULL;
 
@@ -1794,15 +1785,15 @@ static void file_xfer_close_cb(GObject  *object,
 
 /* Notify to user that files have been transferred or something error
happened. */
-res = g_simple_async_result_new(G_OBJECT(self->priv->channel),
-self->priv->callback,
-self->priv->user_data,
-spice_main_file_copy_async);
+task = g_task_new(self->priv->channel,
+  self->priv->cancellable,
+  self->priv->callback,
+  self->priv->user_data);
 if (self->priv->error) {
-g_simple_async_result_take_error(res, self->priv->error);
-g_simple_async_result_set_op_res_gboolean(res, FALSE);
+g_task_return_error(task, self->priv->error);
+g_task_return_boolean(task, FALSE);
 } else {
-g_simple_async_result_set_op_res_gboolean(res, TRUE);
+g_task_return_boolean(task, TRUE);
 if (spice_util_get_debug()) {
 gint64 now = g_get_monotonic_time();
 gchar 

[Spice-devel] [PATCH 13/14] wocky-http-proxy: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Fabiano Fidêncio
Instead of using GSimpleAsyncResult, use the new GTask API, which is
much more straightforward.
---
 src/wocky-http-proxy.c | 47 ++-
 1 file changed, 18 insertions(+), 29 deletions(-)

diff --git a/src/wocky-http-proxy.c b/src/wocky-http-proxy.c
index d84cd72..f079e10 100644
--- a/src/wocky-http-proxy.c
+++ b/src/wocky-http-proxy.c
@@ -254,14 +254,13 @@ error:
 
 typedef struct
 {
-  GSimpleAsyncResult *simple;
+  GTask *task;
   GIOStream *io_stream;
   gchar *buffer;
   gssize length;
   gssize offset;
   GDataInputStream *data_in;
   gboolean has_cred;
-  GCancellable *cancellable;
 } ConnectAsyncData;
 
 static void request_write_cb (GObject *source,
@@ -282,26 +281,22 @@ free_connect_data (ConnectAsyncData *data)
   if (data->data_in != NULL)
 g_object_unref (data->data_in);
 
-  if (data->cancellable != NULL)
-g_object_unref (data->cancellable);
-
   g_free (data);
 }
 
 static void
 complete_async_from_error (ConnectAsyncData *data, GError *error)
 {
-  GSimpleAsyncResult *simple = data->simple;
+  GTask *task = data->task;
 
   if (error == NULL)
 g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_PROXY_FAILED,
 "HTTP proxy server closed connection unexpectedly.");
 
-  g_simple_async_result_set_from_error (data->simple, error);
+  g_task_return_error(data->task, error);
   g_error_free (error);
-  g_simple_async_result_set_op_res_gpointer (simple, NULL, NULL);
-  g_simple_async_result_complete (simple);
-  g_object_unref (simple);
+  g_task_return_pointer(task, NULL, NULL);
+  g_object_unref (task);
 }
 
 static void
@@ -312,7 +307,7 @@ do_write (GAsyncReadyCallback callback, ConnectAsyncData 
*data)
   g_output_stream_write_async (out,
   data->buffer + data->offset,
   data->length - data->offset,
-  G_PRIORITY_DEFAULT, data->cancellable,
+  G_PRIORITY_DEFAULT, g_task_get_cancellable(data->task),
   callback, data);
 }
 
@@ -357,24 +352,22 @@ wocky_http_proxy_connect_async (GProxy *proxy,
 GAsyncReadyCallback callback,
 gpointer user_data)
 {
-  GSimpleAsyncResult *simple;
+  GTask *task;
   ConnectAsyncData *data;
 
-  simple = g_simple_async_result_new (G_OBJECT (proxy),
-  callback, user_data,
-  wocky_http_proxy_connect_async);
+  task = g_task_new (proxy,
+ cancellable,
+ callback,
+ user_data);
 
   data = g_new0 (ConnectAsyncData, 1);
-  if (cancellable != NULL)
-data->cancellable = g_object_ref (cancellable);
-  data->simple = simple;
+  data->task = task;
 
   data->buffer = create_request (proxy_address, &data->has_cred);
   data->length = strlen (data->buffer);
   data->offset = 0;
 
-  g_simple_async_result_set_op_res_gpointer (simple, data,
- (GDestroyNotify) 
free_connect_data);
+  g_task_return_pointer (task, data, (GDestroyNotify) free_connect_data);
 
   if (WOCKY_IS_HTTPS_PROXY (proxy))
 {
@@ -435,7 +428,7 @@ request_write_cb (GObject *source,
   g_data_input_stream_read_until_async (data->data_in,
   HTTP_END_MARKER,
   G_PRIORITY_DEFAULT,
-  data->cancellable,
+  g_task_get_cancellable(data->task),
   reply_read_cb, data);
 
 }
@@ -468,8 +461,7 @@ reply_read_cb (GObject *source,
   return;
 }
 
-  g_simple_async_result_complete (data->simple);
-  g_object_unref (data->simple);
+  g_object_unref (data->task);
 }
 
 static GIOStream *
@@ -477,13 +469,10 @@ wocky_http_proxy_connect_finish (GProxy *proxy,
 GAsyncResult *result,
 GError **error)
 {
-  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
-  ConnectAsyncData *data = g_simple_async_result_get_op_res_gpointer (simple);
-
-  if (g_simple_async_result_propagate_error (simple, error))
-return NULL;
+  GTask *task = G_TASK (result);
+  ConnectAsyncData *data = g_task_propagate_pointer (task, error);
 
-  return g_object_ref (data->io_stream);
+  return data ? g_object_ref (data->io_stream) : NULL;
 }
 
 static gboolean
-- 
2.5.0

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH 14/14] Add strings for translation

2016-01-18 Thread Fabiano Fidêncio
While doing the work to use GTask isntead of GSimpleAsyncResult I've
noticed a few error strings that were not marked to be translated.
I am not exactly sure if it was intentional or not, but I do believe
that our error messages should be translated.
---
 po/POTFILES.in   |  6 ++
 src/channel-main.c   |  4 +++-
 src/channel-port.c   |  4 +++-
 src/channel-usbredir.c   |  4 ++--
 src/spice-channel.c  |  2 +-
 src/spice-pulse.c|  8 +---
 src/usb-acl-helper.c | 10 ++
 src/usb-device-manager.c |  4 ++--
 src/vmcstream.c  |  4 +++-
 src/win-usb-driver-install.c | 16 +---
 10 files changed, 40 insertions(+), 22 deletions(-)

diff --git a/po/POTFILES.in b/po/POTFILES.in
index ad12609..7c79541 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,8 +1,14 @@
+src/channel-main.c
+src/channel-port.c
 src/channel-usbredir.c
 src/desktop-integration.c
 src/spice-channel.c
 src/spice-cmdline.c
 src/spice-option.c
+src/spice-pulse.c
+src/usb-acl-helper.c
 src/usb-device-manager.c
 src/usb-device-widget.c
 src/usbutil.c
+src/vmcstream.c
+src/win-usb-driver-install.c
diff --git a/src/channel-main.c b/src/channel-main.c
index 6c0f238..40d5cff 100644
--- a/src/channel-main.c
+++ b/src/channel-main.c
@@ -21,6 +21,8 @@
 #include 
 #include 
 
+#include 
+
 #include "glib-compat.h"
 #include "spice-client.h"
 #include "spice-common.h"
@@ -3143,7 +3145,7 @@ void spice_main_file_copy_async(SpiceMainChannel *channel,
 spice_main_file_copy_async,
 SPICE_CLIENT_ERROR,
 SPICE_CLIENT_ERROR_FAILED,
-"The agent is not connected");
+_("The agent is not connected"));
 return;
 }
 
diff --git a/src/channel-port.c b/src/channel-port.c
index 20ee2fa..86194ab 100644
--- a/src/channel-port.c
+++ b/src/channel-port.c
@@ -23,6 +23,8 @@
 #include "spice-marshal.h"
 #include "glib-compat.h"
 
+#include 
+
 /**
  * SECTION:channel-port
  * @short_description: private communication channel
@@ -295,7 +297,7 @@ void spice_port_write_async(SpicePortChannel *self,
 g_task_report_new_error(self, callback,
 user_data, spice_port_write_async,
 SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
-"The port is not opened");
+_("The port is not opened"));
 return;
 }
 
diff --git a/src/channel-usbredir.c b/src/channel-usbredir.c
index 4ddf7bf..824bc43 100644
--- a/src/channel-usbredir.c
+++ b/src/channel-usbredir.c
@@ -344,14 +344,14 @@ void spice_usbredir_channel_connect_device_async(
 if (!priv->host) {
 g_task_return_new_error(task,
 SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
-"Error libusb context not set");
+_("Error libusb context not set"));
 goto done;
 }
 
 if (priv->state != STATE_DISCONNECTED) {
 g_task_return_new_error(task,
 SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
-"Error channel is busy");
+_("Error channel is busy"));
 goto done;
 }
 
diff --git a/src/spice-channel.c b/src/spice-channel.c
index dd32818..246609a 100644
--- a/src/spice-channel.c
+++ b/src/spice-channel.c
@@ -2979,7 +2979,7 @@ void spice_channel_flush_async(SpiceChannel *self, 
GCancellable *cancellable,
 g_task_report_new_error(self, callback, user_data,
 spice_channel_flush_async,
 SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
-"The channel is not ready yet");
+_("The channel is not ready yet"));
 return;
 }
 
diff --git a/src/spice-pulse.c b/src/spice-pulse.c
index 60a037c..5c3cfb7 100644
--- a/src/spice-pulse.c
+++ b/src/spice-pulse.c
@@ -28,6 +28,8 @@
 #include 
 #include 
 
+#include 
+
 #define SPICE_PULSE_GET_PRIVATE(obj)  \
 (G_TYPE_INSTANCE_GET_PRIVATE((obj), SPICE_TYPE_PULSE, SpicePulsePrivate))
 
@@ -995,7 +997,7 @@ static void complete_task(SpicePulse *pulse, struct 
async_task *task, const gcha
 g_task_return_new_error(task->task,
 SPICE_CLIENT_ERROR,
 SPICE_CLIENT_ERROR_FAILED,
-"restore-info failed due %s",
+_("restore-info failed due %s"),
 err_msg);
 /* Volume-info does not change if stream is not found */
 } else if ((task->is_playback == TRUE && p->playback.info_updated == 
FALSE) ||
@@ -1004,7 +1006,7 @@ static void complete_task(SpicePulse *pulse, struct 
async_task *task, const gcha
 g_task_return_new_error(task->task,
 SPICE_CLIENT_ERROR,
 SPICE_CLIENT_ER

[Spice-devel] [PATCH 10/14] usb-device-manager: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Fabiano Fidêncio
Instead of using GSimpleAsyncResult, use the new GTask API, which is
much more straightforward.
---
 src/usb-device-manager.c | 61 
 1 file changed, 30 insertions(+), 31 deletions(-)

diff --git a/src/usb-device-manager.c b/src/usb-device-manager.c
index c62f56e..1840177 100644
--- a/src/usb-device-manager.c
+++ b/src/usb-device-manager.c
@@ -1055,15 +1055,16 @@ static void spice_usb_device_manager_channel_connect_cb(
 GObject *gobject, GAsyncResult *channel_res, gpointer user_data)
 {
 SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(gobject);
-GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT(user_data);
+GTask *task = G_TASK(user_data);
 GError *err = NULL;
 
 spice_usbredir_channel_connect_device_finish(channel, channel_res, &err);
-if (err) {
-g_simple_async_result_take_error(result, err);
-}
-g_simple_async_result_complete(result);
-g_object_unref(result);
+if (err)
+g_task_return_error(task, err);
+else
+g_task_return_boolean(task, TRUE);
+
+g_object_unref(task);
 }
 
 #ifdef G_OS_WIN32
@@ -1229,7 +1230,7 @@ static void 
spice_usb_device_manager_check_redir_on_connect(
 SpiceUsbDeviceManager *self, SpiceChannel *channel)
 {
 SpiceUsbDeviceManagerPrivate *priv = self->priv;
-GSimpleAsyncResult *result;
+GTask *task;
 SpiceUsbDevice *device;
 libusb_device *libdev;
 guint i;
@@ -1254,15 +1255,19 @@ static void 
spice_usb_device_manager_check_redir_on_connect(
 libdev, 0) == 0) {
 /* Note: re-uses spice_usb_device_manager_connect_device_async's
completion handling code! */
-result = g_simple_async_result_new(G_OBJECT(self),
-   spice_usb_device_manager_auto_connect_cb,
-   spice_usb_device_ref(device),
-   spice_usb_device_manager_connect_device_async);
+task = g_task_new(self,
+  NULL,
+  spice_usb_device_manager_auto_connect_cb,
+  spice_usb_device_ref(device));
+
+g_task_set_source_tag(task,
+  spice_usb_device_manager_connect_device_async);
+
 spice_usbredir_channel_connect_device_async(
SPICE_USBREDIR_CHANNEL(channel),
libdev, device, NULL,
spice_usb_device_manager_channel_connect_cb,
-   result);
+   task);
 libusb_unref_device(libdev);
 return; /* We've taken the channel! */
 }
@@ -1401,15 +1406,14 @@ 
_spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
GAsyncReadyCallback callback,
gpointer user_data)
 {
-GSimpleAsyncResult *result;
+GTask *task;
 
 g_return_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self));
 g_return_if_fail(device != NULL);
 
 SPICE_DEBUG("connecting device %p", device);
 
-result = g_simple_async_result_new(G_OBJECT(self), callback, user_data,
-   spice_usb_device_manager_connect_device_async);
+task = g_task_new(self, cancellable, callback, user_data);
 
 #ifdef USE_USBREDIR
 SpiceUsbDeviceManagerPrivate *priv = self->priv;
@@ -1417,7 +1421,7 @@ 
_spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
 guint i;
 
 if (spice_usb_device_manager_is_device_connected(self, device)) {
-g_simple_async_result_set_error(result,
+g_task_return_new_error(task,
 SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
 "Cannot connect an already connected usb device");
 goto done;
@@ -1441,10 +1445,10 @@ 
_spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
 g_ptr_array_remove(priv->devices, device);
 g_signal_emit(self, signals[DEVICE_REMOVED], 0, device);
 spice_usb_device_unref(device);
-g_simple_async_result_set_error(result,
-SPICE_CLIENT_ERROR,
-SPICE_CLIENT_ERROR_FAILED,
-_("Device was not found"));
+g_task_return_new_error(task,
+SPICE_CLIENT_ERROR,
+SPICE_CLIENT_ERROR_FAILED,
+_("Device was not found"));
 goto done;
 }
 #endif
@@ -1453,20 +1457,19 @@ 
_spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
  device,
  cancellable,
   

[Spice-devel] [PATCH 08/14] spice-pulse: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Fabiano Fidêncio
Instead of using GSimpleAsyncResult, use the new GTask API, which is
much more straightforward.
---
 src/spice-pulse.c | 96 +++
 1 file changed, 33 insertions(+), 63 deletions(-)

diff --git a/src/spice-pulse.c b/src/spice-pulse.c
index 22db893..60a037c 100644
--- a/src/spice-pulse.c
+++ b/src/spice-pulse.c
@@ -34,13 +34,12 @@
 struct async_task {
 SpicePulse *pulse;
 SpiceMainChannel   *main_channel;
-GSimpleAsyncResult *res;
+GTask  *task;
 GAsyncReadyCallbackcallback;
 gpointer   user_data;
 gboolean   is_playback;
 pa_operation   *pa_op;
 gulong cancel_id;
-GCancellable   *cancellable;
 };
 
 struct stream {
@@ -941,8 +940,8 @@ static gboolean free_async_task(gpointer user_data)
 g_object_unref(task->pulse);
 }
 
-if (task->res)
-g_object_unref(task->res);
+if (task->task)
+g_object_unref(task->task);
 
 if (task->main_channel)
 g_object_unref(task->main_channel);
@@ -950,10 +949,9 @@ static gboolean free_async_task(gpointer user_data)
 if (task->pa_op != NULL)
 pa_operation_unref(task->pa_op);
 
-if (task->cancel_id != 0) {
-g_cancellable_disconnect(task->cancellable, task->cancel_id);
-g_clear_object(&task->cancellable);
-}
+if (task->cancel_id != 0)
+g_cancellable_disconnect(g_task_get_cancellable(task->task),
+ task->cancel_id);
 
 g_free(task);
 return G_SOURCE_REMOVE;
@@ -981,14 +979,6 @@ static void cancel_task(GCancellable *cancellable, 
gpointer user_data)
 task->pulse->priv->pending_restore_task = NULL;
 }
 
-#if !GLIB_CHECK_VERSION(2,32,0)
-/* g_simple_async_result_set_check_cancellable is not present. Set an error
- * in the GSimpleAsyncResult in case of _finish functions is called */
-g_simple_async_result_set_error(task->res,
-SPICE_CLIENT_ERROR,
-SPICE_CLIENT_ERROR_FAILED,
-"Operation was cancelled");
-#endif
 /* FIXME: https://bugzilla.gnome.org/show_bug.cgi?id=705395
  * Free the memory in idle */
 g_idle_add(free_async_task, task);
@@ -1001,27 +991,23 @@ static void complete_task(SpicePulse *pulse, struct 
async_task *task, const gcha
 
 /* If we do have any err_msg, we failed */
 if (err_msg != NULL) {
-g_simple_async_result_set_op_res_gboolean(task->res, FALSE);
-g_simple_async_result_set_error(task->res,
-SPICE_CLIENT_ERROR,
-SPICE_CLIENT_ERROR_FAILED,
-"restore-info failed due %s",
-err_msg);
+g_task_return_boolean(task->task, FALSE);
+g_task_return_new_error(task->task,
+SPICE_CLIENT_ERROR,
+SPICE_CLIENT_ERROR_FAILED,
+"restore-info failed due %s",
+err_msg);
 /* Volume-info does not change if stream is not found */
 } else if ((task->is_playback == TRUE && p->playback.info_updated == 
FALSE) ||
(task->is_playback == FALSE && p->record.info_updated == 
FALSE)) {
-g_simple_async_result_set_op_res_gboolean(task->res, FALSE);
-g_simple_async_result_set_error(task->res,
-SPICE_CLIENT_ERROR,
-SPICE_CLIENT_ERROR_FAILED,
-"Stream not found by pulse");
+g_task_return_boolean(task->task, FALSE);
+g_task_return_new_error(task->task,
+SPICE_CLIENT_ERROR,
+SPICE_CLIENT_ERROR_FAILED,
+"Stream not found by pulse");
 } else {
-g_simple_async_result_set_op_res_gboolean(task->res, TRUE);
+g_task_return_boolean(task->task, TRUE);
 }
-
-/* As all async calls to PulseAudio are done with glib mainloop, it is
- * safe to complete the operation synchronously here. */
-g_simple_async_result_complete(task->res);
 }
 
 static void spice_pulse_complete_async_task(struct async_task *task, const 
gchar *err_msg)
@@ -1157,19 +1143,13 @@ static void pulse_stream_restore_info_async(gboolean 
is_playback,
 gpointer user_data)
 {
 SpicePulsePrivate *p = SPICE_PULSE(audio)->priv;
-GSimpleAsyncResult *simple;
+GTask *res;
 struct async_task *task = g_malloc0(sizeof(struct async_task));
 pa_operation *op = NULL;
 
-simple = g_simple_async_result_new(G_OBJECT(audio),
-   callback,
-   

[Spice-devel] [PATCH 04/14] channel-usbredir: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Fabiano Fidêncio
Instead of using GSimpleAsyncResult, use the new GTask API, which is
much more straightforward.
---
 src/channel-usbredir.c | 39 +--
 1 file changed, 17 insertions(+), 22 deletions(-)

diff --git a/src/channel-usbredir.c b/src/channel-usbredir.c
index 0be72ba..4ddf7bf 100644
--- a/src/channel-usbredir.c
+++ b/src/channel-usbredir.c
@@ -76,7 +76,7 @@ struct _SpiceUsbredirChannelPrivate {
 int read_buf_size;
 enum SpiceUsbredirChannelState state;
 #if USE_POLKIT
-GSimpleAsyncResult *result;
+GTask *task;
 SpiceUsbAclHelper *acl_helper;
 #endif
 };
@@ -297,12 +297,14 @@ static void spice_usbredir_channel_open_acl_cb(
 spice_usbredir_channel_open_device(channel, &err);
 }
 if (err) {
-g_simple_async_result_take_error(priv->result, err);
+g_task_return_error(priv->task, err);
 libusb_unref_device(priv->device);
 priv->device = NULL;
 g_boxed_free(spice_usb_device_get_type(), priv->spice_device);
 priv->spice_device = NULL;
 priv->state  = STATE_DISCONNECTED;
+} else {
+g_task_return_boolean(priv->task, TRUE);
 }
 
 spice_usb_acl_helper_close_acl(priv->acl_helper);
@@ -310,8 +312,7 @@ static void spice_usbredir_channel_open_acl_cb(
 g_object_set(spice_channel_get_session(SPICE_CHANNEL(channel)),
  "inhibit-keyboard-grab", FALSE, NULL);
 
-g_simple_async_result_complete_in_idle(priv->result);
-g_clear_object(&priv->result);
+g_clear_object(&priv->task);
 }
 #endif
 
@@ -325,7 +326,7 @@ void spice_usbredir_channel_connect_device_async(
   gpointer  user_data)
 {
 SpiceUsbredirChannelPrivate *priv = channel->priv;
-GSimpleAsyncResult *result;
+GTask *task;
 #if ! USE_POLKIT
 GError *err = NULL;
 #endif
@@ -338,18 +339,17 @@ void spice_usbredir_channel_connect_device_async(
   spice_usb_device_get_pid(spice_device),
   spice_device, channel);
 
-result = g_simple_async_result_new(G_OBJECT(channel), callback, user_data,
- spice_usbredir_channel_connect_device_async);
+task = g_task_new(channel, cancellable, callback, user_data);
 
 if (!priv->host) {
-g_simple_async_result_set_error(result,
+g_task_return_new_error(task,
 SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
 "Error libusb context not set");
 goto done;
 }
 
 if (priv->state != STATE_DISCONNECTED) {
-g_simple_async_result_set_error(result,
+g_task_return_new_error(task,
 SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
 "Error channel is busy");
 goto done;
@@ -359,7 +359,7 @@ void spice_usbredir_channel_connect_device_async(
 priv->spice_device = g_boxed_copy(spice_usb_device_get_type(),
   spice_device);
 #if USE_POLKIT
-priv->result = result;
+priv->task = task;
 priv->state  = STATE_WAITING_FOR_ACL_HELPER;
 priv->acl_helper = spice_usb_acl_helper_new();
 g_object_set(spice_channel_get_session(SPICE_CHANNEL(channel)),
@@ -373,17 +373,17 @@ void spice_usbredir_channel_connect_device_async(
 return;
 #else
 if (!spice_usbredir_channel_open_device(channel, &err)) {
-g_simple_async_result_take_error(result, err);
+g_task_return_error(task, err);
 libusb_unref_device(priv->device);
 priv->device = NULL;
 g_boxed_free(spice_usb_device_get_type(), priv->spice_device);
 priv->spice_device = NULL;
-}
+} else {
+g_task_return_boolean(task, TRUE);
 #endif
 
 done:
-g_simple_async_result_complete_in_idle(result);
-g_object_unref(result);
+g_object_unref(task);
 }
 
 G_GNUC_INTERNAL
@@ -392,16 +392,11 @@ gboolean spice_usbredir_channel_connect_device_finish(
GAsyncResult *res,
GError  **err)
 {
-GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT(res);
+GTask *task = G_TASK(res);
 
-g_return_val_if_fail(g_simple_async_result_is_valid(res, G_OBJECT(channel),
- spice_usbredir_channel_connect_device_async),
- FALSE);
+g_return_val_if_fail(g_task_is_valid(task, channel), FALSE);
 
-if (g_simple_async_result_propagate_error(result, err))
-return FALSE;
-
-return TRUE;
+return g_task_propagate_boolean(task, err);
 }
 
 G_GNUC_INTERNAL
-- 
2.5.0

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH 01/14] channel-base: Use GTask instead of GSimpleAsyncResult

2016-01-18 Thread Fabiano Fidêncio
Instead of using GSimpleAsyncResult, use the new GTask API, which is
much more straightforward.
For using the new GTask API, let's bump GIO (part of GLib) dependency
version to 2.36, which is safe based on major distro support:
- Debian Jessie: glib-2.42
- RHEL-7.1: glib-2.40
- SLES12: glib-2.38
- Ubuntu LTS 14.04: glib-2.40
---
 configure.ac   |  6 +++---
 src/channel-base.c | 26 ++
 2 files changed, 13 insertions(+), 19 deletions(-)

diff --git a/configure.ac b/configure.ac
index 38db8b5..e113487 100644
--- a/configure.ac
+++ b/configure.ac
@@ -201,7 +201,7 @@ fi
 
 AC_CHECK_FUNCS(clearenv strtok_r)
 
-PKG_CHECK_MODULES(GLIB2, glib-2.0 >= 2.28)
+PKG_CHECK_MODULES(GLIB2, glib-2.0)
 AC_SUBST(GLIB2_CFLAGS)
 AC_SUBST(GLIB2_LIBS)
 
@@ -209,7 +209,7 @@ PKG_CHECK_MODULES(GOBJECT2, gobject-2.0)
 AC_SUBST(GOBJECT2_CFLAGS)
 AC_SUBST(GOBJECT2_LIBS)
 
-PKG_CHECK_MODULES(GIO, gio-2.0 >= 2.10.0 $gio_os)
+PKG_CHECK_MODULES(GIO, gio-2.0 >= 2.36 $gio_os)
 AC_SUBST(GIO_CFLAGS)
 AC_SUBST(GIO_LIBS)
 
@@ -217,7 +217,7 @@ PKG_CHECK_MODULES(CAIRO, cairo >= 1.2.0)
 AC_SUBST(CAIRO_CFLAGS)
 AC_SUBST(CAIRO_LIBS)
 
-PKG_CHECK_MODULES(GTHREAD, gthread-2.0 > 2.0.0)
+PKG_CHECK_MODULES(GTHREAD, gthread-2.0)
 AC_SUBST(GTHREAD_CFLAGS)
 AC_SUBST(GTHREAD_LIBS)
 
diff --git a/src/channel-base.c b/src/channel-base.c
index 13e4ced..517e7b2 100644
--- a/src/channel-base.c
+++ b/src/channel-base.c
@@ -240,10 +240,9 @@ void spice_channel_set_handlers(SpiceChannelClass *klass,
 static void
 vmc_write_free_cb(uint8_t *data, void *user_data)
 {
-GSimpleAsyncResult *result = user_data;
+GTask *task = user_data;
 
-g_simple_async_result_complete_in_idle(result);
-g_object_unref(result);
+g_object_unref(task);
 }
 
 G_GNUC_INTERNAL
@@ -254,15 +253,14 @@ void spice_vmc_write_async(SpiceChannel *self,
gpointer user_data)
 {
 SpiceMsgOut *msg;
-GSimpleAsyncResult *simple;
+GTask *task;
 
-simple = g_simple_async_result_new(G_OBJECT(self), callback, user_data,
-   spice_port_write_async);
-g_simple_async_result_set_op_res_gssize(simple, count);
+task = g_task_new(self, cancellable, callback, user_data);
+g_task_return_int(task, count);
 
 msg = spice_msg_out_new(SPICE_CHANNEL(self), SPICE_MSGC_SPICEVMC_DATA);
 spice_marshaller_add_ref_full(msg->marshaller, (uint8_t*)buffer, count,
-  vmc_write_free_cb, simple);
+  vmc_write_free_cb, task);
 spice_msg_out_send(msg);
 }
 
@@ -270,17 +268,13 @@ G_GNUC_INTERNAL
 gssize spice_vmc_write_finish(SpiceChannel *self,
   GAsyncResult *result, GError **error)
 {
-GSimpleAsyncResult *simple;
+GTask *task;
 
 g_return_val_if_fail(result != NULL, -1);
 
-simple = (GSimpleAsyncResult *)result;
+task = G_TASK(result);
 
-if (g_simple_async_result_propagate_error(simple, error))
-return -1;
+g_return_val_if_fail(g_task_is_valid(task, self), -1);
 
-g_return_val_if_fail(g_simple_async_result_is_valid(result, G_OBJECT(self),
-
spice_port_write_async), -1);
-
-return g_simple_async_result_get_op_res_gssize(simple);
+return g_task_propagate_int(task, error);
 }
-- 
2.5.0

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH 00/14] gobject: Use GTask API

2016-01-18 Thread Fabiano Fidêncio
This series (apart from the last patch) could be merged into a single patch.
I haven't done this because I'm not so sure about some changes in the 
spice-{gstaudio,pulse}, like in
spice_gstaudio_get_record_volume_info_finish() or in 
pulse_stream_restore_info_finish().

Fabiano Fidêncio (14):
  channel-base: Use GTask instead of GSimpleAsyncResult
  channel-main: Use GTask instead of GSimpleAsyncResult
  channel-port: Use GTask instead of GSimpleAsyncResult
  channel-usbredir: Use GTask instead of GSimpleAsyncResult
  smartcard-manager: Use GTask instead of GSimpleAsyncResult
  spice-channel: Use GTask instead of GSimpleAsyncResult
  spice-gstaudio: Use GTask instead of GSimpleAsyncResult
  spice-pulse: Use GTask instead of GSimpleAsyncResult
  usb-acl-helper: Use GTask instead of GSimpleAsyncResult
  usb-device-manager: Use GTask instead of GSimpleAsyncResult
  vmcstream: Use GTask instead of GSimpleAsyncResult
  win-usb-driver-install: Use GTask instead of GSimpleAsyncResult
  wocky-http-proxy: Use GTask instead of GSimpleAsyncResult
  Add strings for translation

 configure.ac |   6 +-
 po/POTFILES.in   |   6 ++
 src/channel-base.c   |  26 -
 src/channel-main.c   |  85 
 src/channel-port.c   |   7 ++-
 src/channel-usbredir.c   |  43 +++---
 src/smartcard-manager.c  |  33 +--
 src/spice-channel.c  |  34 +--
 src/spice-gstaudio.c |  48 
 src/spice-pulse.c|  98 
 src/usb-acl-helper.c |  86 ++--
 src/usb-device-manager.c |  65 +++--
 src/vmcstream.c  | 131 ++-
 src/win-usb-driver-install.c |  90 +++--
 src/wocky-http-proxy.c   |  47 ++--
 15 files changed, 340 insertions(+), 465 deletions(-)

-- 
2.5.0

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH] Remove GSLice usage

2016-01-18 Thread Fabiano Fidêncio
It's being slowly deprecated im glib
https://bugzilla.gnome.org/show_bug.cgi?id=754687
---
 src/channel-display.c | 6 +++---
 src/channel-smartcard.c   | 4 ++--
 src/spice-channel-cache.h | 8 
 src/spice-channel.c   | 8 
 src/spice-grabsequence.c  | 8 
 src/spice-util.c  | 4 ++--
 src/wocky-http-proxy.c| 4 ++--
 7 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/src/channel-display.c b/src/channel-display.c
index dc73235..6a474b1 100644
--- a/src/channel-display.c
+++ b/src/channel-display.c
@@ -635,7 +635,7 @@ static void destroy_surface(gpointer data)
 display_surface *surface = data;
 
 destroy_canvas(surface);
-g_slice_free(display_surface, surface);
+g_free(surface);
 }
 
 static void spice_display_channel_init(SpiceDisplayChannel *channel)
@@ -869,7 +869,7 @@ static void display_handle_mode(SpiceChannel *channel, 
SpiceMsgIn *in)
 
 g_warn_if_fail(c->mark == FALSE);
 
-surface = g_slice_new0(display_surface);
+surface = g_new0(display_surface, 1);
 surface->format  = mode->bits == 32 ?
 SPICE_SURFACE_FMT_32_xRGB : SPICE_SURFACE_FMT_16_555;
 surface->width   = mode->x_res;
@@ -1674,7 +1674,7 @@ static void display_handle_surface_create(SpiceChannel 
*channel, SpiceMsgIn *in)
 {
 SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
 SpiceMsgSurfaceCreate *create = spice_msg_in_parsed(in);
-display_surface *surface = g_slice_new0(display_surface);
+display_surface *surface = g_new0(display_surface, 1);
 
 surface->surface_id = create->surface_id;
 surface->format = create->format;
diff --git a/src/channel-smartcard.c b/src/channel-smartcard.c
index b5535e6..e2e1aad 100644
--- a/src/channel-smartcard.c
+++ b/src/channel-smartcard.c
@@ -241,7 +241,7 @@ smartcard_message_free(SpiceSmartcardChannelMessage 
*message)
 {
 if (message->message)
 spice_msg_out_unref(message->message);
-g_slice_free(SpiceSmartcardChannelMessage, message);
+g_free(message);
 }
 
 #if USE_SMARTCARD
@@ -301,7 +301,7 @@ smartcard_message_new(VSCMsgType msg_type, SpiceMsgOut 
*msg_out)
 {
 SpiceSmartcardChannelMessage *message;
 
-message = g_slice_new0(SpiceSmartcardChannelMessage);
+message = g_new0(SpiceSmartcardChannelMessage, 1);
 message->message = msg_out;
 message->message_type = msg_type;
 
diff --git a/src/spice-channel-cache.h b/src/spice-channel-cache.h
index e609a67..75cc2cd 100644
--- a/src/spice-channel-cache.h
+++ b/src/spice-channel-cache.h
@@ -37,7 +37,7 @@ typedef struct display_cache {
 
 static inline display_cache_item* cache_item_new(guint64 id, gboolean lossy)
 {
-display_cache_item *self = g_slice_new(display_cache_item);
+display_cache_item *self = g_new(display_cache_item, 1);
 self->id = id;
 self->lossy = lossy;
 self->ref_count = 1;
@@ -46,12 +46,12 @@ static inline display_cache_item* cache_item_new(guint64 
id, gboolean lossy)
 
 static inline void cache_item_free(display_cache_item *self)
 {
-g_slice_free(display_cache_item, self);
+g_free(self);
 }
 
 static inline display_cache* cache_new(GDestroyNotify value_destroy)
 {
-display_cache * self = g_slice_new(display_cache);
+display_cache * self = g_new(display_cache, 1);
 self->table = g_hash_table_new_full(g_int64_hash, g_int64_equal,
(GDestroyNotify) cache_item_free,
value_destroy);
@@ -131,7 +131,7 @@ static inline void cache_clear(display_cache *cache)
 static inline void cache_free(display_cache *cache)
 {
 g_hash_table_unref(cache->table);
-g_slice_free(display_cache, cache);
+g_free(cache);
 }
 
 G_END_DECLS
diff --git a/src/spice-channel.c b/src/spice-channel.c
index 41c94d0..ff85715 100644
--- a/src/spice-channel.c
+++ b/src/spice-channel.c
@@ -471,7 +471,7 @@ SpiceMsgIn *spice_msg_in_new(SpiceChannel *channel)
 
 g_return_val_if_fail(channel != NULL, NULL);
 
-in = g_slice_new0(SpiceMsgIn);
+in = g_new0(SpiceMsgIn, 1);
 in->refcount = 1;
 in->channel  = channel;
 
@@ -519,7 +519,7 @@ void spice_msg_in_unref(SpiceMsgIn *in)
 } else {
 g_free(in->data);
 }
-g_slice_free(SpiceMsgIn, in);
+g_free(in);
 }
 
 G_GNUC_INTERNAL
@@ -624,7 +624,7 @@ SpiceMsgOut *spice_msg_out_new(SpiceChannel *channel, int 
type)
 
 g_return_val_if_fail(c != NULL, NULL);
 
-out = g_slice_new0(SpiceMsgOut);
+out = g_new0(SpiceMsgOut, 1);
 out->refcount = 1;
 out->channel  = channel;
 out->ro_check = msg_check_read_only(c->channel_type, type);
@@ -660,7 +660,7 @@ void spice_msg_out_unref(SpiceMsgOut *out)
 if (out->refcount > 0)
 return;
 spice_marshaller_destroy(out->marshaller);
-g_slice_free(SpiceMsgOut, out);
+g_free(out);
 }
 
 /* system context */
diff --git a/src/spice-grabsequence.c b/src/spice-grabsequence.c
index 26bf96f..3d87329 100644
--- a/src/spice-grabsequ