1 /*****************************************************************************
2 * osd.c - The OSD Menu core code.
3 *****************************************************************************
4 * Copyright (C) 2005-2008 M2X
7 * Authors: Jean-Paul Saman <jpsaman #_at_# m2x dot nl>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
32 #include <vlc_common.h>
35 #include <vlc_image.h>
41 /*****************************************************************************
43 *****************************************************************************/
45 static void osd_UpdateState( osd_menu_state_t *, int, int, int, int, picture_t * );
46 static inline osd_state_t *osd_VolumeStateChange( osd_state_t *, int );
47 static int osd_VolumeStep( vlc_object_t *, int, int );
48 static bool osd_isVisible( osd_menu_t *p_osd );
49 static bool osd_ParserLoad( osd_menu_t *, const char * );
50 static void osd_ParserUnload( osd_menu_t * );
52 static bool osd_isVisible( osd_menu_t *p_osd )
56 var_Get( p_osd, "osd-menu-visible", &val );
60 /*****************************************************************************
61 * Wrappers for loading and unloading osd parser modules.
62 *****************************************************************************/
63 static bool osd_ParserLoad( osd_menu_t *p_menu, const char *psz_file )
65 /* Stuff needed for Parser */
66 p_menu->psz_file = strdup( psz_file );
67 p_menu->p_image = image_HandlerCreate( p_menu );
68 if( !p_menu->p_image || !p_menu->psz_file )
70 msg_Err( p_menu, "unable to load images, aborting .." );
71 osd_ParserUnload( p_menu );
77 char *psz_ext = strrchr( p_menu->psz_file, '.' );
79 if( psz_ext && !strcmp( psz_ext, ".cfg") )
80 psz_type = (char*)"import-osd";
82 psz_type = (char*)"import-osd-xml";
84 p_menu->p_parser = module_Need( p_menu, "osd parser",
86 if( !p_menu->p_parser )
88 osd_ParserUnload( p_menu );
95 static void osd_ParserUnload( osd_menu_t *p_menu )
98 image_HandlerDelete( p_menu->p_image );
100 if( p_menu->p_parser )
101 module_Unneed( p_menu, p_menu->p_parser );
103 free( p_menu->psz_file );
107 * Change state on an osd_button_t.
109 * This function selects the specified state and returns a pointer vlc_custom_createto it. The
110 * following states are currently supported:
111 * \see OSD_BUTTON_UNSELECT
112 * \see OSD_BUTTON_SELECT
113 * \see OSD_BUTTON_PRESSED
115 static osd_state_t *osd_StateChange( osd_button_t *p_button, const int i_state )
117 osd_state_t *p_current = p_button->p_states;
118 osd_state_t *p_temp = NULL;
121 for( i=0; p_current != NULL; i++ )
123 if( p_current->i_state == i_state )
125 p_button->i_x = p_current->i_x;
126 p_button->i_y = p_current->i_y;
127 p_button->i_width = p_current->i_width;
128 p_button->i_height = p_current->i_height;
131 p_temp = p_current->p_next;
134 return p_button->p_states;
137 /*****************************************************************************
139 *****************************************************************************/
140 osd_menu_t *__osd_MenuCreate( vlc_object_t *p_this, const char *psz_file )
142 osd_menu_t *p_osd = NULL;
147 /* to be sure to avoid multiple creation */
148 var_Create( p_this->p_libvlc, "osd_mutex", VLC_VAR_MUTEX );
149 var_Get( p_this->p_libvlc, "osd_mutex", &lockval );
150 vlc_mutex_lock( lockval.p_address );
152 p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE );
155 static const char osdmenu_name[] = "osd menu";
158 p_osd = vlc_custom_create( p_this, sizeof( *p_osd ), VLC_OBJECT_OSDMENU,
163 p_osd->p_parser = NULL;
164 vlc_object_attach( p_osd, p_this->p_libvlc );
166 /* Parse configuration file */
167 if ( !osd_ParserLoad( p_osd, psz_file ) )
169 if( !p_osd->p_state )
172 /* Setup default button (first button) */
173 p_osd->p_state->p_visible = p_osd->p_button;
174 p_osd->p_state->p_visible->p_current_state =
175 osd_StateChange( p_osd->p_state->p_visible, OSD_BUTTON_SELECT );
176 p_osd->i_width = p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch;
177 p_osd->i_height = p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_lines;
179 if( p_osd->p_state->p_volume )
181 /* Update the volume state images to match the current volume */
182 i_volume = config_GetInt( p_this, "volume" );
183 i_steps = osd_VolumeStep( p_this, i_volume, p_osd->p_state->p_volume->i_ranges );
184 p_osd->p_state->p_volume->p_current_state = osd_VolumeStateChange(
185 p_osd->p_state->p_volume->p_states, i_steps );
187 /* Initialize OSD state */
188 osd_UpdateState( p_osd->p_state, p_osd->i_x, p_osd->i_y,
189 p_osd->i_width, p_osd->i_height, NULL );
191 /* Signal when an update of OSD menu is needed */
192 var_Create( p_osd, "osd-menu-update", VLC_VAR_BOOL );
193 var_Create( p_osd, "osd-menu-visible", VLC_VAR_BOOL );
196 var_Set( p_osd, "osd-menu-update", val );
197 var_Set( p_osd, "osd-menu-visible", val );
199 vlc_mutex_unlock( lockval.p_address );
203 __osd_MenuDelete( p_this, p_osd );
207 void __osd_MenuDelete( vlc_object_t *p_this, osd_menu_t *p_osd )
211 if( !p_osd || !p_this ) return;
213 var_Get( p_this->p_libvlc, "osd_mutex", &lockval );
214 vlc_mutex_lock( lockval.p_address );
216 if( vlc_internals( VLC_OBJECT(p_osd) )->i_refcount == 1 )
218 var_Destroy( p_osd, "osd-menu-visible" );
219 var_Destroy( p_osd, "osd-menu-update" );
220 osd_ParserUnload( p_osd );
223 vlc_object_release( p_osd );
224 if( vlc_internals( VLC_OBJECT(p_osd) )->i_refcount > 0 )
226 vlc_mutex_unlock( lockval.p_address );
230 vlc_mutex_unlock( lockval.p_address );
233 /* The volume can be modified in another interface while the OSD Menu
234 * has not been instantiated yet. This routines updates the "volume OSD menu item"
235 * to reflect the current state of the GUI.
237 static inline osd_state_t *osd_VolumeStateChange( osd_state_t *p_current, int i_steps )
239 osd_state_t *p_temp = NULL;
242 if( i_steps < 0 ) i_steps = 0;
244 for( i=0; (i < i_steps) && (p_current != NULL); i++ )
246 p_temp = p_current->p_next;
247 if( !p_temp ) return p_current;
250 return (!p_temp) ? p_current : p_temp;
253 /* Update the state of the OSD Menu */
254 static void osd_UpdateState( osd_menu_state_t *p_state, int i_x, int i_y,
255 int i_width, int i_height, picture_t *p_pic )
259 p_state->i_width = i_width;
260 p_state->i_height = i_height;
261 p_state->p_pic = p_pic;
264 void __osd_MenuShow( vlc_object_t *p_this )
266 osd_menu_t *p_osd = NULL;
267 osd_button_t *p_button = NULL;
270 p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE );
273 msg_Err( p_this, "osd_MenuNext failed" );
277 var_Get( p_this->p_libvlc, "osd_mutex", &lockval );
278 vlc_mutex_lock( lockval.p_address );
280 #if defined(OSD_MENU_DEBUG)
281 msg_Dbg( p_osd, "menu on" );
283 p_button = p_osd->p_state->p_visible;
286 if( !p_button->b_range )
287 p_button->p_current_state = osd_StateChange( p_button, OSD_BUTTON_UNSELECT );
288 p_osd->p_state->p_visible = p_osd->p_button;
290 if( !p_osd->p_state->p_visible->b_range )
291 p_osd->p_state->p_visible->p_current_state =
292 osd_StateChange( p_osd->p_state->p_visible, OSD_BUTTON_SELECT );
294 osd_UpdateState( p_osd->p_state,
295 p_osd->p_state->p_visible->i_x, p_osd->p_state->p_visible->i_y,
296 p_osd->p_state->p_visible->p_current_state->i_width,
297 p_osd->p_state->p_visible->p_current_state->i_height,
298 p_osd->p_state->p_visible->p_current_state->p_pic );
299 osd_SetMenuUpdate( p_osd, true );
301 osd_SetMenuVisible( p_osd, true );
303 vlc_object_release( (vlc_object_t*) p_osd );
304 vlc_mutex_unlock( lockval.p_address );
307 void __osd_MenuHide( vlc_object_t *p_this )
309 osd_menu_t *p_osd = NULL;
312 p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE );
315 msg_Err( p_this, "osd_MenuNext failed" );
319 var_Get( p_this->p_libvlc, "osd_mutex", &lockval );
320 vlc_mutex_lock( lockval.p_address );
322 #if defined(OSD_MENU_DEBUG)
323 msg_Dbg( p_osd, "menu off" );
325 osd_UpdateState( p_osd->p_state,
326 p_osd->p_state->i_x, p_osd->p_state->i_y,
328 osd_SetMenuUpdate( p_osd, true );
330 vlc_object_release( (vlc_object_t*) p_osd );
331 vlc_mutex_unlock( lockval.p_address );
334 void __osd_MenuActivate( vlc_object_t *p_this )
336 osd_menu_t *p_osd = NULL;
337 osd_button_t *p_button = NULL;
340 p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE );
343 msg_Err( p_this, "osd_MenuNext failed" );
347 if( osd_isVisible( p_osd ) == false )
349 vlc_object_release( (vlc_object_t*) p_osd );
353 var_Get( p_this->p_libvlc, "osd_mutex", &lockval );
354 vlc_mutex_lock( lockval.p_address );
356 #if defined(OSD_MENU_DEBUG)
357 msg_Dbg( p_osd, "select" );
359 p_button = p_osd->p_state->p_visible;
361 * Is there a menu item above or below? If so, then select it.
363 if( p_button && p_button->p_up )
365 vlc_object_release( (vlc_object_t*) p_osd );
366 vlc_mutex_unlock( lockval.p_address );
367 __osd_MenuUp( p_this ); /* "menu select" means go to menu item above. */
370 if( p_button && p_button->p_down )
372 vlc_object_release( (vlc_object_t*) p_osd );
373 vlc_mutex_unlock( lockval.p_address );
374 __osd_MenuDown( p_this ); /* "menu select" means go to menu item below. */
378 if( p_button && !p_button->b_range )
380 p_button->p_current_state = osd_StateChange( p_button, OSD_BUTTON_PRESSED );
381 osd_UpdateState( p_osd->p_state,
382 p_button->i_x, p_button->i_y,
383 p_osd->p_state->p_visible->p_current_state->i_width,
384 p_osd->p_state->p_visible->p_current_state->i_height,
385 p_button->p_current_state->p_pic );
386 osd_SetMenuUpdate( p_osd, true );
387 osd_SetMenuVisible( p_osd, true );
388 osd_SetKeyPressed( VLC_OBJECT(p_osd->p_libvlc), config_GetInt( p_osd, p_button->psz_action ) );
389 #if defined(OSD_MENU_DEBUG)
390 msg_Dbg( p_osd, "select (%d, %s)", config_GetInt( p_osd, p_button->psz_action ), p_button->psz_action );
393 vlc_object_release( (vlc_object_t*) p_osd );
394 vlc_mutex_unlock( lockval.p_address );
397 void __osd_MenuNext( vlc_object_t *p_this )
399 osd_menu_t *p_osd = NULL;
400 osd_button_t *p_button = NULL;
403 p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE );
406 msg_Err( p_this, "osd_MenuNext failed" );
410 if( osd_isVisible( p_osd ) == false )
412 vlc_object_release( (vlc_object_t*) p_osd );
416 var_Get( p_this->p_libvlc, "osd_mutex", &lockval );
417 vlc_mutex_lock( lockval.p_address );
419 p_button = p_osd->p_state->p_visible;
422 if( !p_button->b_range )
423 p_button->p_current_state = osd_StateChange( p_button, OSD_BUTTON_UNSELECT );
424 if( p_button->p_next )
425 p_osd->p_state->p_visible = p_button->p_next;
427 p_osd->p_state->p_visible = p_osd->p_button;
429 if( !p_osd->p_state->p_visible->b_range )
430 p_osd->p_state->p_visible->p_current_state =
431 osd_StateChange( p_osd->p_state->p_visible, OSD_BUTTON_SELECT );
433 osd_UpdateState( p_osd->p_state,
434 p_osd->p_state->p_visible->i_x, p_osd->p_state->p_visible->i_y,
435 p_osd->p_state->p_visible->p_current_state->i_width,
436 p_osd->p_state->p_visible->p_current_state->i_height,
437 p_osd->p_state->p_visible->p_current_state->p_pic );
438 osd_SetMenuUpdate( p_osd, true );
440 #if defined(OSD_MENU_DEBUG)
441 msg_Dbg( p_osd, "direction right [button %s]", p_osd->p_state->p_visible->psz_action );
444 vlc_object_release( (vlc_object_t*) p_osd );
445 vlc_mutex_unlock( lockval.p_address );
448 void __osd_MenuPrev( vlc_object_t *p_this )
450 osd_menu_t *p_osd = NULL;
451 osd_button_t *p_button = NULL;
454 p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE );
457 msg_Err( p_this, "osd_MenuPrev failed" );
461 if( osd_isVisible( p_osd ) == false )
463 vlc_object_release( (vlc_object_t*) p_osd );
467 var_Get( p_this->p_libvlc, "osd_mutex", &lockval );
468 vlc_mutex_lock( lockval.p_address );
470 p_button = p_osd->p_state->p_visible;
473 if( !p_button->b_range )
474 p_button->p_current_state = osd_StateChange( p_button, OSD_BUTTON_UNSELECT );
475 if( p_button->p_prev )
476 p_osd->p_state->p_visible = p_button->p_prev;
478 p_osd->p_state->p_visible = p_osd->p_last_button;
480 if( !p_osd->p_state->p_visible->b_range )
481 p_osd->p_state->p_visible->p_current_state =
482 osd_StateChange( p_osd->p_state->p_visible, OSD_BUTTON_SELECT );
484 osd_UpdateState( p_osd->p_state,
485 p_osd->p_state->p_visible->i_x, p_osd->p_state->p_visible->i_y,
486 p_osd->p_state->p_visible->p_current_state->i_width,
487 p_osd->p_state->p_visible->p_current_state->i_height,
488 p_osd->p_state->p_visible->p_current_state->p_pic );
489 osd_SetMenuUpdate( p_osd, true );
491 #if defined(OSD_MENU_DEBUG)
492 msg_Dbg( p_osd, "direction left [button %s]", p_osd->p_state->p_visible->psz_action );
495 vlc_object_release( (vlc_object_t*) p_osd );
496 vlc_mutex_unlock( lockval.p_address );
499 void __osd_MenuUp( vlc_object_t *p_this )
501 osd_menu_t *p_osd = NULL;
502 osd_button_t *p_button = NULL;
504 #if defined(OSD_MENU_DEBUG)
507 p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE );
510 msg_Err( p_this, "osd_MenuDown failed" );
514 if( osd_isVisible( p_osd ) == false )
516 vlc_object_release( (vlc_object_t*) p_osd );
520 var_Get( p_this->p_libvlc, "osd_mutex", &lockval );
521 vlc_mutex_lock( lockval.p_address );
523 p_button = p_osd->p_state->p_visible;
526 if( !p_button->b_range )
528 p_button->p_current_state = osd_StateChange( p_button, OSD_BUTTON_SELECT );
530 p_osd->p_state->p_visible = p_button->p_up;
533 if( p_button->b_range && p_osd->p_state->p_visible->b_range )
535 osd_state_t *p_temp = p_osd->p_state->p_visible->p_current_state;
536 if( p_temp && p_temp->p_next )
537 p_osd->p_state->p_visible->p_current_state = p_temp->p_next;
539 else if( !p_osd->p_state->p_visible->b_range )
541 p_osd->p_state->p_visible->p_current_state =
542 osd_StateChange( p_osd->p_state->p_visible, OSD_BUTTON_SELECT );
545 osd_UpdateState( p_osd->p_state,
546 p_osd->p_state->p_visible->i_x, p_osd->p_state->p_visible->i_y,
547 p_osd->p_state->p_visible->p_current_state->i_width,
548 p_osd->p_state->p_visible->p_current_state->i_height,
549 p_osd->p_state->p_visible->p_current_state->p_pic );
550 osd_SetMenuUpdate( p_osd, true );
551 /* If this is a range style action with associated images of only one state,
552 * then perform "menu select" on every menu navigation
554 if( p_button->b_range )
556 osd_SetKeyPressed( VLC_OBJECT(p_osd->p_libvlc), config_GetInt(p_osd, p_button->psz_action) );
557 #if defined(OSD_MENU_DEBUG)
558 msg_Dbg( p_osd, "select (%d, %s)", val.i_int, p_button->psz_action );
562 #if defined(OSD_MENU_DEBUG)
563 msg_Dbg( p_osd, "direction up [button %s]", p_osd->p_state->p_visible->psz_action );
566 vlc_object_release( (vlc_object_t*) p_osd );
567 vlc_mutex_unlock( lockval.p_address );
570 void __osd_MenuDown( vlc_object_t *p_this )
572 osd_menu_t *p_osd = NULL;
573 osd_button_t *p_button = NULL;
575 #if defined(OSD_MENU_DEBUG)
579 p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE );
582 msg_Err( p_this, "osd_MenuDown failed" );
586 if( osd_isVisible( p_osd ) == false )
588 vlc_object_release( (vlc_object_t*) p_osd );
592 var_Get( p_this->p_libvlc, "osd_mutex", &lockval );
593 vlc_mutex_lock( lockval.p_address );
595 p_button = p_osd->p_state->p_visible;
598 if( !p_button->b_range )
600 p_button->p_current_state = osd_StateChange( p_button, OSD_BUTTON_SELECT );
601 if( p_button->p_down )
602 p_osd->p_state->p_visible = p_button->p_down;
605 if( p_button->b_range && p_osd->p_state->p_visible->b_range )
607 osd_state_t *p_temp = p_osd->p_state->p_visible->p_current_state;
608 if( p_temp && p_temp->p_prev )
609 p_osd->p_state->p_visible->p_current_state = p_temp->p_prev;
611 else if( !p_osd->p_state->p_visible->b_range )
613 p_osd->p_state->p_visible->p_current_state =
614 osd_StateChange( p_osd->p_state->p_visible, OSD_BUTTON_SELECT );
617 osd_UpdateState( p_osd->p_state,
618 p_osd->p_state->p_visible->i_x, p_osd->p_state->p_visible->i_y,
619 p_osd->p_state->p_visible->p_current_state->i_width,
620 p_osd->p_state->p_visible->p_current_state->i_height,
621 p_osd->p_state->p_visible->p_current_state->p_pic );
622 osd_SetMenuUpdate( p_osd, true );
623 /* If this is a range style action with associated images of only one state,
624 * then perform "menu select" on every menu navigation
626 if( p_button->b_range )
628 osd_SetKeyPressed( VLC_OBJECT(p_osd->p_libvlc), config_GetInt(p_osd, p_button->psz_action_down) );
629 #if defined(OSD_MENU_DEBUG)
630 msg_Dbg( p_osd, "select (%d, %s)", val.i_int, p_button->psz_action_down );
634 #if defined(OSD_MENU_DEBUG)
635 msg_Dbg( p_osd, "direction down [button %s]", p_osd->p_state->p_visible->psz_action );
638 vlc_object_release( (vlc_object_t*) p_osd );
639 vlc_mutex_unlock( lockval.p_address );
642 static int osd_VolumeStep( vlc_object_t *p_this, int i_volume, int i_steps )
644 int i_volume_step = 0;
647 i_volume_step = config_GetInt( p_this->p_libvlc, "volume-step" );
648 return (i_volume/i_volume_step);
652 * Display current audio volume bitmap
654 * The OSD Menu audio volume bar is updated to reflect the new audio volume. Call this function
655 * when the audio volume is updated outside the OSD menu command "menu up", "menu down" or "menu select".
657 void __osd_Volume( vlc_object_t *p_this )
659 osd_menu_t *p_osd = NULL;
660 osd_button_t *p_button = NULL;
665 p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE );
668 msg_Err( p_this, "OSD menu volume update failed" );
672 if( p_osd->p_state && p_osd->p_state->p_volume )
674 var_Get( p_this->p_libvlc, "osd_mutex", &lockval );
675 vlc_mutex_lock( lockval.p_address );
677 p_button = p_osd->p_state->p_volume;
678 if( p_osd->p_state->p_volume )
679 p_osd->p_state->p_visible = p_osd->p_state->p_volume;
680 if( p_button && p_button->b_range )
682 /* Update the volume state images to match the current volume */
683 i_volume = config_GetInt( p_this, "volume" );
684 i_steps = osd_VolumeStep( p_this, i_volume, p_button->i_ranges );
685 p_button->p_current_state = osd_VolumeStateChange( p_button->p_states, i_steps );
687 osd_UpdateState( p_osd->p_state,
688 p_button->i_x, p_button->i_y,
689 p_button->p_current_state->i_width,
690 p_button->p_current_state->i_height,
691 p_button->p_current_state->p_pic );
692 osd_SetMenuUpdate( p_osd, true );
693 osd_SetMenuVisible( p_osd, true );
695 vlc_mutex_unlock( lockval.p_address );
697 vlc_object_release( p_osd );
700 osd_button_t *__osd_ButtonFind( vlc_object_t *p_this, int i_x, int i_y,
701 int i_window_height, int i_window_width,
702 int i_scale_width, int i_scale_height )
705 osd_button_t *p_button;
708 p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE );
711 msg_Err( p_this, "OSD menu button find failed" );
715 if( osd_isVisible( p_osd ) == false )
717 vlc_object_release( p_osd );
721 var_Get( p_this->p_libvlc, "osd_mutex", &lockval );
722 vlc_mutex_lock( lockval.p_address );
724 p_button = p_osd->p_button;
725 for( ; p_button != NULL; p_button = p_button->p_next )
727 int i_source_video_width = ( i_window_width * 1000 ) / i_scale_width;
728 int i_source_video_height = ( i_window_height * 1000 ) / i_scale_height;
729 int i_y_offset = p_button->i_y;
730 int i_x_offset = p_button->i_x;
731 int i_width = p_button->i_width;
732 int i_height = p_button->i_height;
734 if( p_osd->i_position > 0 )
736 int i_inv_scale_y = i_source_video_height;
737 int i_inv_scale_x = i_source_video_width;
740 if( p_osd->i_position & SUBPICTURE_ALIGN_BOTTOM )
742 i_y_offset = i_window_height - p_button->i_height -
743 (p_osd->i_y + p_button->i_y) * i_inv_scale_y / 1000;
745 else if ( !(p_osd->i_position & SUBPICTURE_ALIGN_TOP) )
747 i_y_offset = i_window_height / 2 - p_button->i_height / 2;
750 if( p_osd->i_position & SUBPICTURE_ALIGN_RIGHT )
752 i_x_offset = i_window_width - p_button->i_width -
753 (pi_x + p_button->i_x)
754 * i_inv_scale_x / 1000;
756 else if ( !(p_osd->i_position & SUBPICTURE_ALIGN_LEFT) )
758 i_x_offset = i_window_width / 2 - p_button->i_width / 2;
761 i_width = i_window_width - p_button->i_width - i_inv_scale_x / 1000;
762 i_height = i_window_height - p_button->i_height - i_inv_scale_y / 1000;
765 // TODO: write for Up / Down case too.
766 // TODO: handle absolute positioning case
767 if( ( i_x >= i_x_offset ) && ( i_x <= i_x_offset + i_width ) &&
768 ( i_y >= i_y_offset ) && ( i_y <= i_y_offset + i_height ) )
770 vlc_object_release( p_osd );
771 vlc_mutex_unlock( lockval.p_address );
776 vlc_object_release( p_osd );
777 vlc_mutex_unlock( lockval.p_address );
782 * Select the button provided as the new active button
784 void __osd_ButtonSelect( vlc_object_t *p_this, osd_button_t *p_button )
790 p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE );
793 msg_Err( p_this, "OSD menu button select failed" );
797 if( osd_isVisible( p_osd ) == false )
799 vlc_object_release( (vlc_object_t*) p_osd );
803 var_Get( p_this->p_libvlc, "osd_mutex", &lockval );
804 vlc_mutex_lock( lockval.p_address );
806 p_old = p_osd->p_state->p_visible;
809 if( !p_old->b_range )
810 p_old->p_current_state = osd_StateChange( p_old, OSD_BUTTON_UNSELECT );
811 p_osd->p_state->p_visible = p_button;
813 if( !p_osd->p_state->p_visible->b_range )
814 p_osd->p_state->p_visible->p_current_state =
815 osd_StateChange( p_osd->p_state->p_visible, OSD_BUTTON_SELECT );
817 osd_UpdateState( p_osd->p_state,
818 p_osd->p_state->p_visible->i_x, p_osd->p_state->p_visible->i_y,
819 p_osd->p_state->p_visible->p_current_state->i_width,
820 p_osd->p_state->p_visible->p_current_state->i_height,
821 p_osd->p_state->p_visible->p_current_state->p_pic );
822 osd_SetMenuUpdate( p_osd, true );
824 #if defined(OSD_MENU_DEBUG)
825 msg_Dbg( p_osd, "button selected is [button %s]", p_osd->p_state->p_visible->psz_action );
828 vlc_object_release( p_osd );
829 vlc_mutex_unlock( lockval.p_address );