Commit 446404d0 authored by Matthias Bauer's avatar Matthias Bauer Committed by Rafaël Carré

Added plugin RemoteOSD, a VNC client as video-filter

Signed-off-by: Rafaël Carré's avatarRafaël Carré <funman@videolan.org>
parent c52079ad
......@@ -313,13 +313,13 @@ case "${host_os}" in
VLC_ADD_LDFLAGS([vlc],[-mwindows])
VLC_ADD_LIBS([activex mozilla],[-lgdi32])
VLC_ADD_LIBS([cdda vcdx cddax sdl_image],[-lwinmm])
VLC_ADD_LIBS([access_http access_mms access_udp access_tcp access_ftp access_rtmp access_output_udp access_output_shout access_output_rtmp sap slp http stream_out_standard stream_out_rtp vod_rtsp access_realrtsp rtp telnet rc netsync gnutls growl_udp flac ts audioscrobbler lua],[-lws2_32])
VLC_ADD_LIBS([access_http access_mms access_udp access_tcp access_ftp access_rtmp access_output_udp access_output_shout access_output_rtmp sap slp http stream_out_standard stream_out_rtp vod_rtsp access_realrtsp rtp telnet rc netsync gnutls growl_udp flac ts audioscrobbler lua remoteosd],[-lws2_32])
fi
if test "${SYS}" = "mingwce"; then
# add ws2 for closesocket, select, recv
VLC_ADD_CPPFLAGS([libvlc vlc],[-Dmain(a,b)=maince(a,b)])
VLC_ADD_LDFLAGS([libvlc vlc],[-e WinMainCRTStartup])
VLC_ADD_LIBS([libvlc access_http access_mms access_udp access_tcp access_ftp access_rtmp access_output_udp sap http netsync audioscrobbler growl rtp stream_out_rtp],[-lws2])
VLC_ADD_LIBS([libvlc access_http access_mms access_udp access_tcp access_ftp access_rtmp access_output_udp sap http netsync audioscrobbler growl rtp stream_out_rtp remoteosd],[-lws2])
VLC_ADD_LIBS([libvlc],[-lmmtimer])
fi
;;
......@@ -518,7 +518,7 @@ AC_CHECK_FUNCS(connect,,[
AC_CHECK_FUNCS(send,,[
AC_CHECK_LIB(socket,send,[
VLC_ADD_LIBS([access_http access_mms access_udp access_tcp access_ftp access_rtmp sap access_output_udp access_output_rtmp stream_out_standard growl_udp],[-lsocket])
VLC_ADD_LIBS([access_http access_mms access_udp access_tcp access_ftp access_rtmp sap access_output_udp access_output_rtmp stream_out_standard growl_udp remoteosd],[-lsocket])
])
])
......@@ -5338,6 +5338,24 @@ AS_IF([test "${enable_gnutls}" != "no"], [
])
])
dnl
dnl RemoteOSD plugin (VNC client as video filter)
dnl
AC_ARG_ENABLE(remoteosd,
[ --disable-remoteosd RemoteOSD plugin (default enabled)])
AS_IF([test "${enable_remoteosd}" != "no"], [
AS_IF([test "${have_libgcrypt}" = "yes"],[
VLC_ADD_PLUGIN([remoteosd])
VLC_ADD_LIBS([remoteosd], ${GCRYPT_LIBS})
VLC_ADD_CFLAGS([remoteosd], ${GCRYPT_CFLAGS})
], [
AC_MSG_ERROR([libgcrypt support required for RemoteOSD plugin])
])
])
dnl
dnl update checking system
dnl
......
......@@ -16,6 +16,7 @@ SOURCES_rss = rss.c
SOURCES_motiondetect = motiondetect.c
SOURCES_rv32 = rv32.c
SOURCES_osdmenu = osdmenu.c
SOURCES_remoteosd = remoteosd.c remoteosd_rfbproto.h
SOURCES_magnify = magnify.c
SOURCES_wave = wave.c
SOURCES_ripple = ripple.c
......
/*****************************************************************************
* remoteosd.c: remote osd over vnc filter module
*****************************************************************************
* Copyright (C) 2007-2008 Matthias Bauer
* $Id$
*
* 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>
#define CHALLENGESIZE 16
#define MAX_VNC_SERVER_NAME_LENGTH 255
#include "remoteosd_rfbproto.h" /* type definitions of the RFB protocol for VNC */
/*****************************************************************************
* Local prototypes
*****************************************************************************/
/* subfilter functions */
static int CreateFilter ( vlc_object_t * );
static void DestroyFilter( vlc_object_t * );
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 bool read_exact( filter_t *p_filter,
int i_socket,
char* p_readbuf,
int i_bytes );
static bool write_exact( filter_t *p_filter,
int i_socket,
char* p_writebuf,
int i_bytes );
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 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 );
/*****************************************************************************
* 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
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();
/*****************************************************************************
* 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;
vlc_object_t* p_update_request_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 = (filter_sys_t *) malloc( sizeof(filter_sys_t) );
if( !p_filter->p_sys )
{
msg_Err( p_filter, "out of memory" );
return VLC_ENOMEM;
}
memset( p_sys, 0, sizeof(filter_sys_t) );
/* Populating struct */
vlc_mutex_init( &p_sys->lock );
p_sys->b_continue = true;
p_sys->i_socket = -1;
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 miliseconds, 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;
/* create the vnc worker thread */
p_sys->p_worker_thread = vlc_object_create( p_this, VLC_OBJECT_GENERIC );
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, false ) )
{
vlc_object_detach( p_sys->p_worker_thread );
vlc_object_release( p_sys->p_worker_thread );
p_sys->p_worker_thread = NULL;
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" );
p_sys->b_continue = false;
stop_osdvnc( p_filter );
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 );
p_sys->p_vout = NULL;
}
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" );
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;
if (p_sys->i_socket >= 0)
{
net_Close(p_sys->i_socket);
}
p_sys->b_continue = false; /* this causes the threads to stop */
if ( p_sys->p_worker_thread )
{
msg_Dbg( p_filter, "joining 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" );
}
if ( p_sys->p_update_request_thread )
{
msg_Dbg( p_filter, "joining update_request_thread" );
vlc_thread_join( p_sys->p_update_request_thread );
vlc_object_detach( p_sys->p_update_request_thread );
vlc_object_release( p_sys->p_update_request_thread );
msg_Dbg( p_filter, "released update_request_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] = '\0'; /* pv size is sz_rfbProtocolVersionMsg+1 */
msg_Dbg( p_filter, "Server version is %s", pv );
strncpy(pv, "RFB 003.003\n", 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] = '\0';
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.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;
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.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;