Re: Writing gvnccapture in python



Hi Chris,
I'm not sure about this however I did study a little over the weekend
since I found this interesting.

If you look to the C code you can see:

        /* We'll fix our local copy as rgb888 */
        capture->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
                                         TRUE,
                                         8,
                                         width,
                                         height);
        gdk_pixbuf_fill(capture->pixbuf, 0);

        fb =
vnc_base_framebuffer_new(gdk_pixbuf_get_pixels(capture->pixbuf),
                                      gdk_pixbuf_get_width(capture->pixbuf),
                                     
gdk_pixbuf_get_height(capture->pixbuf),
                                     
gdk_pixbuf_get_rowstride(capture->pixbuf),
                                      remoteFormat,
                                      &localFormat);

and the gdk_pixbuf_get_pixels() should be returning the pointer to
guchar [1] but it seems that the get_pixels() method of the
gtk.gdk.Pixbuf does *not* return the pointer but it's returning the
string instead, please see [2].

I've added the debugging messages to the code and the argument 1 seems
to be an empty string.

Argument 1:  -> <type 'str'>
Argument 2: 720 -> <type 'int'>
Argument 3: 400 -> <type 'int'>
Argument 4: 2880 -> <type 'int'>
Argument 5: <VncPixelFormat at 0x9ac93f8> -> <class
'gi.repository.GVnc.PixelFormat'>
Argument 6: <VncPixelFormat at 0x9a71990> -> <class
'gi.repository.GVnc.PixelFormat'>
Traceback (most recent call last):
  File "x.py", line 15, in initialize
    desktop_resize(conn.get_width(), conn.get_height())
  File "x.py", line 67, in desktop_resize
    conn.get_pixel_format(), localFormat)
  File "/usr/lib/python2.7/site-packages/gtk-2.0/gi/types.py", line 54,
in constructor
    return info.invoke(cls, *args)
TypeError: argument 1: Item 0: Must be number, not str

I guess the solution is to find how is the gtk.gdk.Pixbuf.get_pixels 
using the gdk_pixbuf_get_pixels() function to provide the proper data.
If I tried to change this to get_pixels_array() then the numpy.ndarray
type has been returned which is not good since it's having too many
dimensions and therefore it can't allow it to work properly.

I don't know whether it can help you or not however I'm sending you the
modified version that's working for me so far. The main issue is that
you have to initialize an array and put the get_pixels() data directly
into the array instead of putting the output string of
gtk.gdk.Pixbuf.get_pixels() directly into the function.

Please see the code for more information,
Michal

[1]
http://developer.gimp.org/api/2.0/gdk-pixbuf/gdk-pixbuf-gdk-pixbuf.html#gdk-pixbuf-get-pixels
[2]
http://www.pygtk.org/docs/pygtk/class-gdkpixbuf.html#method-gdkpixbuf--get-pixels

On 03/25/2011 07:19 PM, Chris Lalancette wrote:
> Hi there,
>      I've been attempting to write a program that does the rough equivalent
> of what gvnccapture does, except in python (my ultimate goal is to integrate
> this code into a larger python program).  Based on some advice from
> Dan Berrange, I've started to implement a test program using gobject
> introspection.  However, I've run into a couple of problems (I'll paste my
> full example code below).
>
> The first problem is that I cannot seem to pass the pixel array through to
> BaseFramebuffer like the constructor expects.  The line of code in question is:
>
>     fb = gvnc.BaseFramebuffer().new(pixbuf.get_pixels_array(),
>                                     pixbuf.get_width(),
>                                     pixbuf.get_height(),
>                                     pixbuf.get_rowstride(),
>                                     conn.get_pixel_format(),
>                                     localFormat)
>
> If I run that as-is, I get:
>
> TypeError: only length-1 arrays can be converted to Python scalars
>
> I've also tried using pixbuf.get_pixels(), which gives me:
>
> TypeError: argument 1: Item 0: Must be number, not str
>
> Finally, I tried just using a simple array like [1, 1] there, and I was able
> to get the call to succeed.  In the end, I'm not sure what I'm supposed to pass
> here; does anyone have ideas?
>
> The second problem that I am having has to do with the set_encodings() method.
> The gvnccapture.c program does something like:
>
>     gint32 encodings[] = {  VNC_CONNECTION_ENCODING_DESKTOP_RESIZE,
>                             VNC_CONNECTION_ENCODING_ZRLE,
> 			    VNC_CONNECTION_ENCODING_HEXTILE,
> 			    VNC_CONNECTION_ENCODING_RRE,
> 			    VNC_CONNECTION_ENCODING_COPY_RECT,
> 			    VNC_CONNECTION_ENCODING_RAW };
>     gint32 *encodingsp;
>
>     encodingsp = encodings;
>     n_encodings = G_N_ELEMENTS(encodings);
>
>     if (!vnc_connection_set_encodings(conn, n_encodings, encodingsp))
>        goto error;
>
> However, in python, if I try to call conn.set_encodings(), it only seems to
> take a single parameter in, and an int parameter (not an array or dictionary)
> at that.  Looking at the GVnc-1.0.gir file, it looks like the second paramter
> (encoding) is marked as "out", which might explain this behavior.  Again,
> does anyone have any ideas what I'm doing wrong here?
>
> As mentioned, my full program (as it is so far) is attached.  Any advice
> is greatly appreciated.
>
> Thanks,
>
>
> _______________________________________________
> gtk-vnc-list mailing list
> gtk-vnc-list gnome org
> http://mail.gnome.org/mailman/listinfo/gtk-vnc-list


