]> git.sesse.net Git - vlc/blob - src/osd/osd.c
Added --volume-step to override AOUT_VOLUME_DEFAULT. This will give an OSD menu ...
[vlc] / src / osd / osd.c
1 /*****************************************************************************\r
2  * osd.c - The OSD Menu core code.\r
3  *****************************************************************************\r
4  * Copyright (C) 2005 M2X\r
5  * $Id: osd.c 9451 2004-12-01 01:07:08Z jpsaman $\r
6  *\r
7  * Authors: Jean-Paul Saman <jpsaman #_at_# m2x dot nl>\r
8  *\r
9  * This program is free software; you can redistribute it and/or modify\r
10  * it under the terms of the GNU General Public License as published by\r
11  * the Free Software Foundation; either version 2 of the License, or\r
12  * (at your option) any later version.\r
13  *\r
14  * This program is distributed in the hope that it will be useful,\r
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
17  * GNU General Public License for more details.\r
18  *\r
19  * You should have received a copy of the GNU General Public License\r
20  * along with this program; if not, write to the Free Software\r
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.\r
22  *****************************************************************************/\r
23 \r
24 /*****************************************************************************\r
25  * Preamble\r
26  *****************************************************************************/\r
27 #include <stdlib.h>\r
28 #include <string.h>\r
29 \r
30 #include <vlc/vlc.h>\r
31 #include <vlc_keys.h>\r
32 #include <vlc_osd.h>\r
33 \r
34 #undef OSD_MENU_DEBUG\r
35 \r
36 /*****************************************************************************\r
37  * Local prototypes\r
38  *****************************************************************************/\r
39 \r
40 static void osd_UpdateState( osd_menu_state_t *, int, int, int, int, picture_t * );\r
41 static inline osd_state_t *osd_VolumeStateChange( osd_state_t *, int );\r
42 static int osd_VolumeStep( vlc_object_t *, int, int );\r
43 \r
44 /*****************************************************************************\r
45  * OSD menu Funtions\r
46  *****************************************************************************/\r
47 osd_menu_t *__osd_MenuCreate( vlc_object_t *p_this, const char *psz_file )\r
48 {\r
49     osd_menu_t  *p_osd = NULL;\r
50     vlc_value_t lockval;\r
51     int         i_volume = 0;\r
52     int         i_steps = 0;\r
53 \r
54     /* to be sure to avoid multiple creation */\r
55     var_Create( p_this->p_libvlc, "osd_mutex", VLC_VAR_MUTEX );\r
56     var_Get( p_this->p_libvlc, "osd_mutex", &lockval );\r
57     vlc_mutex_lock( lockval.p_address );\r
58     \r
59     if( ( p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE ) ) == NULL )\r
60     {\r
61         vlc_value_t val;\r
62         \r
63         msg_Dbg( p_this, "creating osd menu object" );\r
64         if( ( p_osd = vlc_object_create( p_this, VLC_OBJECT_OSDMENU ) ) == NULL )\r
65         {\r
66             msg_Err( p_this, "out of memory" );\r
67             vlc_mutex_unlock( lockval.p_address );\r
68             return NULL;\r
69         }\r
70 \r
71         /* Parse configuration file */\r
72         if( osd_ConfigLoader( p_this, psz_file, &p_osd ) )\r
73             goto error;\r
74         \r
75         /* Setup default button (first button) */\r
76         p_osd->p_state->p_visible = p_osd->p_button;\r
77         p_osd->p_state->p_visible->p_current_state =\r
78             osd_StateChange( p_osd->p_state->p_visible->p_states, OSD_BUTTON_SELECT );\r
79         p_osd->i_width  = p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch;\r
80         p_osd->i_height = p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_lines;\r
81 \r
82         /* Update the volume state images to match the current volume */\r
83         i_volume = config_GetInt( p_this, "volume" );\r
84         i_steps = osd_VolumeStep( p_this, i_volume, p_osd->p_state->p_volume->i_ranges );\r
85         p_osd->p_state->p_volume->p_current_state = osd_VolumeStateChange( p_osd->p_state->p_volume->p_states, i_steps );\r
86 \r
87         /* Initialize OSD state */\r
88         osd_UpdateState( p_osd->p_state, p_osd->i_x, p_osd->i_y,\r
89                          p_osd->i_width, p_osd->i_height, NULL );\r
90         \r
91         vlc_object_yield( p_osd );\r
92         vlc_object_attach( p_osd, p_this->p_vlc );\r
93         \r
94         /* Signal when an update of OSD menu is needed */\r
95         var_Create( p_osd, "osd-menu-update", VLC_VAR_BOOL );\r
96         var_Create( p_osd, "osd-menu-visible", VLC_VAR_BOOL );\r
97 \r
98         val.b_bool = VLC_FALSE;\r
99         var_Set( p_osd, "osd-menu-update", val );\r
100         var_Set( p_osd, "osd-menu-visible", val );        \r
101     }\r
102     vlc_mutex_unlock( lockval.p_address );\r
103     return p_osd;\r
104     \r
105 error:\r
106     msg_Err( p_this, "creating osd menu object failed" );\r
107     vlc_mutex_unlock( lockval.p_address );\r
108     vlc_object_destroy( p_osd );\r
109     return NULL;    \r
110 }\r
111 \r
112 void __osd_MenuDelete( vlc_object_t *p_this, osd_menu_t *p_osd )\r
113 {\r
114     vlc_value_t lockval;\r
115 \r
116     if( !p_osd || !p_this ) return;\r
117     \r
118     var_Get( p_this->p_libvlc, "osd_mutex", &lockval );\r
119     vlc_mutex_lock( lockval.p_address );\r
120 \r
121     vlc_object_release( p_osd );    \r
122     if( p_osd->i_refcount > 0 )\r
123     {\r
124         vlc_mutex_unlock( lockval.p_address );        \r
125         return;\r
126     }    \r
127 \r
128     var_Destroy( p_osd, "osd-menu-visible" );\r
129     var_Destroy( p_osd, "osd-menu-update" );\r
130     \r
131     osd_ConfigUnload( p_this, &p_osd );\r
132     vlc_object_detach( p_osd );\r
133     vlc_object_destroy( p_osd );\r
134     p_osd = NULL;\r
135     \r
136     vlc_mutex_unlock( lockval.p_address );        \r
137 }\r
138 \r
139 osd_state_t *__osd_StateChange( osd_state_t *p_states, const int i_state )\r
140 {\r
141     osd_state_t *p_current = p_states;\r
142     osd_state_t *p_temp = NULL;\r
143     int i = 0;\r
144 \r
145     for( i=0; p_current != NULL; i++ )\r
146     {\r
147         if( p_current->i_state == i_state )\r
148             return p_current;\r
149         p_temp = p_current->p_next;\r
150         p_current = p_temp;\r
151     }\r
152     return p_states;\r
153 }\r
154 \r
155 /* The volume can be modified in another interface while the OSD Menu \r
156  * has not been instantiated yet. This routines updates the "volume OSD menu item"\r
157  * to reflect the current state of the GUI.\r
158  */\r
159 static inline osd_state_t *osd_VolumeStateChange( osd_state_t *p_current, int i_steps )\r
160 {\r
161     osd_state_t *p_temp = NULL;\r
162     int i;\r
163 \r
164     if( i_steps < 0 ) i_steps = 0;\r
165     \r
166     for( i=0; (i < i_steps) && (p_current != NULL); i++ )\r
167     {    \r
168         p_temp = p_current->p_next;\r
169         if( !p_temp ) return p_current;\r
170         p_current = p_temp;\r
171     }\r
172     return (!p_temp) ? p_current : p_temp;\r
173 }\r
174 \r
175 /* Update the state of the OSD Menu */\r
176 static void osd_UpdateState( osd_menu_state_t *p_state, int i_x, int i_y,\r
177         int i_width, int i_height, picture_t *p_pic )\r
178 {\r
179     p_state->i_x = i_x;\r
180     p_state->i_y = i_y;\r
181     p_state->i_width = i_width;\r
182     p_state->i_height = i_height;\r
183     p_state->p_pic = p_pic;\r
184 }\r
185 \r
186 void __osd_MenuShow( vlc_object_t *p_this )\r
187 {\r
188     osd_menu_t *p_osd = NULL;\r
189     osd_button_t *p_button = NULL;\r
190     vlc_value_t lockval;\r
191     \r
192     if( ( p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE ) ) == NULL )\r
193     {\r
194         msg_Err( p_this, "osd_MenuNext failed" );\r
195         return;\r
196     }        \r
197 \r
198     var_Get( p_this->p_libvlc, "osd_mutex", &lockval );\r
199     vlc_mutex_lock( lockval.p_address );\r
200 \r
201 #if defined(OSD_MENU_DEBUG)\r
202     msg_Dbg( p_osd, "menu on" );\r
203 #endif            \r
204     p_button = p_osd->p_state->p_visible;\r
205     if( p_button )\r
206     {                    \r
207         if( !p_button->b_range ) \r
208             p_button->p_current_state = osd_StateChange( p_button->p_states, OSD_BUTTON_UNSELECT );\r
209         p_osd->p_state->p_visible = p_osd->p_button;\r
210         \r
211         if( !p_osd->p_state->p_visible->b_range ) \r
212             p_osd->p_state->p_visible->p_current_state =\r
213                 osd_StateChange( p_osd->p_state->p_visible->p_states, OSD_BUTTON_SELECT );\r
214         \r
215         osd_UpdateState( p_osd->p_state,\r
216                 p_osd->p_state->p_visible->i_x, p_osd->p_state->p_visible->i_y,\r
217                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch,\r
218                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_lines,\r
219                 p_osd->p_state->p_visible->p_current_state->p_pic );                \r
220         osd_SetMenuUpdate( p_osd, VLC_TRUE );\r
221     }\r
222     osd_SetMenuVisible( p_osd, VLC_TRUE );\r
223     \r
224     vlc_object_release( (vlc_object_t*) p_osd );\r
225     vlc_mutex_unlock( lockval.p_address );\r
226 }\r
227             \r
228 void __osd_MenuHide( vlc_object_t *p_this )\r
229 {\r
230     osd_menu_t *p_osd = NULL;\r
231     vlc_value_t lockval;\r
232     \r
233     if( ( p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE ) ) == NULL )\r
234     {\r
235         msg_Err( p_this, "osd_MenuNext failed" );\r
236         return;\r
237     }\r
238         \r
239     var_Get( p_this->p_libvlc, "osd_mutex", &lockval );\r
240     vlc_mutex_lock( lockval.p_address );\r
241 \r
242 #if defined(OSD_MENU_DEBUG)\r
243     msg_Dbg( p_osd, "menu off" );\r
244 #endif\r
245     osd_UpdateState( p_osd->p_state,\r
246                 p_osd->p_state->i_x, p_osd->p_state->i_y,\r
247                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch,\r
248                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_lines,\r
249                 NULL );\r
250     osd_SetMenuUpdate( p_osd, VLC_TRUE );\r
251 \r
252     vlc_object_release( (vlc_object_t*) p_osd );\r
253     vlc_mutex_unlock( lockval.p_address );\r
254 }\r
255 \r
256 void __osd_MenuActivate( vlc_object_t *p_this )\r
257 {\r
258     osd_menu_t *p_osd = NULL;\r
259     osd_button_t *p_button = NULL;\r
260     vlc_value_t lockval;\r
261     \r
262     if( ( p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE ) ) == NULL )\r
263     {\r
264         msg_Err( p_this, "osd_MenuNext failed" );\r
265         return;\r
266     }\r
267     \r
268     var_Get( p_this->p_libvlc, "osd_mutex", &lockval );\r
269     vlc_mutex_lock( lockval.p_address );\r
270     \r
271 #if defined(OSD_MENU_DEBUG)\r
272     msg_Dbg( p_osd, "select" );\r
273 #endif\r
274     p_button = p_osd->p_state->p_visible;\r
275     /*\r
276      * Is there a menu item above or below? If so, then select it.\r
277      */\r
278     if( p_button && p_button->p_up)\r
279     {\r
280         vlc_object_release( (vlc_object_t*) p_osd );\r
281         vlc_mutex_unlock( lockval.p_address );\r
282         __osd_MenuUp( p_this );   /* "menu select" means go to menu item above. */\r
283         return;\r
284     }    \r
285     if( p_button && p_button->p_down)\r
286     {    \r
287         vlc_object_release( (vlc_object_t*) p_osd );\r
288         vlc_mutex_unlock( lockval.p_address );\r
289         __osd_MenuDown( p_this ); /* "menu select" means go to menu item below. */\r
290         return;\r
291     }\r
292 \r
293     if( p_button && !p_button->b_range )\r
294     {\r
295         p_button->p_current_state = osd_StateChange( p_button->p_states, OSD_BUTTON_PRESSED );\r
296         osd_UpdateState( p_osd->p_state,\r
297                 p_button->i_x, p_button->i_y,\r
298                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch,\r
299                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_lines,\r
300                 p_button->p_current_state->p_pic );\r
301         osd_SetMenuUpdate( p_osd, VLC_TRUE );\r
302         osd_SetMenuVisible( p_osd, VLC_TRUE );\r
303         osd_SetKeyPressed( VLC_OBJECT(p_osd->p_vlc), config_GetInt( p_osd, p_button->psz_action ) );\r
304 #if defined(OSD_MENU_DEBUG)\r
305         msg_Dbg( p_osd, "select (%d, %s)", config_GetInt( p_osd, p_button->psz_action ), p_button->psz_action );\r
306 #endif\r
307     }\r
308     vlc_object_release( (vlc_object_t*) p_osd );\r
309     vlc_mutex_unlock( lockval.p_address );            \r
310 }           \r
311 \r
312 void __osd_MenuNext( vlc_object_t *p_this )\r
313 {\r
314     osd_menu_t *p_osd = NULL;\r
315     osd_button_t *p_button = NULL;\r
316     vlc_value_t lockval;\r
317     \r
318     if( ( p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE ) ) == NULL )\r
319     {\r
320         msg_Err( p_this, "osd_MenuNext failed" );\r
321         return;\r
322     }\r
323             \r
324     var_Get( p_this->p_libvlc, "osd_mutex", &lockval );\r
325     vlc_mutex_lock( lockval.p_address );\r
326     \r
327     p_button = p_osd->p_state->p_visible;\r
328     if( p_button )\r
329     {\r
330         if( !p_button->b_range ) \r
331             p_button->p_current_state = osd_StateChange( p_button->p_states, OSD_BUTTON_UNSELECT );\r
332         if( p_button->p_next )\r
333             p_osd->p_state->p_visible = p_button->p_next;\r
334         else\r
335             p_osd->p_state->p_visible = p_osd->p_button;\r
336             \r
337         if( !p_osd->p_state->p_visible->b_range ) \r
338             p_osd->p_state->p_visible->p_current_state =\r
339                 osd_StateChange( p_osd->p_state->p_visible->p_states, OSD_BUTTON_SELECT );\r
340         \r
341         osd_UpdateState( p_osd->p_state, \r
342                 p_osd->p_state->p_visible->i_x, p_osd->p_state->p_visible->i_y,\r
343                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch,\r
344                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_lines,\r
345                 p_osd->p_state->p_visible->p_current_state->p_pic );\r
346         osd_SetMenuUpdate( p_osd, VLC_TRUE );\r
347     }\r
348 #if defined(OSD_MENU_DEBUG)\r
349     msg_Dbg( p_osd, "direction right [button %s]", p_osd->p_state->p_visible->psz_action );            \r
350 #endif\r
351     \r
352     vlc_object_release( (vlc_object_t*) p_osd );\r
353     vlc_mutex_unlock( lockval.p_address );\r
354 }\r
355 \r
356 void __osd_MenuPrev( vlc_object_t *p_this )\r
357 {\r
358     osd_menu_t *p_osd = NULL;\r
359     osd_button_t *p_button = NULL;\r
360     vlc_value_t lockval;\r
361     \r
362     if( ( p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE ) ) == NULL )\r
363     {\r
364         msg_Err( p_this, "osd_MenuPrev failed" );\r
365         return;\r
366     }\r
367 \r
368     var_Get( p_this->p_libvlc, "osd_mutex", &lockval );\r
369     vlc_mutex_lock( lockval.p_address );\r
370     \r
371     p_button = p_osd->p_state->p_visible;\r
372     if( p_button )\r
373     {                    \r
374         if( !p_button->b_range ) \r
375             p_button->p_current_state = osd_StateChange( p_button->p_states, OSD_BUTTON_UNSELECT );\r
376         if( p_button->p_prev )\r
377             p_osd->p_state->p_visible = p_button->p_prev;\r
378         else\r
379             p_osd->p_state->p_visible = p_osd->p_last_button;                \r
380         \r
381         if( !p_osd->p_state->p_visible->b_range ) \r
382             p_osd->p_state->p_visible->p_current_state =\r
383                 osd_StateChange( p_osd->p_state->p_visible->p_states, OSD_BUTTON_SELECT );\r
384         \r
385         osd_UpdateState( p_osd->p_state, \r
386                 p_osd->p_state->p_visible->i_x, p_osd->p_state->p_visible->i_y,\r
387                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch,\r
388                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_lines,\r
389                 p_osd->p_state->p_visible->p_current_state->p_pic );\r
390         osd_SetMenuUpdate( p_osd, VLC_TRUE );\r
391     }\r
392 #if defined(OSD_MENU_DEBUG)\r
393     msg_Dbg( p_osd, "direction left [button %s]", p_osd->p_state->p_visible->psz_action );            \r
394 #endif\r
395             \r
396     vlc_object_release( (vlc_object_t*) p_osd );\r
397     vlc_mutex_unlock( lockval.p_address );\r
398 }\r
399 \r
400 void __osd_MenuUp( vlc_object_t *p_this )\r
401 {\r
402     osd_menu_t *p_osd = NULL;\r
403     osd_button_t *p_button = NULL;\r
404     vlc_value_t lockval;\r
405 #if defined(OSD_MENU_DEBUG)    \r
406     vlc_value_t val;\r
407 #endif\r
408         \r
409     if( ( p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE ) ) == NULL )\r
410     {\r
411         msg_Err( p_this, "osd_MenuDown failed" );\r
412         return;\r
413     }\r
414             \r
415     var_Get( p_this->p_libvlc, "osd_mutex", &lockval );\r
416     vlc_mutex_lock( lockval.p_address );\r
417 \r
418     p_button = p_osd->p_state->p_visible;\r
419     if( p_button )\r
420     {\r
421         if( !p_button->b_range ) \r
422         {\r
423             p_button->p_current_state = osd_StateChange( p_button->p_states, OSD_BUTTON_SELECT );\r
424             if( p_button->p_up )\r
425                 p_osd->p_state->p_visible = p_button->p_up;                    \r
426         }\r
427         \r
428         if( p_button->b_range && p_osd->p_state->p_visible->b_range ) \r
429         {                    \r
430             osd_state_t *p_temp = p_osd->p_state->p_visible->p_current_state;\r
431             if( p_temp && p_temp->p_next )\r
432                 p_osd->p_state->p_visible->p_current_state = p_temp->p_next;\r
433         }\r
434         else if( !p_osd->p_state->p_visible->b_range )\r
435         {    \r
436             p_osd->p_state->p_visible->p_current_state =\r
437                 osd_StateChange( p_osd->p_state->p_visible->p_states, OSD_BUTTON_SELECT );\r
438         } \r
439         \r
440         osd_UpdateState( p_osd->p_state, \r
441                 p_osd->p_state->p_visible->i_x, p_osd->p_state->p_visible->i_y,\r
442                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch,\r
443                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_lines,\r
444                 p_osd->p_state->p_visible->p_current_state->p_pic );\r
445         osd_SetMenuUpdate( p_osd, VLC_TRUE );\r
446         /* If this is a range style action with associated images of only one state, \r
447             * then perform "menu select" on every menu navigation\r
448             */\r
449         if( p_button->b_range ) \r
450         {\r
451             osd_SetKeyPressed( VLC_OBJECT(p_osd->p_vlc), config_GetInt(p_osd, p_button->psz_action) );\r
452 #if defined(OSD_MENU_DEBUG)\r
453             msg_Dbg( p_osd, "select (%d, %s)", val.i_int, p_button->psz_action );\r
454 #endif\r
455         }\r
456     }\r
457 #if defined(OSD_MENU_DEBUG)\r
458     msg_Dbg( p_osd, "direction up [button %s]", p_osd->p_state->p_visible->psz_action );            \r
459 #endif            \r
460     \r
461     vlc_object_release( (vlc_object_t*) p_osd );\r
462     vlc_mutex_unlock( lockval.p_address );\r
463 }\r
464 \r
465 void __osd_MenuDown( vlc_object_t *p_this )\r
466 {\r
467     osd_menu_t *p_osd = NULL;\r
468     osd_button_t *p_button = NULL;\r
469     vlc_value_t lockval;\r
470 #if defined(OSD_MENU_DEBUG)    \r
471     vlc_value_t val;\r
472 #endif\r
473         \r
474     if( ( p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE ) ) == NULL )\r
475     {\r
476         msg_Err( p_this, "osd_MenuDown failed" );\r
477         return;\r
478     }\r
479     \r
480     var_Get( p_this->p_libvlc, "osd_mutex", &lockval );\r
481     vlc_mutex_lock( lockval.p_address );\r
482     \r
483     p_button = p_osd->p_state->p_visible;\r
484     if( p_button )\r
485     {\r
486         if( !p_button->b_range ) \r
487         {\r
488             p_button->p_current_state = osd_StateChange( p_button->p_states, OSD_BUTTON_SELECT );\r
489             if( p_button->p_down )\r
490                 p_osd->p_state->p_visible = p_button->p_down;\r
491         }\r
492         \r
493         if( p_button->b_range && p_osd->p_state->p_visible->b_range ) \r
494         {\r
495             osd_state_t *p_temp = p_osd->p_state->p_visible->p_current_state;\r
496             if( p_temp && p_temp->p_prev )\r
497                 p_osd->p_state->p_visible->p_current_state = p_temp->p_prev;\r
498         }\r
499         else if( !p_osd->p_state->p_visible->b_range )\r
500         {\r
501             p_osd->p_state->p_visible->p_current_state =\r
502                 osd_StateChange( p_osd->p_state->p_visible->p_states, OSD_BUTTON_SELECT );\r
503         }\r
504 \r
505         osd_UpdateState( p_osd->p_state, \r
506                 p_osd->p_state->p_visible->i_x, p_osd->p_state->p_visible->i_y,\r
507                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch,\r
508                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_lines,\r
509                 p_osd->p_state->p_visible->p_current_state->p_pic );\r
510         osd_SetMenuUpdate( p_osd, VLC_TRUE );\r
511         /* If this is a range style action with associated images of only one state, \r
512          * then perform "menu select" on every menu navigation\r
513          */\r
514         if( p_button->b_range ) \r
515         {\r
516             osd_SetKeyPressed( VLC_OBJECT(p_osd->p_vlc), config_GetInt(p_osd, p_button->psz_action_down) );\r
517 #if defined(OSD_MENU_DEBUG)\r
518             msg_Dbg( p_osd, "select (%d, %s)", val.i_int, p_button->psz_action_down );\r
519 #endif\r
520         }\r
521     }\r
522 #if defined(OSD_MENU_DEBUG)\r
523     msg_Dbg( p_osd, "direction down [button %s]", p_osd->p_state->p_visible->psz_action );            \r
524 #endif            \r
525 \r
526     vlc_object_release( (vlc_object_t*) p_osd );\r
527     vlc_mutex_unlock( lockval.p_address );\r
528 }\r
529 \r
530 static int osd_VolumeStep( vlc_object_t *p_this, int i_volume, int i_steps )\r
531 {\r
532     int i_volume_step = 0;\r
533 \r
534     i_volume_step = config_GetInt( p_this->p_vlc, "volume-step" );\r
535     return (i_volume/i_volume_step);\r
536 }\r
537 \r
538 /**\r
539  * Display current audio volume bitmap\r
540  *\r
541  * The OSD Menu audio volume bar is updated to reflect the new audio volume. Call this function\r
542  * when the audio volume is updated outside the OSD menu command "menu up", "menu down" or "menu select".\r
543  */\r
544 void __osd_Volume( vlc_object_t *p_this )\r
545 {\r
546     osd_menu_t *p_osd = NULL;\r
547     osd_button_t *p_button = NULL;\r
548     vlc_value_t lockval;\r
549     int i_volume = 0;\r
550     int i_steps = 0;\r
551 \r
552     if( ( p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE ) ) == NULL )\r
553     {\r
554         msg_Err( p_this, "OSD menu volume update failed" );\r
555         return;\r
556     }\r
557 \r
558     var_Get( p_this->p_libvlc, "osd_mutex", &lockval );\r
559     vlc_mutex_lock( lockval.p_address );\r
560 \r
561     p_button = p_osd->p_state->p_volume;\r
562     if( p_osd->p_state->p_volume ) \r
563         p_osd->p_state->p_visible = p_osd->p_state->p_volume;\r
564     if( p_button && p_button->b_range )\r
565     {\r
566         /* Update the volume state images to match the current volume */\r
567         i_volume = config_GetInt( p_this, "volume" );\r
568         i_steps = osd_VolumeStep( p_this, i_volume, p_button->i_ranges );\r
569         msg_Err( p_this, "OSD steps=%d", i_steps );\r
570         p_button->p_current_state = osd_VolumeStateChange( p_button->p_states, i_steps );\r
571 \r
572         osd_UpdateState( p_osd->p_state,\r
573                 p_button->i_x, p_button->i_y,\r
574                 p_button->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch,\r
575                 p_button->p_current_state->p_pic->p[Y_PLANE].i_visible_lines,\r
576                 p_button->p_current_state->p_pic );\r
577         osd_SetMenuUpdate( p_osd, VLC_TRUE );\r
578         osd_SetMenuVisible( p_osd, VLC_TRUE );\r
579     }\r
580     vlc_object_release( (vlc_object_t*) p_osd );\r
581     vlc_mutex_unlock( lockval.p_address );\r
582 }\r