#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_filter.h>
+#include <vlc_image.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 RMTOSD_PORT_TEXT N_("VNC Port")
#define RMTOSD_PORT_LONGTEXT N_( \
- "VNC portnumber." )
+ "VNC port number." )
#define RMTOSD_PASSWORD_TEXT N_("VNC Password")
#define RMTOSD_PASSWORD_LONGTEXT N_( \
#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 );
+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 );
+ RMTOSD_HOST_LONGTEXT, false )
add_integer_with_range( RMTOSD_CFG "port", 20001, 1, 0xFFFF, NULL,
- RMTOSD_PORT_TEXT, RMTOSD_PORT_LONGTEXT, false );
+ RMTOSD_PORT_TEXT, RMTOSD_PORT_LONGTEXT, false )
add_password( RMTOSD_CFG "password", "", NULL, RMTOSD_PASSWORD_TEXT,
- RMTOSD_PASSWORD_LONGTEXT, false );
+ 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 );
+ RMTOSD_UPDATE_LONGTEXT, true )
+ add_bool( RMTOSD_CFG "vnc-polling", false, NULL,
+ RMTOSD_POLL_TEXT , RMTOSD_POLL_LONGTEXT, false )
+ add_bool( RMTOSD_CFG "mouse-events", false, NULL,
+ RMTOSD_MOUSE_TEXT , RMTOSD_MOUSE_LONGTEXT, false )
+ add_bool( RMTOSD_CFG "key-events", false, 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 );
+ 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( filter_t *,
+ const vlc_mouse_t *,
+ const vlc_mouse_t *,
+ const video_format_t * );
+
+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 );
-vlc_module_end();
/*****************************************************************************
* Sub filter code
*****************************************************************************/
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 */
bool b_continue;
vlc_object_t* p_worker_thread;
- vlc_object_t* p_update_request_thread;
uint8_t ar_color_table_yuv[256][4];
};
msg_Dbg( p_filter, "Creating vnc osd filter..." );
- p_filter->p_sys = p_sys = (filter_sys_t *) malloc( sizeof(filter_sys_t) );
+ p_filter->p_sys = p_sys = calloc( 1, sizeof(*p_sys) );
if( !p_filter->p_sys )
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->p_pic = NULL;
p_sys->psz_host = var_CreateGetString( p_this, RMTOSD_CFG "host" );
if( EMPTY_STR(p_sys->psz_host) )
p_sys->i_alpha = var_CreateGetIntegerCommand( p_this, RMTOSD_CFG "alpha" );
- /* in miliseconds, 0 disables polling, should not be lower than 100 */
+ /* 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)
/* Attach subpicture filter callback */
p_filter->pf_sub_filter = Filter;
+ p_filter->pf_sub_mouse = MouseEvent;
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',' ' ) );
+ es_format_Init( &p_filter->fmt_out, SPU_ES, VLC_CODEC_SPU );
p_filter->fmt_out.i_priority = 0;
vlc_gcrypt_init();
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, false ) )
+ vnc_worker_thread, VLC_THREAD_PRIORITY_LOW ) )
{
- 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;
}
error:
msg_Err( p_filter, "osdvnc filter discarded" );
- p_sys->b_continue = false;
-
stop_osdvnc( p_filter );
+ vlc_mutex_destroy( &p_sys->lock );
free( p_sys->psz_host );
free( p_sys->psz_passwd );
free( p_sys );
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 "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 );
{
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 */
+ /* It will unlock socket reading */
+ vlc_object_kill( p_filter );
- if ( p_sys->p_worker_thread )
+ /* */
+ 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" );
}
- 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" );
}
rfbSetPixelFormatMsg sp;
sp.type = rfbSetPixelFormat;
+ sp.pad1 = sp.pad2 = 0;
sp.format.bitsPerPixel = 8;
sp.format.depth = 8 ;
sp.format.bigEndian = 1;
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) )
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,
}
-static void vnc_worker_thread( vlc_object_t *p_thread_obj )
+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 ) == false )
+ if( !open_vnc_connection ( p_filter ) )
{
msg_Err( p_filter, "Could not connect to vnc host" );
- return;
+ goto exit;
}
- if ( handshaking ( p_filter ) == false )
+ if( !handshaking ( p_filter ) )
{
msg_Err( p_filter, "Error occured while handshaking vnc host" );
- return;
+ goto exit;
}
p_sys->b_connection_active = true; /* to enable sending key
/* Create an empty picture for VNC the data */
vlc_mutex_lock( &p_sys->lock );
- p_sys->p_pic = malloc( sizeof(picture_t) );
+ p_sys->p_pic = picture_New( VLC_CODEC_YUVA,
+ p_sys->i_vnc_width, p_sys->i_vnc_height, 1, 1 );
if( !p_sys->p_pic )
{
vlc_mutex_unlock( &p_sys->lock );
- return;
- }
- vout_AllocatePicture( VLC_OBJECT(p_filter), p_sys->p_pic,
- VLC_FOURCC('Y','U','V','A'),
- p_sys->i_vnc_width,
- p_sys->i_vnc_height,
- VOUT_ASPECT_FACTOR );
- if( !p_sys->p_pic->i_planes )
- {
- free( p_sys->p_pic );
- p_sys->p_pic = NULL;
- vlc_mutex_unlock( &p_sys->lock );
- return;
+ 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_sys->p_update_request_thread = vlc_object_create( p_filter,
- sizeof( vlc_object_t ) );
- vlc_object_attach( p_sys->p_update_request_thread, p_filter );
- if( vlc_thread_create( p_sys->p_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, false ) )
+ update_request_thread, VLC_THREAD_PRIORITY_LOW ) )
{
- vlc_object_detach( p_sys->p_update_request_thread );
- vlc_object_release( p_sys->p_update_request_thread );
- p_sys->p_update_request_thread = NULL;
+ vlc_object_release( p_update_request_thread );
msg_Err( p_filter, "cannot spawn vnc update request thread" );
- return;
+ 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) );
- int i_msgSize;
+ 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;
+ }
- rfbServerToClientMsg msg;
+ if( i_msgSize <= 0 )
+ break;
- while (p_sys->b_continue)
- {
- msg.type = 0;
- if ( !read_exact(p_filter, p_sys->i_socket, (char*)&msg, 1 ) )
- {
- msg_Err( p_filter, "Error while waiting for next server message");
- p_sys->b_continue = false;
- }
- else
- {
- 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;
+ 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;
- default:
- i_msgSize = 0;
- msg_Err( p_filter, "Invalid message %u received", msg.type );
- p_sys->b_continue = false;
- }
- if (p_sys->b_continue == true)
- {
- 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 );
- p_sys->b_continue = false;
- }
- else
- {
- process_server_message( p_filter, &msg);
- }
- }
- else
- {
- process_server_message( p_filter, &msg);
- }
- }
-
- }
-
- if (!vlc_object_alive (p_sys->p_worker_thread) ||
- p_sys->p_worker_thread->b_error)
- {
- p_sys->b_continue = false;
- }
-
+ }
+ }
+ process_server_message( p_filter, &msg);
}
- msg_Dbg( p_filter, "VNC message reader thread ended" );
+ msg_Dbg( p_filter, "joining update_request_thread" );
+ vlc_object_kill( p_update_request_thread );
+ vlc_thread_join( 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 )
+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" );
{
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)
+ if( p_sys->b_vnc_poll)
{
- while ( p_sys->b_continue == true )
+ 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." );
- p_sys->b_continue = false;
- }
- if (!vlc_object_alive (p_sys->p_update_request_thread) ||
- p_sys->p_update_request_thread->b_error)
- {
- p_sys->b_continue = false;
+ 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,
case rfbEncodingCopyRect:
{
- msg_Err( p_filter,
- "Rect in unsupported encoding rfbEncodingCopyRect" );
- return false;
+ 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:
{
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_chroma = VLC_CODEC_YUVA;
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 = p_spu->pf_create_region( VLC_OBJECT(p_filter), &fmt );
+ p_region = subpicture_region_New( &fmt );
if( !p_region )
{
msg_Err( p_filter, "cannot allocate SPU region" );
return NULL;
}
- vout_CopyPicture( p_filter, &p_region->picture, p_pic );
+ /* 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_region->i_align = 0; /* Center */
p_spu->b_absolute = false;
- p_spu->i_x = 0;
- p_spu->i_y = 0;
+ 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;
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 )
/*****************************************************************************
* 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 )
+static int MouseEvent( filter_t *p_filter,
+ const vlc_mouse_t *p_old,
+ const vlc_mouse_t *p_new,
+ const video_format_t *p_fmt )
{
- 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_connection_active )
- return VLC_SUCCESS;
+ VLC_UNUSED(p_old);
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;
+ int i_v = p_new->i_pressed;
+ int i_x = p_new->i_x;
+ int i_y = p_new->i_y;
- int v_h = p_vout->output.i_height;
- int v_w = p_vout->output.i_width;
+ vlc_mutex_lock( &p_sys->lock );
+
+ const int v_h = p_fmt->i_visible_height;
+ const int v_w = p_sys->i_vnc_width * v_h / p_sys->i_vnc_height;
+ const int v_x = (p_fmt->i_visible_width-v_w)/2;
- 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" );
+ i_x -= v_x;
if( i_y < 0 || i_x < 0 || i_y >= v_h || i_x >= v_w )
{
- msg_Dbg( p_this, "invalid mouse event? x=%d y=%d btn=%x", i_x, i_y, i_v );
- return VLC_SUCCESS;
+ vlc_mutex_unlock( &p_sys->lock );
+ msg_Dbg( p_filter, "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 );
+ msg_Dbg( p_filter, "mouse event x=%d y=%d btn=%x", i_x, i_y, i_v );
#endif
- /* FIXME: calculate x and y coordinates for scaled output */
+ /* */
+ 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;
write_exact( p_filter, p_sys->i_socket,
(char*)&ev, sz_rfbPointerEventMsg);
- return VLC_SUCCESS;
+ vlc_mutex_unlock( &p_sys->lock );
+
+ return VLC_EGENERIC;
}
/*****************************************************************************
filter_t *p_filter = (filter_t *)p_data;
filter_sys_t *p_sys = p_filter->p_sys;
- if( !p_sys->b_connection_active )
- return VLC_SUCCESS;
-
if( !p_sys->b_vnc_key_events )
return VLC_SUCCESS;
- msg_Dbg( p_this, "key pressed (%d) ", newval.i_int );
+ msg_Dbg( p_this, "key pressed (%"PRId64") ", newval.i_int );
if ( !newval.i_int )
{
- msg_Err( p_this, "Received invalid key event %d", newval.i_int );
+ msg_Err( p_this, "Received invalid key event 0" );
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)
write_exact( p_filter, p_sys->i_socket,
(char*)&ev, sz_rfbKeyEventMsg);
}
+ vlc_mutex_unlock( &p_sys->lock );
return VLC_SUCCESS;
}
gcry_cipher_encrypt( ctx, bytes, CHALLENGESIZE, bytes, CHALLENGESIZE );
gcry_cipher_close( ctx );
}
+