-- 
Michal Novotny <minovotn redhat com>, RHCE
Virtualization Team (xen userspace), Red Hat

from gi.repository import GVnc as gvnc
import glib
import gtk
import array

# FIXME: can we get these somewhere out of glib?  Doesn't look like it
# (at least in the python bindings), but I'm not sure
G_LITTLE_ENDIAN = 1234
G_BIG_ENDIAN = 4321

def initialize(*args):
    print "init called"
    print args
    print conn.get_width()
    print conn.get_height()
    desktop_resize(conn.get_width(), conn.get_height())

    conn.set_encodings(6)

def disconnect(*args):
    print "disconnect"
    conn.shutdown()
    loop.quit()

def auth_choose_type(*args):
    print "auth_choose_type"
    # FIXME: VNC_CONNECTION_AUTH_NONE
    conn.set_auth_type(1)

def auth_choose_subtype(*args):
    print "auth_choose_subtype"

def auth_credential(*args):
    print "auth_credential"

def desktop_resize(*args):
    print "desktop_resize"
    print args

    width = args[0]
    height = args[1]
    pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, width, height)
    pixbuf.fill(0)

    localFormat = gvnc.PixelFormat()
    localFormat.bits_per_pixel = 32
    localFormat.depth = 32
    localFormat.byte_order = G_LITTLE_ENDIAN
    localFormat.true_color_flag = True
    localFormat.red_max = 255
    localFormat.green_max = 255
    localFormat.blue_max = 255
    localFormat.red_shift = 0
    localFormat.green_shift = 8
    localFormat.blue_shift = 16

    # FIXME: the first argument here needs to be pixbuf.get_pixels() or
    # pixbuf.get_pixels_array()
    print "TEST: %s" % id( pixbuf.get_pixels())
    print "Argument 1: %s -> %s" % (pixbuf.get_pixels(), type( pixbuf.get_pixels() ))
    print "Argument 2: %s -> %s" % (pixbuf.get_width(), type( pixbuf.get_width() ))
    print "Argument 3: %s -> %s" % (pixbuf.get_height(), type( pixbuf.get_height() ))
    print "Argument 4: %s -> %s" % (pixbuf.get_rowstride(), type( pixbuf.get_rowstride() ))
    print "Argument 5: %s -> %s" % (conn.get_pixel_format(), type( conn.get_pixel_format() ))
    print "Argument 6: %s -> %s" % (localFormat, type( localFormat ))

    fb = gvnc.BaseFramebuffer().new( array.array('i', pixbuf.get_pixels() ) , pixbuf.get_width(),
                                    pixbuf.get_height(), pixbuf.get_rowstride(),
                                    conn.get_pixel_format(), localFormat)

    print conn.get_pixel_format()

    conn.set_framebuffer(fb)

def framebuffer_update(*args):
    print "framebuffer_update"

conn = gvnc.Connection()

conn.connect("vnc-initialized", initialize)
conn.connect("vnc-disconnected", disconnect)
conn.connect("vnc-auth-choose-type", auth_choose_type)
conn.connect("vnc-auth-choose-subtype", auth_choose_subtype)
conn.connect("vnc-auth-credential", auth_credential)
conn.connect("vnc-desktop-resize", desktop_resize)
conn.connect("vnc-framebuffer-update", framebuffer_update)

conn.open_host("127.0.0.1", "5900")

loop = glib.MainLoop()

loop.run()



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]