remoteosd.c
资源名称:vlc-1.0.5.zip [点击查看]
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:51k
源码类别:
midi
开发平台:
Unix_Linux
- /*****************************************************************************
- * remoteosd.c: remote osd over vnc filter module
- *****************************************************************************
- * Copyright (C) 2007-2008 Matthias Bauer
- * $Id: 8b0e02ece326754b86991c75306cf4f11c192ec7 $
- *
- * Authors: Matthias Bauer <matthias dot bauer #_at_# gmx dot ch>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implid warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
- /*****************************************************************************
- * RemoteOSD uses the RFB-Protocol of VNC to display an On-Screen-Display
- * menu generated by a streaming server as overlay for the streamed video.
- *
- * The streaming server that implements this is the ffnetdev plugin for VDR.
- * VDR (VideoDiskRecorder) is an Linux based OpenSource harddisk recorder
- * software.
- * The VDR ffnetdev plugin emulates the hardware MPEG decoder and streams the
- * video over the network instead of hardware video outputs.
- * The OSD menu of VDR is offered with the RFB protocol to a VNC client.
- *
- * In fact this video-filter is a simple VNC client that could be also used to
- * connect to a real VNC host.
- * Only 8-bit color is supported at the moment.
- * Using password protected VNC hosts is supported but not recommended, because
- * you need to insert the used password in the plugin configuration page of
- * VLC configuration in plain text and it's saved in plain text.
- *****************************************************************************/
- //#define VNC_DEBUG
- /*****************************************************************************
- * Preamble
- *****************************************************************************/
- #ifdef HAVE_CONFIG_H
- # include "config.h"
- #endif
- #include <vlc_common.h>
- #include <vlc_plugin.h>
- #include <vlc_vout.h>
- #include "vlc_filter.h"
- #include "filter_common.h"
- #include "vlc_image.h"
- #include "vlc_osd.h"
- #include "vlc_keys.h"
- #include <vlc_network.h>
- #include <gcrypt.h> /* to encrypt password */
- #include <vlc_gcrypt.h>
- #include "remoteosd_rfbproto.h" /* type definitions of the RFB protocol for VNC */
- /*****************************************************************************
- * Module descriptor
- *****************************************************************************/
- #define READ_BUFFER_SIZE 1000000
- #define RMTOSD_HOST_TEXT N_("VNC Host")
- #define RMTOSD_HOST_LONGTEXT N_(
- "VNC hostname or IP address." )
- #define RMTOSD_PORT_TEXT N_("VNC Port")
- #define RMTOSD_PORT_LONGTEXT N_(
- "VNC portnumber." )
- #define RMTOSD_PASSWORD_TEXT N_("VNC Password")
- #define RMTOSD_PASSWORD_LONGTEXT N_(
- "VNC password." )
- #define RMTOSD_UPDATE_TEXT N_("VNC poll interval" )
- #define RMTOSD_UPDATE_LONGTEXT N_(
- "In this interval an update from VNC is requested, default every 300 ms. ")
- #define RMTOSD_POLL_TEXT N_("VNC polling")
- #define RMTOSD_POLL_LONGTEXT N_(
- "Activate VNC polling. Do NOT activate for use as VDR ffnetdev client." )
- #define RMTOSD_MOUSE_TEXT N_("Mouse events")
- #define RMTOSD_MOUSE_LONGTEXT N_(
- "Send mouse events to VNC host. Not needed for use as VDR ffnetdev client." )
- #define RMTOSD_KEYS_TEXT N_("Key events")
- #define RMTOSD_KEYS_LONGTEXT N_(
- "Send key events to VNC host." )
- #define RMTOSD_ALPHA_TEXT N_("Alpha transparency value (default 255)")
- #define RMTOSD_ALPHA_LONGTEXT N_(
- "The transparency of the OSD VNC can be changed by giving a value "
- "between 0 and 255. A lower value specifies more transparency a higher "
- "means less transparency. The default is being not transparent "
- "(value 255) the minimum is fully transparent (value 0)." )
- #define RMTOSD_CFG "rmtosd-"
- #define RMTOSD_UPDATE_MIN 200
- #define RMTOSD_UPDATE_DEFAULT 1000
- #define RMTOSD_UPDATE_MAX 300
- static int CreateFilter ( vlc_object_t * );
- static void DestroyFilter( vlc_object_t * );
- vlc_module_begin ()
- set_description( N_("Remote-OSD over VNC") )
- set_capability( "sub filter", 100 )
- set_shortname( N_("Remote-OSD") )
- set_category( CAT_VIDEO )
- set_subcategory( SUBCAT_VIDEO_SUBPIC )
- add_shortcut( "rmtosd" )
- set_callbacks( CreateFilter, DestroyFilter )
- add_string( RMTOSD_CFG "host", "myvdr", NULL, RMTOSD_HOST_TEXT,
- RMTOSD_HOST_LONGTEXT, false )
- add_integer_with_range( RMTOSD_CFG "port", 20001, 1, 0xFFFF, NULL,
- RMTOSD_PORT_TEXT, RMTOSD_PORT_LONGTEXT, false )
- add_password( RMTOSD_CFG "password", "", NULL, RMTOSD_PASSWORD_TEXT,
- RMTOSD_PASSWORD_LONGTEXT, false )
- add_integer_with_range( RMTOSD_CFG "update", RMTOSD_UPDATE_DEFAULT,
- RMTOSD_UPDATE_MIN, RMTOSD_UPDATE_MAX, NULL, RMTOSD_UPDATE_TEXT,
- RMTOSD_UPDATE_LONGTEXT, true )
- add_bool( RMTOSD_CFG "vnc-polling", 0, NULL,
- RMTOSD_POLL_TEXT , RMTOSD_POLL_LONGTEXT, false )
- add_bool( RMTOSD_CFG "mouse-events", 0, NULL,
- RMTOSD_MOUSE_TEXT , RMTOSD_MOUSE_LONGTEXT, false )
- add_bool( RMTOSD_CFG "key-events", 0, NULL,
- RMTOSD_KEYS_TEXT , RMTOSD_KEYS_LONGTEXT, false )
- add_integer_with_range( RMTOSD_CFG "alpha", 255, 0, 255, NULL,
- RMTOSD_ALPHA_TEXT, RMTOSD_ALPHA_LONGTEXT, true )
- vlc_module_end ()
- /*****************************************************************************
- * Local prototypes
- *****************************************************************************/
- #define CHALLENGESIZE 16
- #define MAX_VNC_SERVER_NAME_LENGTH 255
- /* subfilter functions */
- static subpicture_t *Filter( filter_t *, mtime_t );
- static int MouseEvent ( vlc_object_t *p_this, char const *psz_var,
- vlc_value_t oldval, vlc_value_t newval, void *p_data );
- static int KeyEvent( vlc_object_t *p_this, char const *psz_var,
- vlc_value_t oldval, vlc_value_t newval, void *p_data );
- static void stop_osdvnc ( filter_t *p_filter );
- static void* vnc_worker_thread ( vlc_object_t *p_thread_obj );
- static void* update_request_thread( vlc_object_t *p_thread_obj );
- static bool open_vnc_connection ( filter_t *p_filter );
- static bool handshaking ( filter_t *p_filter );
- static bool process_server_message ( filter_t *p_filter,
- rfbServerToClientMsg *msg );
- static inline void rgb_to_yuv( uint8_t *y, uint8_t *u, uint8_t *v,
- int r, int g, int b );
- static inline bool fill_rect( filter_sys_t* p_sys,
- uint16_t i_x, uint16_t i_y,
- uint16_t i_w, uint16_t i_h,
- uint8_t i_color );
- static inline bool copy_rect( filter_sys_t* p_sys,
- uint16_t i_x, uint16_t i_y,
- uint16_t i_w, uint16_t i_h,
- uint16_t i_sx, uint16_t i_sy );
- static inline bool raw_line( filter_sys_t* p_sys,
- uint16_t i_x, uint16_t i_y,
- uint16_t i_w );
- static void vnc_encrypt_bytes( unsigned char *bytes, char *passwd );
- /*****************************************************************************
- * Sub filter code
- *****************************************************************************/
- /*****************************************************************************
- * Local prototypes
- *****************************************************************************/
- struct filter_sys_t
- {
- VLC_COMMON_MEMBERS
- bool b_need_update; /* VNC picture is updated, do update the OSD*/
- mtime_t i_vnc_poll_interval; /* Update the OSD menu every n ms */
- uint8_t i_alpha; /* alpha transparency value */
- char *psz_host; /* VNC host */
- int i_port;
- char *psz_passwd; /* VNC password */
- bool b_vnc_poll; /* Activate VNC polling ? */
- bool b_vnc_mouse_events; /* Send MouseEvents ? */
- bool b_vnc_key_events; /* Send KeyEvents ? */
- bool b_connection_active; /* Handshaking finished ? */
- vlc_mutex_t lock; /* To lock for read/write on picture */
- picture_t *p_pic; /* The picture with OSD data from VNC */
- vout_thread_t *p_vout; /* Pointer to video-out thread */
- int i_socket; /* Socket used for VNC */
- uint16_t i_vnc_width; /* The with of the VNC screen */
- uint16_t i_vnc_height; /* The height of the VNC screen */
- uint32_t i_vnc_pixels; /* The pixels of the VNC screen */
- bool b_alpha_from_vnc; /* Special ffnetdev alpha feature enabled ? */
- char read_buffer[READ_BUFFER_SIZE];
- bool b_continue;
- vlc_object_t* p_worker_thread;
- uint8_t ar_color_table_yuv[256][4];
- };
- /*****************************************************************************
- * CreateFilter: Create the filter and open the definition file
- *****************************************************************************/
- static int CreateFilter ( vlc_object_t *p_this )
- {
- filter_t *p_filter = (filter_t *)p_this;
- filter_sys_t *p_sys = NULL;
- msg_Dbg( p_filter, "Creating vnc osd filter..." );
- p_filter->p_sys = p_sys = malloc( sizeof(*p_sys) );
- if( !p_filter->p_sys )
- return VLC_ENOMEM;
- memset( p_sys, 0, sizeof(*p_sys) );
- /* Populating struct */
- vlc_mutex_init( &p_sys->lock );
- p_sys->b_continue = true;
- p_sys->i_socket = -1;
- p_sys->p_pic = NULL;
- p_sys->psz_host = var_CreateGetString( p_this, RMTOSD_CFG "host" );
- if( EMPTY_STR(p_sys->psz_host) )
- {
- msg_Err( p_filter, "unable to get vnc host" );
- goto error;
- }
- p_sys->psz_passwd = var_CreateGetString( p_this, RMTOSD_CFG "password" );
- if( !p_sys->psz_passwd )
- {
- msg_Err( p_filter, "unable to get vnc password" );
- goto error;
- }
- p_sys->i_port = var_CreateGetIntegerCommand( p_this, RMTOSD_CFG "port" );
- p_sys->i_alpha = var_CreateGetIntegerCommand( p_this, RMTOSD_CFG "alpha" );
- /* in milliseconds, 0 disables polling, should not be lower than 100 */
- p_sys->i_vnc_poll_interval = var_CreateGetIntegerCommand( p_this,
- RMTOSD_CFG "update" );
- if ( p_sys->i_vnc_poll_interval < 100)
- {
- p_sys->i_vnc_poll_interval = 100;
- }
- for ( int i = 0; i < 256; i++ )
- {
- p_sys->ar_color_table_yuv[i][0] = 255;
- p_sys->ar_color_table_yuv[i][1] = 255;
- p_sys->ar_color_table_yuv[i][2] = 255;
- p_sys->ar_color_table_yuv[i][3] = 255;
- }
- p_sys->b_vnc_poll = var_CreateGetBoolCommand( p_this,
- RMTOSD_CFG "vnc-polling" );
- p_sys->b_vnc_mouse_events = var_CreateGetBoolCommand( p_this,
- RMTOSD_CFG "mouse-events" );
- p_sys->b_vnc_key_events = var_CreateGetBoolCommand( p_this,
- RMTOSD_CFG "key-events" );
- /* Keep track of OSD Events */
- p_sys->b_need_update = false;
- /* Attach subpicture filter callback */
- p_filter->pf_sub_filter = Filter;
- p_sys->p_vout = vlc_object_find( p_this, VLC_OBJECT_VOUT, FIND_PARENT );
- if( p_sys->p_vout )
- {
- var_AddCallback( p_sys->p_vout, "mouse-moved",
- MouseEvent, p_this );
- var_AddCallback( p_sys->p_vout, "mouse-button-down",
- MouseEvent, p_this );
- var_AddCallback( p_sys->p_vout->p_libvlc, "key-pressed",
- KeyEvent, p_this );
- }
- es_format_Init( &p_filter->fmt_out, SPU_ES, VLC_FOURCC( 's','p','u',' ' ) );
- p_filter->fmt_out.i_priority = 0;
- vlc_gcrypt_init();
- /* create the vnc worker thread */
- p_sys->p_worker_thread = vlc_object_create( p_this,
- sizeof( vlc_object_t ) );
- vlc_object_attach( p_sys->p_worker_thread, p_this );
- if( vlc_thread_create( p_sys->p_worker_thread, "vnc worker thread",
- vnc_worker_thread, VLC_THREAD_PRIORITY_LOW ) )
- {
- vlc_object_detach( p_sys->p_worker_thread );
- vlc_object_release( p_sys->p_worker_thread );
- msg_Err( p_filter, "cannot spawn vnc message reader thread" );
- goto error;
- }
- msg_Dbg( p_filter, "osdvnc filter started" );
- return VLC_SUCCESS;
- error:
- msg_Err( p_filter, "osdvnc filter discarded" );
- stop_osdvnc( p_filter );
- vlc_mutex_destroy( &p_sys->lock );
- free( p_sys->psz_host );
- free( p_sys->psz_passwd );
- free( p_sys );
- return VLC_EGENERIC;
- }
- /*****************************************************************************
- * DestroyFilter: Make a clean exit of this plugin
- *****************************************************************************/
- static void DestroyFilter( vlc_object_t *p_this )
- {
- filter_t *p_filter = (filter_t*)p_this;
- filter_sys_t *p_sys = p_filter->p_sys;
- msg_Dbg( p_filter, "DestroyFilter called." );
- stop_osdvnc( p_filter );
- if( p_sys->p_vout )
- {
- var_DelCallback( p_sys->p_vout, "mouse-moved",
- MouseEvent, p_this );
- var_DelCallback( p_sys->p_vout, "mouse-button-down",
- MouseEvent, p_this );
- var_DelCallback( p_sys->p_vout->p_libvlc, "key-pressed",
- KeyEvent, p_this );
- vlc_object_release( p_sys->p_vout );
- }
- var_Destroy( p_this, RMTOSD_CFG "host" );
- var_Destroy( p_this, RMTOSD_CFG "port" );
- var_Destroy( p_this, RMTOSD_CFG "password" );
- var_Destroy( p_this, RMTOSD_CFG "update" );
- var_Destroy( p_this, RMTOSD_CFG "vnc-polling" );
- var_Destroy( p_this, RMTOSD_CFG "mouse-events" );
- var_Destroy( p_this, RMTOSD_CFG "key-events" );
- var_Destroy( p_this, RMTOSD_CFG "alpha" );
- vlc_mutex_destroy( &p_sys->lock );
- free( p_sys->psz_host );
- free( p_sys->psz_passwd );
- free( p_sys );
- }
- static void stop_osdvnc ( filter_t *p_filter )
- {
- filter_sys_t *p_sys = p_filter->p_sys;
- /* It will unlock socket reading */
- vlc_object_kill( p_filter );
- /* */
- if( p_sys->p_worker_thread )
- {
- msg_Dbg( p_filter, "joining worker_thread" );
- vlc_object_kill( p_sys->p_worker_thread );
- vlc_thread_join( p_sys->p_worker_thread );
- vlc_object_detach( p_sys->p_worker_thread );
- vlc_object_release( p_sys->p_worker_thread );
- msg_Dbg( p_filter, "released worker_thread" );
- }
- msg_Dbg( p_filter, "osdvnc stopped" );
- }
- static bool read_exact( filter_t *p_filter,
- int i_socket,
- char* p_readbuf,
- int i_bytes )
- {
- return i_bytes == net_Read( p_filter, i_socket, NULL,
- (unsigned char*)p_readbuf,
- i_bytes, true );
- }
- static bool write_exact( filter_t *p_filter,
- int i_socket,
- char* p_writebuf,
- int i_bytes )
- {
- return i_bytes == net_Write( p_filter, i_socket, NULL,
- (unsigned char*)p_writebuf, i_bytes );
- }
- static bool open_vnc_connection ( filter_t *p_filter )
- {
- filter_sys_t *p_sys = p_filter->p_sys;
- msg_Dbg( p_filter, "Open socket to vnc server on %s:%u.",
- p_sys->psz_host, p_sys->i_port );
- p_sys->i_socket = net_ConnectTCP( p_filter, p_sys->psz_host, p_sys->i_port );
- if( p_sys->i_socket < 0 )
- {
- msg_Err( p_filter, "Could not open socket" );
- return false;
- }
- msg_Dbg( p_filter, "socket is open." );
- return true;
- }
- static bool handshaking ( filter_t *p_filter )
- {
- filter_sys_t *p_sys = p_filter->p_sys;
- msg_Dbg( p_filter, "Reading protocol version" );
- rfbProtocolVersionMsg pv;
- if ( !read_exact( p_filter, p_sys->i_socket, pv,
- sz_rfbProtocolVersionMsg ) )
- {
- msg_Err( p_filter, "Could not read version message" );
- return false;
- }
- pv[sz_rfbProtocolVersionMsg] = ' '; /* pv size is sz_rfbProtocolVersionMsg+1 */
- msg_Dbg( p_filter, "Server version is %s", pv );
- strncpy(pv, "RFB 003.003n", sz_rfbProtocolVersionMsg);
- if( !write_exact(p_filter, p_sys->i_socket, pv,
- sz_rfbProtocolVersionMsg) )
- {
- msg_Err( p_filter, "Could not write version message" );
- return false;
- }
- msg_Dbg( p_filter, "Reading authentication scheme" );
- uint32_t i_authScheme;
- if( !read_exact( p_filter, p_sys->i_socket, (char*)&i_authScheme, 4 ) )
- {
- msg_Err( p_filter, "Could not read authentication scheme" );
- return false;
- }
- i_authScheme = htonl(i_authScheme);
- msg_Dbg( p_filter, "Authentication scheme = %x", i_authScheme );
- if ( i_authScheme == rfbConnFailed )
- {
- msg_Err( p_filter, "Connection rejected by server" );
- return false;
- }
- if (i_authScheme == rfbVncAuth)
- {
- unsigned char challenge[CHALLENGESIZE];
- if ( !read_exact( p_filter, p_sys->i_socket,
- (char*)challenge, CHALLENGESIZE ) )
- {
- msg_Err( p_filter, "Could not read password challenge" );
- return false;
- }
- vnc_encrypt_bytes( challenge, p_sys->psz_passwd );
- if( !write_exact(p_filter, p_sys->i_socket,
- (char*)challenge, CHALLENGESIZE ) )
- {
- msg_Err( p_filter, "Could not write password" );
- return false;
- }
- uint32_t i_authResult;
- if( !read_exact( p_filter, p_sys->i_socket, (char*)&i_authResult, 4 ) )
- {
- msg_Err( p_filter, "Could not read authentication result" );
- return false;
- }
- i_authResult = htonl(i_authResult);
- if (i_authResult != rfbVncAuthOK)
- {
- msg_Err( p_filter, "VNC authentication failed" );
- return false;
- }
- }
- msg_Dbg( p_filter, "Writing client init message" );
- rfbClientInitMsg ci;
- ci.shared = 1;
- if( !write_exact( p_filter, p_sys->i_socket,
- (char*)&ci, sz_rfbClientInitMsg ) )
- {
- msg_Err( p_filter, "Could not write client init message" );
- return false;
- }
- msg_Dbg( p_filter, "Reading server init message" );
- rfbServerInitMsg si;
- if( !read_exact( p_filter, p_sys->i_socket,
- (char*)&si, sz_rfbServerInitMsg ) )
- {
- msg_Err( p_filter, "Could not read server init message" );
- return false;
- }
- si.framebufferWidth = htons(si.framebufferWidth);
- si.framebufferHeight = htons(si.framebufferHeight);
- si.format.redMax = htons(si.format.redMax);
- si.format.greenMax = htons(si.format.greenMax);
- si.format.blueMax = htons(si.format.blueMax);
- p_sys->i_vnc_width = si.framebufferWidth;
- p_sys->i_vnc_height = si.framebufferHeight;
- msg_Dbg( p_filter, "Servers preferred pixelformat: "
- "%ux%u, R(%u),G(%u),B(%u), %u bit, depht=%u, %s",
- si.framebufferWidth,
- si.framebufferHeight,
- si.format.redMax,
- si.format.greenMax,
- si.format.blueMax,
- si.format.bitsPerPixel,
- si.format.depth,
- si.format.trueColour ? "TrueColor" : "Not-TrueColor");
- uint32_t i_nameLength = htonl(si.nameLength);
- if( i_nameLength > MAX_VNC_SERVER_NAME_LENGTH )
- {
- msg_Err( p_filter, "Server name too long" );
- return false;
- }
- char s_ServerName[MAX_VNC_SERVER_NAME_LENGTH+1];
- msg_Dbg( p_filter, "Reading server name with size = %u", i_nameLength );
- if( !read_exact( p_filter, p_sys->i_socket, s_ServerName, i_nameLength ) )
- {
- msg_Err( p_filter, "Could not read server name" );
- return false;
- }
- s_ServerName[i_nameLength] = ' ';
- if( strcmp( s_ServerName, "VDR-OSD") == 0 )
- {
- msg_Dbg( p_filter, "Server is a VDR" );
- p_sys->b_alpha_from_vnc = true;
- }
- else
- {
- msg_Dbg( p_filter, "Server is a normal VNC" );
- p_sys->b_alpha_from_vnc = false;
- }
- msg_Dbg( p_filter, "Server init message read properly" );
- msg_Dbg( p_filter, "Server name is %s", s_ServerName );
- msg_Dbg( p_filter, "Writing SetPixelFormat message" );
- rfbSetPixelFormatMsg sp;
- sp.type = rfbSetPixelFormat;
- sp.pad1 = sp.pad2 = 0;
- sp.format.bitsPerPixel = 8;
- sp.format.depth = 8 ;
- sp.format.bigEndian = 1;
- sp.format.trueColour = 0;
- sp.format.redMax = htons(31);
- sp.format.greenMax = htons(31);
- sp.format.blueMax = htons(31);
- sp.format.redShift = 10;
- sp.format.greenShift = 5;
- sp.format.blueShift = 0;
- sp.format.pad1 = sp.format.pad2 = 0;
- if( !write_exact( p_filter, p_sys->i_socket,
- (char*)&sp, sz_rfbSetPixelFormatMsg) )
- {
- msg_Err( p_filter, "Could not write SetPixelFormat message" );
- return false;
- }
- msg_Dbg( p_filter, "Writing SetEncodings message" );
- rfbSetEncodingsMsg se;
- se.type = rfbSetEncodings;
- se.pad = 0;
- se.nEncodings = htons( p_sys->b_alpha_from_vnc ? 3 : 2 );
- if( !write_exact( p_filter, p_sys->i_socket,
- (char*)&se, sz_rfbSetEncodingsMsg) )
- {
- msg_Err( p_filter, "Could not write SetEncodings message begin" );
- return false;
- }
- uint32_t i_encoding;
- msg_Dbg( p_filter, "Writing SetEncodings rfbEncodingCopyRect" );
- i_encoding = htonl(rfbEncodingCopyRect);
- if( !write_exact( p_filter, p_sys->i_socket, (char*)&i_encoding, 4) )
- {
- msg_Err( p_filter, "Could not write encoding type rfbEncodingCopyRect." );
- return false;
- }
- msg_Dbg( p_filter, "Writing SetEncodings rfbEncodingRRE" );
- i_encoding = htonl(rfbEncodingRRE);
- if( !write_exact(p_filter, p_sys->i_socket, (char*)&i_encoding, 4) )
- {
- msg_Err( p_filter, "Could not write encoding type rfbEncodingRRE." );
- return false;
- }
- if( p_sys->b_alpha_from_vnc )
- {
- msg_Dbg( p_filter, "Writing SetEncodings rfbEncSpecialUseAlpha" );
- i_encoding = 0x00F0FFFF; /* rfbEncSpecialUseAlpha is 0xFFFFF000
- * before we swap it */
- if( !write_exact(p_filter, p_sys->i_socket, (char*)&i_encoding, 4) )
- {
- msg_Err( p_filter, "Could not write encoding type rfbEncSpecialUseAlpha." );
- return false;
- }
- }
- return true;
- }
- static void* vnc_worker_thread( vlc_object_t *p_thread_obj )
- {
- filter_t* p_filter = (filter_t*)(p_thread_obj->p_parent);
- filter_sys_t *p_sys = p_filter->p_sys;
- vlc_object_t *p_update_request_thread;
- int canc = vlc_savecancel ();
- msg_Dbg( p_filter, "VNC worker thread started" );
- if( !open_vnc_connection ( p_filter ) )
- {
- msg_Err( p_filter, "Could not connect to vnc host" );
- goto exit;
- }
- if( !handshaking ( p_filter ) )
- {
- msg_Err( p_filter, "Error occured while handshaking vnc host" );
- goto exit;
- }
- p_sys->b_connection_active = true; /* to enable sending key
- * and mouse events to host */
- /* Create an empty picture for VNC the data */
- vlc_mutex_lock( &p_sys->lock );
- p_sys->p_pic = picture_New( VLC_FOURCC('Y','U','V','A'),
- p_sys->i_vnc_width, p_sys->i_vnc_height, VOUT_ASPECT_FACTOR );
- if( !p_sys->p_pic )
- {
- vlc_mutex_unlock( &p_sys->lock );
- goto exit;
- }
- p_sys->i_vnc_pixels = p_sys->i_vnc_width * p_sys->i_vnc_height;
- vlc_mutex_unlock( &p_sys->lock );
- /* create the update request thread */
- p_update_request_thread = vlc_object_create( p_filter,
- sizeof( vlc_object_t ) );
- vlc_object_attach( p_update_request_thread, p_filter );
- if( vlc_thread_create( p_update_request_thread,
- "vnc update request thread",
- update_request_thread, VLC_THREAD_PRIORITY_LOW ) )
- {
- vlc_object_detach( p_update_request_thread );
- vlc_object_release( p_update_request_thread );
- msg_Err( p_filter, "cannot spawn vnc update request thread" );
- goto exit;
- }
- /* connection is initialized, now read and handle server messages */
- while( vlc_object_alive( p_thread_obj ) )
- {
- rfbServerToClientMsg msg;
- int i_msgSize;
- memset( &msg, 0, sizeof(msg) );
- if( !read_exact(p_filter, p_sys->i_socket, (char*)&msg, 1 ) )
- {
- msg_Err( p_filter, "Error while waiting for next server message");
- break;
- }
- switch (msg.type)
- {
- case rfbFramebufferUpdate:
- i_msgSize = sz_rfbFramebufferUpdateMsg;
- break;
- case rfbSetColourMapEntries:
- i_msgSize = sz_rfbSetColourMapEntriesMsg;
- break;
- case rfbBell:
- i_msgSize = sz_rfbBellMsg;
- break;
- case rfbServerCutText:
- i_msgSize = sz_rfbServerCutTextMsg;
- break;
- case rfbReSizeFrameBuffer:
- i_msgSize = sz_rfbReSizeFrameBufferMsg;
- break;
- default:
- i_msgSize = 0;
- msg_Err( p_filter, "Invalid message %u received", msg.type );
- break;
- }
- if( i_msgSize <= 0 )
- break;
- if( --i_msgSize > 0 )
- {
- if ( !read_exact( p_filter, p_sys->i_socket,
- ((char*)&msg)+1, i_msgSize ) )
- {
- msg_Err( p_filter, "Error while reading message of type %u",
- msg.type );
- break;
- }
- }
- process_server_message( p_filter, &msg);
- }
- msg_Dbg( p_filter, "joining update_request_thread" );
- vlc_object_kill( p_update_request_thread );
- vlc_thread_join( p_update_request_thread );
- vlc_object_detach( p_update_request_thread );
- vlc_object_release( p_update_request_thread );
- msg_Dbg( p_filter, "released update_request_thread" );
- exit:
- vlc_mutex_lock( &p_sys->lock );
- p_sys->b_connection_active = false;
- if (p_sys->i_socket >= 0)
- net_Close(p_sys->i_socket);
- if( p_sys->p_pic )
- picture_Release( p_sys->p_pic );
- /* It will hide the subtitle */
- p_sys->b_continue = false;
- p_sys->b_need_update = true;
- vlc_mutex_unlock( &p_sys->lock );
- msg_Dbg( p_filter, "VNC message reader thread ended" );
- vlc_restorecancel (canc);
- return NULL;
- }
- static void* update_request_thread( vlc_object_t *p_thread_obj )
- {
- filter_t* p_filter = (filter_t*)(p_thread_obj->p_parent);
- filter_sys_t *p_sys = p_filter->p_sys;
- int canc = vlc_savecancel ();
- msg_Dbg( p_filter, "VNC update request thread started" );
- rfbFramebufferUpdateRequestMsg udr;
- udr.type = rfbFramebufferUpdateRequest;
- udr.incremental = 0;
- udr.x = 0;
- udr.y = 0;
- udr.w = htons(p_sys->i_vnc_width);
- udr.h = htons(p_sys->i_vnc_height);
- if( write_exact(p_filter, p_sys->i_socket, (char*)&udr,
- sz_rfbFramebufferUpdateRequestMsg) == false)
- {
- msg_Err( p_filter, "Could not write rfbFramebufferUpdateRequestMsg." );
- p_sys->b_continue = false;
- return NULL;
- }
- udr.incremental = 1;
- mtime_t i_poll_interval_microsec = p_sys->i_vnc_poll_interval * 1000;
- if( p_sys->b_vnc_poll)
- {
- while( vlc_object_alive( p_thread_obj ) )
- {
- msleep( i_poll_interval_microsec );
- if( write_exact(p_filter, p_sys->i_socket, (char*)&udr,
- sz_rfbFramebufferUpdateRequestMsg) == false)
- {
- msg_Err( p_filter, "Could not write rfbFramebufferUpdateRequestMsg." );
- break;
- }
- }
- p_sys->b_continue = false;
- }
- else
- {
- msg_Dbg( p_filter, "VNC polling disabled." );
- }
- msg_Dbg( p_filter, "VNC update request thread ended" );
- vlc_restorecancel (canc);
- return NULL;
- }
- static bool process_server_message ( filter_t *p_filter,
- rfbServerToClientMsg *msg )
- {
- filter_sys_t *p_sys = p_filter->p_sys;
- switch (msg->type)
- {
- case rfbFramebufferUpdate:
- {
- msg->fu.nRects = htons(msg->fu.nRects);
- rfbFramebufferUpdateRectHeader hdr;
- for (int i_rect = 0; i_rect < msg->fu.nRects; i_rect++)
- {
- if (!read_exact(p_filter, p_sys->i_socket, (char*)&hdr,
- sz_rfbFramebufferUpdateRectHeader ) )
- {
- msg_Err( p_filter, "Could not read FrameBufferUpdate header" );
- return false;
- }
- hdr.r.x = htons(hdr.r.x);
- hdr.r.y = htons(hdr.r.y);
- hdr.r.w = htons(hdr.r.w);
- hdr.r.h = htons(hdr.r.h);
- hdr.encoding = htonl(hdr.encoding);
- switch (hdr.encoding)
- {
- case rfbEncodingRaw:
- {
- int i_line;
- for (i_line = 0; i_line < hdr.r.h; i_line++)
- {
- if ( !read_exact( p_filter, p_sys->i_socket,
- p_sys->read_buffer, hdr.r.w ) )
- {
- msg_Err( p_filter,
- "Could not read FrameBufferUpdate line data" );
- return false;
- }
- vlc_mutex_lock( &p_sys->lock );
- if ( !raw_line( p_sys, hdr.r.x,
- hdr.r.y + i_line,
- hdr.r.w ) )
- {
- msg_Err( p_filter, "raw_line failed." );
- vlc_mutex_unlock( &p_sys->lock );
- return false;
- }
- vlc_mutex_unlock( &p_sys->lock );
- }
- }
- break;
- case rfbEncodingCopyRect:
- {
- rfbCopyRect rect;
- if ( !read_exact( p_filter, p_sys->i_socket,
- (char*)&rect,
- sz_rfbCopyRect ) )
- {
- msg_Err( p_filter, "Could not read rfbCopyRect" );
- return false;
- }
- rect.srcX = htons( rect.srcX );
- rect.srcY = htons( rect.srcY );
- vlc_mutex_lock( &p_sys->lock );
- if ( !copy_rect( p_sys,
- hdr.r.x, hdr.r.y,
- hdr.r.w, hdr.r.h,
- rect.srcX, rect.srcY ) )
- {
- msg_Err( p_filter, "copy_rect failed." );
- vlc_mutex_unlock( &p_sys->lock );
- return false;
- }
- vlc_mutex_unlock( &p_sys->lock );
- }
- break;
- case rfbEncodingRRE:
- {
- rfbRREHeader rrehdr;
- if ( !read_exact( p_filter, p_sys->i_socket,
- (char*)&rrehdr,
- sz_rfbRREHeader ) )
- {
- msg_Err( p_filter, "Could not read rfbRREHeader" );
- return false;
- }
- uint8_t i_pixcolor;
- if ( !read_exact(p_filter, p_sys->i_socket,
- (char*)&i_pixcolor, 1 ) )
- {
- msg_Err( p_filter, "Could not read RRE pixcolor" );
- return false;
- }
- vlc_mutex_lock( &p_sys->lock );
- if ( !fill_rect( p_sys,
- hdr.r.x, hdr.r.y,
- hdr.r.w, hdr.r.h,
- i_pixcolor) )
- {
- msg_Err( p_filter, "main fill_rect failed." );
- vlc_mutex_unlock( &p_sys->lock );
- return false;
- }
- vlc_mutex_unlock( &p_sys->lock );
- rrehdr.nSubrects = htonl(rrehdr.nSubrects);
- int i_datasize = rrehdr.nSubrects *
- ( sizeof(i_pixcolor) + sz_rfbRectangle ) ;
- if ( i_datasize > READ_BUFFER_SIZE )
- {
- msg_Err( p_filter, "Buffer too small, "
- "need %u bytes", i_datasize );
- return false;
- }
- if ( !read_exact( p_filter, p_sys->i_socket,
- p_sys->read_buffer, i_datasize ) )
- {
- msg_Err( p_filter,
- "Could not read RRE subrect data" );
- return false;
- }
- uint32_t i_subrect;
- rfbRectangle* p_subrect;
- int i_offset = 0;
- vlc_mutex_lock( &p_sys->lock );
- for ( i_subrect = 0;
- i_subrect < rrehdr.nSubrects; i_subrect++)
- {
- i_pixcolor = p_sys->read_buffer[i_offset];
- i_offset += sizeof(i_pixcolor);
- p_subrect =
- (rfbRectangle*)(p_sys->read_buffer + i_offset);
- i_offset += sz_rfbRectangle;
- if (!fill_rect( p_sys,
- htons(p_subrect->x) + hdr.r.x,
- htons(p_subrect->y) + hdr.r.y,
- htons(p_subrect->w),
- htons(p_subrect->h),
- i_pixcolor) )
- {
- msg_Err( p_filter,
- "subrect %u fill_rect failed.", i_subrect );
- vlc_mutex_unlock( &p_sys->lock );
- return false;
- }
- }
- vlc_mutex_unlock( &p_sys->lock );
- }
- break;
- }
- }
- vlc_mutex_lock( &p_sys->lock );
- p_sys->b_need_update = true;
- vlc_mutex_unlock( &p_sys->lock );
- }
- return true;
- case rfbSetColourMapEntries:
- {
- msg->scme.nColours = htons(msg->scme.nColours);
- msg->scme.firstColour = htons(msg->scme.firstColour);
- int i_datasize;
- if ( p_sys->b_alpha_from_vnc == true )
- {
- i_datasize = 2 * msg->scme.nColours * 4;
- }
- else
- {
- i_datasize = 2 * msg->scme.nColours * 3;
- }
- if ( i_datasize > READ_BUFFER_SIZE )
- {
- msg_Err( p_filter, "Buffer too small, need %u bytes",
- i_datasize );
- return false;
- }
- if ( !read_exact( p_filter, p_sys->i_socket,
- p_sys->read_buffer, i_datasize ) )
- {
- msg_Err( p_filter, "Could not read color map data" );
- return false;
- }
- uint8_t i_red, i_green, i_blue, i_alpha, i_color_index;
- uint16_t i_offset = 0;
- i_alpha = 255;
- for (int i = 0; i < msg->scme.nColours; i++)
- {
- i_color_index = i+msg->scme.firstColour;
- if ( p_sys->b_alpha_from_vnc == true )
- {
- i_alpha = p_sys->read_buffer[i_offset];
- i_offset += 2;
- }
- i_red = p_sys->read_buffer[i_offset];
- i_offset += 2;
- i_green = p_sys->read_buffer[i_offset];
- i_offset += 2;
- i_blue = p_sys->read_buffer[i_offset];
- i_offset += 2;
- rgb_to_yuv( &p_sys->ar_color_table_yuv[i_color_index][0],
- &p_sys->ar_color_table_yuv[i_color_index][1],
- &p_sys->ar_color_table_yuv[i_color_index][2],
- i_red,
- i_green,
- i_blue );
- p_sys->ar_color_table_yuv[i][3] = i_alpha;
- }
- }
- return true;
- case rfbBell:
- msg_Err( p_filter, "rfbBell received" );
- return true;
- case rfbServerCutText:
- msg->sct.length = htons(msg->sct.length);
- if ( msg->sct.length > READ_BUFFER_SIZE )
- {
- msg_Err( p_filter, "Buffer too small, need %u bytes", msg->sct.length );
- return false;
- }
- if ( !read_exact(p_filter, p_sys->i_socket,
- p_sys->read_buffer, msg->sct.length ) )
- {
- msg_Err( p_filter, "Could not read Reading rfbServerCutText data" );
- return false;
- }
- return true;
- case rfbReSizeFrameBuffer:
- msg_Err( p_filter, "Reading rfbReSizeFrameBuffer not implemented" );
- return false;
- default:
- msg_Err( p_filter, "Invalid message %u received", msg->type );
- return false;
- }
- return false;
- }
- /****************************************************************************
- * Filter: the whole thing
- ****************************************************************************
- * This function outputs subpictures at regular time intervals.
- ****************************************************************************/
- static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
- {
- filter_sys_t *p_sys = p_filter->p_sys;
- subpicture_t *p_spu;
- subpicture_region_t *p_region;
- video_format_t fmt;
- picture_t *p_pic;
- if( !p_sys->b_need_update )
- {
- return NULL;
- }
- vlc_mutex_lock( &p_sys->lock );
- p_pic = p_sys->p_pic;
- if( !p_pic )
- {
- vlc_mutex_unlock( &p_sys->lock );
- return NULL;
- }
- /* Allocate the subpicture internal data. */
- p_spu = filter_NewSubpicture( p_filter );
- if( !p_spu )
- {
- vlc_mutex_unlock( &p_sys->lock );
- return NULL;
- }
- p_spu->b_absolute = false;
- p_spu->i_start = date;
- p_spu->i_stop = 0;
- p_spu->b_ephemer = true;
- if( !p_sys->b_continue )
- p_spu->i_stop = p_spu->i_start + 1;
- /* Create new SPU region */
- memset( &fmt, 0, sizeof(video_format_t) );
- fmt.i_chroma = VLC_FOURCC('Y','U','V','A');
- fmt.i_aspect = VOUT_ASPECT_FACTOR;
- fmt.i_sar_num = fmt.i_sar_den = 1;
- fmt.i_width = fmt.i_visible_width = p_pic->p[Y_PLANE].i_visible_pitch;
- fmt.i_height = fmt.i_visible_height = p_pic->p[Y_PLANE].i_visible_lines;
- fmt.i_x_offset = fmt.i_y_offset = 0;
- p_region = subpicture_region_New( &fmt );
- if( !p_region )
- {
- msg_Err( p_filter, "cannot allocate SPU region" );
- p_filter->pf_sub_buffer_del( p_filter, p_spu );
- vlc_mutex_unlock( &p_sys->lock );
- return NULL;
- }
- /* FIXME the copy is probably not needed anymore */
- picture_Copy( p_region->p_picture, p_pic );
- p_sys->b_need_update = false;
- vlc_mutex_unlock( &p_sys->lock );
- /* set to one of the 9 relative locations */
- p_region->i_align = 0; /* Center */
- p_spu->b_absolute = false;
- p_spu->i_original_picture_width = 0; /*Let vout core do the horizontal scaling */
- p_spu->i_original_picture_height = fmt.i_height;
- p_spu->p_region = p_region;
- p_spu->i_alpha = ( p_sys->i_alpha );
- return p_spu;
- }
- static inline void rgb_to_yuv( uint8_t *y, uint8_t *u, uint8_t *v,
- int r, int g, int b )
- {
- *y = ( ( ( 66 * r + 129 * g + 25 * b + 128 ) >> 8 ) + 16 );
- *u = ( ( -38 * r - 74 * g + 112 * b + 128 ) >> 8 ) + 128 ;
- *v = ( ( 112 * r - 94 * g - 18 * b + 128 ) >> 8 ) + 128 ;
- }
- static inline bool fill_rect( filter_sys_t* p_sys,
- uint16_t i_x, uint16_t i_y,
- uint16_t i_w, uint16_t i_h,
- uint8_t i_color)
- {
- plane_t *p_outY = p_sys->p_pic->p+Y_PLANE;
- plane_t *p_outU = p_sys->p_pic->p+U_PLANE;
- plane_t *p_outV = p_sys->p_pic->p+V_PLANE;
- plane_t *p_outA = p_sys->p_pic->p+A_PLANE;
- int i_pitch = p_outY->i_pitch;
- int i_lines = p_outY->i_lines;
- if ( i_x + i_w > i_pitch)
- return false;
- if ( i_y + i_h > i_lines)
- return false;
- int i_line_offset = i_y * i_pitch;
- uint8_t i_yuv_y = p_sys->ar_color_table_yuv[i_color][0];
- uint8_t i_yuv_u = p_sys->ar_color_table_yuv[i_color][1];
- uint8_t i_yuv_v = p_sys->ar_color_table_yuv[i_color][2];
- uint8_t i_alpha = p_sys->ar_color_table_yuv[i_color][3];
- for( int i_line = 0; i_line < i_h; i_line++ )
- {
- for( int i_column = 0; i_column < i_w; i_column++ )
- {
- int i_total_offset = i_line_offset + i_x + i_column;
- p_outY->p_pixels[ i_total_offset ] = i_yuv_y;
- p_outU->p_pixels[ i_total_offset ] = i_yuv_u;
- p_outV->p_pixels[ i_total_offset ] = i_yuv_v;
- p_outA->p_pixels[ i_total_offset ] = i_alpha;
- }
- i_line_offset += i_pitch;
- }
- return true;
- }
- static inline bool copy_rect( filter_sys_t* p_sys,
- uint16_t i_x, uint16_t i_y,
- uint16_t i_w, uint16_t i_h,
- uint16_t i_sx, uint16_t i_sy )
- {
- plane_t *p_Y = p_sys->p_pic->p+Y_PLANE;
- plane_t *p_U = p_sys->p_pic->p+U_PLANE;
- plane_t *p_V = p_sys->p_pic->p+V_PLANE;
- plane_t *p_A = p_sys->p_pic->p+A_PLANE;
- int i_pitch = p_Y->i_pitch;
- int i_lines = p_Y->i_lines;
- fprintf( stderr, "copy_rect: (%d,%d)+(%d,%d) -> (%d,%d)n", i_x, i_y, i_w, i_h, i_sx, i_sy );
- if( i_x + i_w > i_pitch || i_sx + i_w > i_pitch )
- return false;
- if( i_y + i_h > i_lines || i_sy + i_h > i_lines)
- return false;
- if( i_w <= 0 || i_h <= 0 )
- return true;
- uint8_t *pb_buffer = calloc( i_w * i_h, 4 );
- if( !pb_buffer )
- return false;
- for( int i_line = 0; i_line < i_h; i_line++ )
- {
- for( int i_column = 0; i_column < i_w; i_column++ )
- {
- const int i_src_offset = ( i_sy + i_line ) * i_pitch + i_sx + i_column;
- const int i_tmp_offset = ( 0 + i_line ) * i_w + 0 + i_column;
- pb_buffer[4*i_tmp_offset + 0] = p_Y->p_pixels[i_src_offset];
- pb_buffer[4*i_tmp_offset + 1] = p_U->p_pixels[i_src_offset];
- pb_buffer[4*i_tmp_offset + 2] = p_V->p_pixels[i_src_offset];
- pb_buffer[4*i_tmp_offset + 3] = p_A->p_pixels[i_src_offset];
- }
- }
- for( int i_line = 0; i_line < i_h; i_line++ )
- {
- for( int i_column = 0; i_column < i_w; i_column++ )
- {
- const int i_tmp_offset = ( 0 + i_line ) * i_w + 0 + i_column;
- const int i_dst_offset = ( i_y + i_line ) * i_pitch + i_x + i_column;
- p_Y->p_pixels[i_dst_offset] = pb_buffer[4*i_tmp_offset + 0];
- p_U->p_pixels[i_dst_offset] = pb_buffer[4*i_tmp_offset + 1];
- p_V->p_pixels[i_dst_offset] = pb_buffer[4*i_tmp_offset + 2];
- p_A->p_pixels[i_dst_offset] = pb_buffer[4*i_tmp_offset + 3];
- }
- }
- free( pb_buffer );
- return true;
- }
- static inline bool raw_line( filter_sys_t* p_sys,
- uint16_t i_x, uint16_t i_y,
- uint16_t i_w )
- {
- plane_t *p_outY = p_sys->p_pic->p+Y_PLANE;
- plane_t *p_outU = p_sys->p_pic->p+U_PLANE;
- plane_t *p_outV = p_sys->p_pic->p+V_PLANE;
- plane_t *p_outA = p_sys->p_pic->p+A_PLANE;
- int i_pitch = p_outY->i_pitch;
- int i_lines = p_outY->i_lines;
- if ( i_x + i_w > i_pitch)
- return false;
- if ( i_y > i_lines)
- return false;
- int i_line_offset = i_y * i_pitch + i_x;
- for( int i_column = 0; i_column < i_w; i_column++ )
- {
- int i_offset = i_line_offset + i_column;
- uint8_t i_color = p_sys->read_buffer[i_column];
- p_outY->p_pixels[ i_offset ] = p_sys->ar_color_table_yuv[i_color][0];
- p_outU->p_pixels[ i_offset ] = p_sys->ar_color_table_yuv[i_color][1];
- p_outV->p_pixels[ i_offset ] = p_sys->ar_color_table_yuv[i_color][2];
- p_outA->p_pixels[ i_offset ] = p_sys->ar_color_table_yuv[i_color][3];
- }
- return true;
- }
- /*****************************************************************************
- * MouseEvent: callback for mouse events
- *****************************************************************************/
- static int MouseEvent( vlc_object_t *p_this, char const *psz_var,
- vlc_value_t oldval, vlc_value_t newval, void *p_data )
- {
- VLC_UNUSED(oldval); VLC_UNUSED(newval); VLC_UNUSED(psz_var);
- filter_t *p_filter = (filter_t *)p_data;
- filter_sys_t *p_sys = p_filter->p_sys;
- if( !p_sys->b_vnc_mouse_events )
- return VLC_SUCCESS;
- vout_thread_t *p_vout = (vout_thread_t*)p_sys->p_vout;
- int i_x, i_y;
- int i_v;
- i_v = var_GetInteger( p_sys->p_vout, "mouse-button-down" );
- i_y = var_GetInteger( p_sys->p_vout, "mouse-y" );
- i_x = var_GetInteger( p_sys->p_vout, "mouse-x" );
- vlc_mutex_lock( &p_sys->lock );
- const int v_h = p_vout->fmt_in.i_visible_height;
- const int v_w = p_sys->i_vnc_width * v_h / p_sys->i_vnc_height;
- const int v_x = (p_vout->fmt_in.i_visible_width-v_w)/2;
- i_x -= v_x;
- if( i_y < 0 || i_x < 0 || i_y >= v_h || i_x >= v_w )
- {
- vlc_mutex_unlock( &p_sys->lock );
- msg_Dbg( p_this, "invalid mouse event? x=%d y=%d btn=%x", i_x, i_y, i_v );
- return VLC_SUCCESS;
- }
- if( !p_sys->b_connection_active )
- {
- vlc_mutex_unlock( &p_sys->lock );
- return VLC_SUCCESS;
- }
- #ifdef VNC_DEBUG
- msg_Dbg( p_this, "mouse event x=%d y=%d btn=%x", i_x, i_y, i_v );
- #endif
- /* */
- i_x = i_x * p_sys->i_vnc_width / v_w;
- i_y = i_y * p_sys->i_vnc_height / v_h;
- /* buttonMask bits 0-7 are buttons 1-8, 0=up, 1=down */
- rfbPointerEventMsg ev;
- ev.type = rfbPointerEvent;
- ev.buttonMask = i_v;
- ev.x = htons(i_x);
- ev.y = htons(i_y);
- write_exact( p_filter, p_sys->i_socket,
- (char*)&ev, sz_rfbPointerEventMsg);
- vlc_mutex_unlock( &p_sys->lock );
- return VLC_SUCCESS;
- }
- /*****************************************************************************
- * KeyEvent: callback for keyboard events
- *****************************************************************************/
- static int KeyEvent( vlc_object_t *p_this, char const *psz_var,
- vlc_value_t oldval, vlc_value_t newval, void *p_data )
- {
- VLC_UNUSED(psz_var); VLC_UNUSED(oldval);
- filter_t *p_filter = (filter_t *)p_data;
- filter_sys_t *p_sys = p_filter->p_sys;
- if( !p_sys->b_vnc_key_events )
- return VLC_SUCCESS;
- msg_Dbg( p_this, "key pressed (%d) ", newval.i_int );
- if ( !newval.i_int )
- {
- msg_Err( p_this, "Received invalid key event %d", newval.i_int );
- return VLC_EGENERIC;
- }
- vlc_mutex_lock( &p_sys->lock );
- if( !p_sys->b_connection_active )
- {
- vlc_mutex_unlock( &p_sys->lock );
- return VLC_SUCCESS;
- }
- uint32_t i_key32 = newval.i_int;
- i_key32 = htonl(i_key32);
- rfbKeyEventMsg ev;
- ev.type = rfbKeyEvent;
- ev.down = 1;
- ev.pad = 0;
- /* first key-down for modifier-keys */
- if (newval.i_int & KEY_MODIFIER_CTRL)
- {
- ev.key = 0xffe3;
- write_exact( p_filter, p_sys->i_socket,
- (char*)&ev, sz_rfbKeyEventMsg);
- }
- if (newval.i_int & KEY_MODIFIER_SHIFT)
- {
- ev.key = 0xffe1;
- write_exact( p_filter, p_sys->i_socket,
- (char*)&ev, sz_rfbKeyEventMsg);
- }
- if (newval.i_int & KEY_MODIFIER_ALT)
- {
- ev.key = 0xffe9;
- write_exact( p_filter, p_sys->i_socket,
- (char*)&ev, sz_rfbKeyEventMsg);
- }
- /* then key-down for the pressed key */
- ev.key = i_key32;
- write_exact( p_filter, p_sys->i_socket,
- (char*)&ev, sz_rfbKeyEventMsg);
- ev.down = 0;
- /* then key-up for the pressed key */
- write_exact( p_filter, p_sys->i_socket,
- (char*)&ev, sz_rfbKeyEventMsg);
- /* last key-down for modifier-keys */
- if (newval.i_int & KEY_MODIFIER_CTRL)
- {
- ev.key = 0xffe3;
- write_exact( p_filter, p_sys->i_socket,
- (char*)&ev, sz_rfbKeyEventMsg);
- }
- if (newval.i_int & KEY_MODIFIER_SHIFT)
- {
- ev.key = 0xffe1;
- write_exact( p_filter, p_sys->i_socket,
- (char*)&ev, sz_rfbKeyEventMsg);
- }
- if (newval.i_int & KEY_MODIFIER_ALT)
- {
- ev.key = 0xffe9;
- write_exact( p_filter, p_sys->i_socket,
- (char*)&ev, sz_rfbKeyEventMsg);
- }
- vlc_mutex_unlock( &p_sys->lock );
- return VLC_SUCCESS;
- }
- static void vnc_encrypt_bytes( unsigned char *bytes, char *passwd )
- {
- unsigned char key[8];
- unsigned int i;
- for (i = 0; i < 8; i++)
- key[i] = i < strlen( passwd ) ? passwd[i] : ' ';
- gcry_cipher_hd_t ctx;
- gcry_cipher_open( &ctx, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB,0);
- /* reverse bits of the key */
- for( i = 0 ; i < 8 ; i ++ )
- key[i] =
- (key[i] >> 7) +
- (((key[i] >> 6) & 0x01 ) << 1 ) +
- (((key[i] >> 5) & 0x01 ) << 2 ) +
- (((key[i] >> 4) & 0x01 ) << 3 ) +
- (((key[i] >> 3) & 0x01 ) << 4 ) +
- (((key[i] >> 2) & 0x01 ) << 5 ) +
- (((key[i] >> 1) & 0x01 ) << 6 ) +
- ((key[i] & 0x01) << 7 );
- gcry_cipher_setkey( ctx, key, 8 );
- gcry_cipher_encrypt( ctx, bytes, CHALLENGESIZE, bytes, CHALLENGESIZE );
- gcry_cipher_close( ctx );
- }