From 82e29c9ba1135639fe10881591e6261bc3396ae4 Mon Sep 17 00:00:00 2001 From: Jean-Paul Saman Date: Thu, 15 Nov 2007 13:38:32 +0000 Subject: [PATCH] Implement clickable osdmenu. The clickable positioning and scaling guessing is not complete (the whole spu region is now clickable with current configurations). --- include/vlc_osd.h | 35 +++-- modules/misc/osd/osd_menu.c | 3 + modules/misc/osd/osd_menu.h | 2 + modules/misc/osd/simple.c | 9 ++ modules/video_filter/osdmenu.c | 98 ++++++++++++++ src/osd/osd.c | 233 +++++++++++++++++++++++++++------ 6 files changed, 325 insertions(+), 55 deletions(-) diff --git a/include/vlc_osd.h b/include/vlc_osd.h index 0c5f4d15ab..83b9b18c81 100644 --- a/include/vlc_osd.h +++ b/include/vlc_osd.h @@ -285,8 +285,6 @@ static const text_style_t default_text_style = { NULL, 22, 0xffffff, 0xff, STYLE #define OSD_BUTTON_SELECT 1 #define OSD_BUTTON_PRESSED 2 -static const char *ppsz_button_states[] = { "unselect", "select", "pressed" }; - /** * OSD State object * @@ -302,6 +300,11 @@ struct osd_state_t char *psz_state; /*< state name */ int i_state; /*< state index */ + + int i_x; /*< x-position of button state image */ + int i_y; /*< y-position of button state image */ + int i_width; /*< width of button state image */ + int i_height; /*< height of button state image */ }; /** @@ -330,6 +333,8 @@ struct osd_button_t int i_x; /*< x-position of button visible state image */ int i_y; /*< y-position of button visible state image */ + int i_width; /*< width of button visible state image */ + int i_height; /*< height of button visible state image */ /* range style button */ vlc_bool_t b_range; /*< button should be interpreted as range */ @@ -389,6 +394,7 @@ struct osd_menu_t int i_width; /*< width of OSD Menu on the video screen */ int i_height; /*< height of OSD Menu on the video screen */ int i_style; /*< style of spu region generation */ + int i_position; /*< display position */ char *psz_path; /*< directory where OSD menu images are stored */ osd_button_t *p_button; /*< doubly linked list of buttons */ @@ -421,20 +427,23 @@ VLC_EXPORT( osd_menu_t *, __osd_MenuCreate, ( vlc_object_t *, const char * ) ); */ VLC_EXPORT( void, __osd_MenuDelete, ( vlc_object_t *, osd_menu_t * ) ); +#define osd_MenuCreate(object,file) __osd_MenuCreate( VLC_OBJECT(object), file ) +#define osd_MenuDelete(object,osd) __osd_MenuDelete( VLC_OBJECT(object), osd ) + /** - * Change state on an osd_button_t. - * - * This function selects the specified state and returns a pointer to it. The - * following states are currently supported: - * \see OSD_BUTTON_UNSELECT - * \see OSD_BUTTON_SELECT - * \see OSD_BUTTON_PRESSED + * Find OSD Menu button at position x,y */ -VLC_EXPORT( osd_state_t *, __osd_StateChange, ( osd_state_t *, const int ) ); +VLC_EXPORT( osd_button_t *, __osd_ButtonFind, ( vlc_object_t *p_this, + int, int, int, int, int, int ) ); -#define osd_MenuCreate(object,file) __osd_MenuCreate( VLC_OBJECT(object), file ) -#define osd_MenuDelete(object,osd) __osd_MenuDelete( VLC_OBJECT(object), osd ) -#define osd_StateChange(object,value) __osd_StateChange( object, value ) +#define osd_ButtonFind(object,x,y,h,w,sh,sw) __osd_ButtonFind(object,x,y,h,w,sh,sw) + +/** + * Select the button provided as the new active button + */ +VLC_EXPORT( void, __osd_ButtonSelect, ( vlc_object_t *, osd_button_t *) ); + +#define osd_ButtonSelect(object,button) __osd_ButtonSelect(object,button) /** * Show the OSD menu. diff --git a/modules/misc/osd/osd_menu.c b/modules/misc/osd/osd_menu.c index db3a4033be..bbd1719c4e 100644 --- a/modules/misc/osd/osd_menu.c +++ b/modules/misc/osd/osd_menu.c @@ -218,6 +218,9 @@ osd_state_t *osd_StateNew( osd_menu_t *p_menu, const char *psz_file, { p_state->p_pic = image_ReadUrl( p_menu->p_image, psz_file, &fmt_in, &fmt_out ); + + p_state->i_width = p_state->p_pic->p[Y_PLANE].i_visible_pitch; + p_state->i_height = p_state->p_pic->p[Y_PLANE].i_visible_lines; } if( psz_state ) diff --git a/modules/misc/osd/osd_menu.h b/modules/misc/osd/osd_menu.h index 8e8f46669f..ca490f6efc 100644 --- a/modules/misc/osd/osd_menu.h +++ b/modules/misc/osd/osd_menu.h @@ -24,6 +24,8 @@ #ifndef _OSD_MENU_PARSER_H_ #define _OSD_MENU_PARSER_H_ +static const char *ppsz_button_states[] = { "unselect", "select", "pressed" }; + /* OSD Menu structure support routines for internal use by * OSD Menu configuration file parsers only. */ diff --git a/modules/misc/osd/simple.c b/modules/misc/osd/simple.c index d5d92559f0..3ebe0190a7 100644 --- a/modules/misc/osd/simple.c +++ b/modules/misc/osd/simple.c @@ -269,6 +269,9 @@ int osd_parser_simpleOpen( vlc_object_t *p_this ) if( !p_range_current || !p_range_current->p_pic ) goto error; + p_range_current->i_x = i_x; + p_range_current->i_y = i_y; + /* increment the number of ranges for this button */ p_up->i_ranges++; @@ -366,6 +369,9 @@ int osd_parser_simpleOpen( vlc_object_t *p_this ) if( !p_range_current || !p_range_current->p_pic ) goto error; + p_range_current->i_x = i_x; + p_range_current->i_y = i_y; + /* increment the number of ranges for this button */ p_current->i_ranges++; @@ -433,6 +439,9 @@ int osd_parser_simpleOpen( vlc_object_t *p_this ) if( !p_state_current || !p_state_current->p_pic ) goto error; + p_state_current->i_x = i_x; + p_state_current->i_y = i_y; + if( p_state_prev ) p_state_prev->p_next = p_state_current; else diff --git a/modules/video_filter/osdmenu.c b/modules/video_filter/osdmenu.c index af5a914fe9..d1bc93b1dc 100644 --- a/modules/video_filter/osdmenu.c +++ b/modules/video_filter/osdmenu.c @@ -84,6 +84,7 @@ static const char *ppsz_pos_descriptions[] = static int CreateFilter ( vlc_object_t * ); static void DestroyFilter( vlc_object_t * ); static subpicture_t *Filter( filter_t *, mtime_t ); + static int OSDMenuUpdateEvent( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * ); static int OSDMenuVisibleEvent( vlc_object_t *, char const *, @@ -91,6 +92,9 @@ static int OSDMenuVisibleEvent( vlc_object_t *, char const *, static int OSDMenuCallback( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * ); +static int MouseEvent( vlc_object_t *, char const *, + vlc_value_t , vlc_value_t , void * ); + #define OSD_CFG "osdmenu-" #if defined( WIN32 ) || defined( UNDER_CE ) @@ -157,6 +161,12 @@ struct filter_sys_t char *psz_file; /* OSD Menu configuration file */ char *psz_path; /* Path to OSD Menu pictures */ osd_menu_t *p_menu; /* pointer to OSD Menu object */ + + /* menu interaction */ + vout_thread_t *p_vout; + vlc_bool_t b_clicked; + uint32_t i_mouse_x; + uint32_t i_mouse_y; }; /***************************************************************************** @@ -206,6 +216,8 @@ static int CreateFilter ( vlc_object_t *p_this ) if( p_sys->p_menu == NULL ) goto error; + p_sys->p_menu->i_position = p_sys->i_position; + /* Check if menu position was overridden */ p_sys->b_absolute = VLC_TRUE; if( (p_sys->i_x < 0) || (p_sys->i_y < 0) ) @@ -233,6 +245,7 @@ static int CreateFilter ( vlc_object_t *p_this ) /* Keep track of OSD Events */ p_sys->b_update = VLC_FALSE; p_sys->b_visible = VLC_FALSE; + p_sys->b_clicked = VLC_FALSE; /* Listen to osd menu core updates/visible settings. */ var_AddCallback( p_sys->p_menu, "osd-menu-update", @@ -243,6 +256,17 @@ static int CreateFilter ( vlc_object_t *p_this ) /* Attach subpicture filter callback */ p_filter->pf_sub_filter = Filter; + p_sys->p_vout = vlc_object_find( p_this, VLC_OBJECT_VOUT, FIND_ANYWHERE ); + if( p_sys->p_vout ) + { + var_AddCallback( p_sys->p_vout, "mouse-x", + MouseEvent, p_sys ); + var_AddCallback( p_sys->p_vout, "mouse-y", + MouseEvent, p_sys ); + var_AddCallback( p_sys->p_vout, "mouse-clicked", + MouseEvent, p_sys ); + } + es_format_Init( &p_filter->fmt_out, SPU_ES, VLC_FOURCC( 's','p','u',' ' ) ); p_filter->fmt_out.i_priority = 0; @@ -276,6 +300,19 @@ static void DestroyFilter( vlc_object_t *p_this ) var_DelCallback( p_sys->p_menu, "osd-menu-visible", OSDMenuVisibleEvent, p_filter ); + if( p_sys->p_vout ) + { + var_DelCallback( p_sys->p_vout, "mouse-x", + MouseEvent, p_sys ); + var_DelCallback( p_sys->p_vout, "mouse-y", + MouseEvent, p_sys ); + var_DelCallback( p_sys->p_vout, "mouse-clicked", + MouseEvent, p_sys ); + + vlc_object_release( p_sys->p_vout ); + p_sys->p_vout = NULL; + } + var_Destroy( p_this, OSD_CFG "file-path" ); var_Destroy( p_this, OSD_CFG "file" ); var_Destroy( p_this, OSD_CFG "x" ); @@ -468,6 +505,11 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t i_date ) return p_spu; } + if( p_sys->p_vout && p_sys->b_clicked ) + { + p_sys->b_clicked = VLC_FALSE; + osd_MenuActivate( p_filter ); + } /* Create new spu regions */ p_region = create_picture_region( p_filter, p_spu, @@ -606,3 +648,59 @@ static int OSDMenuCallback( vlc_object_t *p_this, char const *psz_var, p_sys->b_update = p_sys->b_visible ? VLC_TRUE : VLC_FALSE; return VLC_SUCCESS; } + +/***************************************************************************** + * 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 ) +{ + filter_sys_t *p_sys = (filter_sys_t *)p_data; + vout_thread_t *p_vout = (vout_thread_t*)p_sys->p_vout; + int i_x, i_y; + int i_v; + +#define MOUSE_DOWN 1 +#define MOUSE_CLICKED 2 +#define MOUSE_MOVE_X 4 +#define MOUSE_MOVE_Y 8 +#define MOUSE_MOVE 12 + uint8_t mouse= 0; + + int v_h = p_vout->output.i_height; + int v_w = p_vout->output.i_width; + + if( psz_var[6] == 'x' ) mouse |= MOUSE_MOVE_X; + if( psz_var[6] == 'y' ) mouse |= MOUSE_MOVE_Y; + if( psz_var[6] == 'c' ) mouse |= MOUSE_CLICKED; + + i_v = var_GetInteger( p_sys->p_vout, "mouse-button-down" ); + if( i_v & 0x1 ) mouse |= MOUSE_DOWN; + i_y = var_GetInteger( p_sys->p_vout, "mouse-y" ); + i_x = var_GetInteger( p_sys->p_vout, "mouse-x" ); + + if( i_y < 0 || i_x < 0 || i_y >= v_h || i_x >= v_w ) + return VLC_SUCCESS; + + if( mouse & MOUSE_CLICKED ) + { + int i_scale_width, i_scale_height; + osd_button_t *p_button = NULL; + + i_scale_width = p_vout->fmt_out.i_visible_width * 1000 / + p_vout->fmt_in.i_visible_width; + i_scale_height = p_vout->fmt_out.i_visible_height * 1000 / + p_vout->fmt_in.i_visible_height; + + p_button = osd_ButtonFind( p_this, i_x, i_y, v_h, v_w, + i_scale_width, i_scale_height ); + if( p_button ) + { + osd_ButtonSelect( p_this, p_button ); + p_sys->b_update = p_sys->b_visible ? VLC_TRUE : VLC_FALSE; + p_sys->b_clicked = VLC_TRUE; + msg_Dbg( p_this, "mouse clicked %s (%d,%d)\n", p_button->psz_name, i_x, i_y ); + } + } + return VLC_SUCCESS; +} diff --git a/src/osd/osd.c b/src/osd/osd.c index e5f3d140b1..72ae0f5c40 100644 --- a/src/osd/osd.c +++ b/src/osd/osd.c @@ -34,6 +34,8 @@ #undef OSD_MENU_DEBUG +static const char *ppsz_button_states[] = { "unselect", "select", "pressed" }; + /***************************************************************************** * Local prototypes *****************************************************************************/ @@ -113,6 +115,37 @@ static void osd_ParserUnload( vlc_object_t *p_this, osd_menu_t *p_menu ) vlc_object_destroy( p_menu ); } +/** + * Change state on an osd_button_t. + * + * This function selects the specified state and returns a pointer to it. The + * following states are currently supported: + * \see OSD_BUTTON_UNSELECT + * \see OSD_BUTTON_SELECT + * \see OSD_BUTTON_PRESSED + */ +static osd_state_t *osd_StateChange( osd_button_t *p_button, const int i_state ) +{ + osd_state_t *p_current = p_button->p_states; + osd_state_t *p_temp = NULL; + int i = 0; + + for( i=0; p_current != NULL; i++ ) + { + if( p_current->i_state == i_state ) + { + p_button->i_x = p_current->i_x; + p_button->i_y = p_current->i_y; + p_button->i_width = p_current->i_width; + p_button->i_height = p_current->i_height; + return p_current; + } + p_temp = p_current->p_next; + p_current = p_temp; + } + return p_button->p_states; +} + /***************************************************************************** * OSD menu Funtions *****************************************************************************/ @@ -141,7 +174,7 @@ osd_menu_t *__osd_MenuCreate( vlc_object_t *p_this, const char *psz_file ) /* Setup default button (first button) */ p_osd->p_state->p_visible = p_osd->p_button; p_osd->p_state->p_visible->p_current_state = - osd_StateChange( p_osd->p_state->p_visible->p_states, OSD_BUTTON_SELECT ); + osd_StateChange( p_osd->p_state->p_visible, OSD_BUTTON_SELECT ); p_osd->i_width = p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch; p_osd->i_height = p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_lines; @@ -206,22 +239,6 @@ void __osd_MenuDelete( vlc_object_t *p_this, osd_menu_t *p_osd ) vlc_mutex_unlock( lockval.p_address ); } -osd_state_t *__osd_StateChange( osd_state_t *p_states, const int i_state ) -{ - osd_state_t *p_current = p_states; - osd_state_t *p_temp = NULL; - int i = 0; - - for( i=0; p_current != NULL; i++ ) - { - if( p_current->i_state == i_state ) - return p_current; - p_temp = p_current->p_next; - p_current = p_temp; - } - return p_states; -} - /* The volume can be modified in another interface while the OSD Menu * has not been instantiated yet. This routines updates the "volume OSD menu item" * to reflect the current state of the GUI. @@ -276,17 +293,17 @@ void __osd_MenuShow( vlc_object_t *p_this ) if( p_button ) { if( !p_button->b_range ) - p_button->p_current_state = osd_StateChange( p_button->p_states, OSD_BUTTON_UNSELECT ); + p_button->p_current_state = osd_StateChange( p_button, OSD_BUTTON_UNSELECT ); p_osd->p_state->p_visible = p_osd->p_button; if( !p_osd->p_state->p_visible->b_range ) p_osd->p_state->p_visible->p_current_state = - osd_StateChange( p_osd->p_state->p_visible->p_states, OSD_BUTTON_SELECT ); + osd_StateChange( p_osd->p_state->p_visible, OSD_BUTTON_SELECT ); osd_UpdateState( p_osd->p_state, p_osd->p_state->p_visible->i_x, p_osd->p_state->p_visible->i_y, - p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch, - p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_lines, + p_osd->p_state->p_visible->p_current_state->i_width, + p_osd->p_state->p_visible->p_current_state->i_height, p_osd->p_state->p_visible->p_current_state->p_pic ); osd_SetMenuUpdate( p_osd, VLC_TRUE ); } @@ -369,11 +386,11 @@ void __osd_MenuActivate( vlc_object_t *p_this ) if( p_button && !p_button->b_range ) { - p_button->p_current_state = osd_StateChange( p_button->p_states, OSD_BUTTON_PRESSED ); + p_button->p_current_state = osd_StateChange( p_button, OSD_BUTTON_PRESSED ); osd_UpdateState( p_osd->p_state, p_button->i_x, p_button->i_y, - p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch, - p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_lines, + p_osd->p_state->p_visible->p_current_state->i_width, + p_osd->p_state->p_visible->p_current_state->i_height, p_button->p_current_state->p_pic ); osd_SetMenuUpdate( p_osd, VLC_TRUE ); osd_SetMenuVisible( p_osd, VLC_TRUE ); @@ -412,7 +429,7 @@ void __osd_MenuNext( vlc_object_t *p_this ) if( p_button ) { if( !p_button->b_range ) - p_button->p_current_state = osd_StateChange( p_button->p_states, OSD_BUTTON_UNSELECT ); + p_button->p_current_state = osd_StateChange( p_button, OSD_BUTTON_UNSELECT ); if( p_button->p_next ) p_osd->p_state->p_visible = p_button->p_next; else @@ -420,12 +437,12 @@ void __osd_MenuNext( vlc_object_t *p_this ) if( !p_osd->p_state->p_visible->b_range ) p_osd->p_state->p_visible->p_current_state = - osd_StateChange( p_osd->p_state->p_visible->p_states, OSD_BUTTON_SELECT ); + osd_StateChange( p_osd->p_state->p_visible, OSD_BUTTON_SELECT ); osd_UpdateState( p_osd->p_state, p_osd->p_state->p_visible->i_x, p_osd->p_state->p_visible->i_y, - p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch, - p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_lines, + p_osd->p_state->p_visible->p_current_state->i_width, + p_osd->p_state->p_visible->p_current_state->i_height, p_osd->p_state->p_visible->p_current_state->p_pic ); osd_SetMenuUpdate( p_osd, VLC_TRUE ); } @@ -463,7 +480,7 @@ void __osd_MenuPrev( vlc_object_t *p_this ) if( p_button ) { if( !p_button->b_range ) - p_button->p_current_state = osd_StateChange( p_button->p_states, OSD_BUTTON_UNSELECT ); + p_button->p_current_state = osd_StateChange( p_button, OSD_BUTTON_UNSELECT ); if( p_button->p_prev ) p_osd->p_state->p_visible = p_button->p_prev; else @@ -471,12 +488,12 @@ void __osd_MenuPrev( vlc_object_t *p_this ) if( !p_osd->p_state->p_visible->b_range ) p_osd->p_state->p_visible->p_current_state = - osd_StateChange( p_osd->p_state->p_visible->p_states, OSD_BUTTON_SELECT ); + osd_StateChange( p_osd->p_state->p_visible, OSD_BUTTON_SELECT ); osd_UpdateState( p_osd->p_state, p_osd->p_state->p_visible->i_x, p_osd->p_state->p_visible->i_y, - p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch, - p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_lines, + p_osd->p_state->p_visible->p_current_state->i_width, + p_osd->p_state->p_visible->p_current_state->i_height, p_osd->p_state->p_visible->p_current_state->p_pic ); osd_SetMenuUpdate( p_osd, VLC_TRUE ); } @@ -517,7 +534,7 @@ void __osd_MenuUp( vlc_object_t *p_this ) { if( !p_button->b_range ) { - p_button->p_current_state = osd_StateChange( p_button->p_states, OSD_BUTTON_SELECT ); + p_button->p_current_state = osd_StateChange( p_button, OSD_BUTTON_SELECT ); if( p_button->p_up ) p_osd->p_state->p_visible = p_button->p_up; } @@ -531,13 +548,13 @@ void __osd_MenuUp( vlc_object_t *p_this ) else if( !p_osd->p_state->p_visible->b_range ) { p_osd->p_state->p_visible->p_current_state = - osd_StateChange( p_osd->p_state->p_visible->p_states, OSD_BUTTON_SELECT ); + osd_StateChange( p_osd->p_state->p_visible, OSD_BUTTON_SELECT ); } osd_UpdateState( p_osd->p_state, p_osd->p_state->p_visible->i_x, p_osd->p_state->p_visible->i_y, - p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch, - p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_lines, + p_osd->p_state->p_visible->p_current_state->i_width, + p_osd->p_state->p_visible->p_current_state->i_height, p_osd->p_state->p_visible->p_current_state->p_pic ); osd_SetMenuUpdate( p_osd, VLC_TRUE ); /* If this is a range style action with associated images of only one state, @@ -589,7 +606,7 @@ void __osd_MenuDown( vlc_object_t *p_this ) { if( !p_button->b_range ) { - p_button->p_current_state = osd_StateChange( p_button->p_states, OSD_BUTTON_SELECT ); + p_button->p_current_state = osd_StateChange( p_button, OSD_BUTTON_SELECT ); if( p_button->p_down ) p_osd->p_state->p_visible = p_button->p_down; } @@ -603,13 +620,13 @@ void __osd_MenuDown( vlc_object_t *p_this ) else if( !p_osd->p_state->p_visible->b_range ) { p_osd->p_state->p_visible->p_current_state = - osd_StateChange( p_osd->p_state->p_visible->p_states, OSD_BUTTON_SELECT ); + osd_StateChange( p_osd->p_state->p_visible, OSD_BUTTON_SELECT ); } osd_UpdateState( p_osd->p_state, p_osd->p_state->p_visible->i_x, p_osd->p_state->p_visible->i_y, - p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch, - p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_lines, + p_osd->p_state->p_visible->p_current_state->i_width, + p_osd->p_state->p_visible->p_current_state->i_height, p_osd->p_state->p_visible->p_current_state->p_pic ); osd_SetMenuUpdate( p_osd, VLC_TRUE ); /* If this is a range style action with associated images of only one state, @@ -678,8 +695,8 @@ void __osd_Volume( vlc_object_t *p_this ) osd_UpdateState( p_osd->p_state, p_button->i_x, p_button->i_y, - p_button->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch, - p_button->p_current_state->p_pic->p[Y_PLANE].i_visible_lines, + p_button->p_current_state->i_width, + p_button->p_current_state->i_height, p_button->p_current_state->p_pic ); osd_SetMenuUpdate( p_osd, VLC_TRUE ); osd_SetMenuVisible( p_osd, VLC_TRUE ); @@ -688,3 +705,135 @@ void __osd_Volume( vlc_object_t *p_this ) vlc_mutex_unlock( lockval.p_address ); } } + +osd_button_t *__osd_ButtonFind( vlc_object_t *p_this, int i_x, int i_y, + int i_window_height, int i_window_width, + int i_scale_width, int i_scale_height ) +{ + osd_menu_t *p_osd; + osd_button_t *p_button, *p_start, *p_end; + vlc_value_t lockval; + + p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE ); + if( p_osd == NULL ) + { + msg_Err( p_this, "OSD menu button find failed" ); + return NULL; + } + + if( osd_isVisible( p_osd ) == VLC_FALSE ) + { + vlc_object_release( (vlc_object_t*) p_osd ); + return NULL; + } + + var_Get( p_this->p_libvlc, "osd_mutex", &lockval ); + vlc_mutex_lock( lockval.p_address ); + + p_button = p_osd->p_button; + for( ; p_button != NULL; p_button = p_button->p_next ) + { + int i_source_video_width = ( i_window_width * 1000 ) / i_scale_width; + int i_source_video_height = ( i_window_height * 1000 ) / i_scale_height; + int i_y_offset = p_button->i_y; + int i_x_offset = p_button->i_x; + int i_width = p_button->i_width; + int i_height = p_button->i_height; + + if( p_osd->i_position > 0 ) + { + int i_inv_scale_y = i_source_video_height; + int i_inv_scale_x = i_source_video_width; + int pi_x = 0; + + if( p_osd->i_position & SUBPICTURE_ALIGN_BOTTOM ) + { + i_y_offset = i_window_height - p_button->i_height - + (p_osd->i_y + p_button->i_y) * i_inv_scale_y / 1000; + } + else if ( !(p_osd->i_position & SUBPICTURE_ALIGN_TOP) ) + { + i_y_offset = i_window_height / 2 - p_button->i_height / 2; + } + + if( p_osd->i_position & SUBPICTURE_ALIGN_RIGHT ) + { + i_x_offset = i_window_width - p_button->i_width - + (pi_x + p_button->i_x) + * i_inv_scale_x / 1000; + } + else if ( !(p_osd->i_position & SUBPICTURE_ALIGN_LEFT) ) + { + i_x_offset = i_window_width / 2 - p_button->i_width / 2; + } + + i_width = i_window_width - p_button->i_width - i_inv_scale_x / 1000; + i_height = i_window_height - p_button->i_height - i_inv_scale_y / 1000; + } + + // TODO: write for Up / Down case too. + // TODO: handle absolute positioning case + if( ( i_x >= i_x_offset ) && ( i_x <= i_x_offset + i_width ) && + ( i_y >= i_y_offset ) && ( i_y <= i_y_offset + i_height ) ) + { + vlc_object_release( (vlc_object_t*) p_osd ); + vlc_mutex_unlock( lockval.p_address ); + return p_button; + } + } + + vlc_object_release( (vlc_object_t*) p_osd ); + vlc_mutex_unlock( lockval.p_address ); + return NULL; +} + +/** + * Select the button provided as the new active button + */ +void __osd_ButtonSelect( vlc_object_t *p_this, osd_button_t *p_button ) +{ + osd_menu_t *p_osd; + osd_button_t *p_old; + vlc_value_t lockval; + + p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE ); + if( p_osd == NULL ) + { + msg_Err( p_this, "OSD menu button select failed" ); + return; + } + + if( osd_isVisible( p_osd ) == VLC_FALSE ) + { + vlc_object_release( (vlc_object_t*) p_osd ); + return; + } + + var_Get( p_this->p_libvlc, "osd_mutex", &lockval ); + vlc_mutex_lock( lockval.p_address ); + + p_old = p_osd->p_state->p_visible; + if( p_old ) + { + if( !p_old->b_range ) + p_old->p_current_state = osd_StateChange( p_old, OSD_BUTTON_UNSELECT ); + p_osd->p_state->p_visible = p_button; + + if( !p_osd->p_state->p_visible->b_range ) + p_osd->p_state->p_visible->p_current_state = + osd_StateChange( p_osd->p_state->p_visible, OSD_BUTTON_SELECT ); + + osd_UpdateState( p_osd->p_state, + p_osd->p_state->p_visible->i_x, p_osd->p_state->p_visible->i_y, + p_osd->p_state->p_visible->p_current_state->i_width, + p_osd->p_state->p_visible->p_current_state->i_height, + p_osd->p_state->p_visible->p_current_state->p_pic ); + osd_SetMenuUpdate( p_osd, VLC_TRUE ); + } +#if defined(OSD_MENU_DEBUG) + msg_Dbg( p_osd, "button selected is [button %s]", p_osd->p_state->p_visible->psz_action ); +#endif + + vlc_object_release( (vlc_object_t*) p_osd ); + vlc_mutex_unlock( lockval.p_address ); +} -- 2.39.2