]> git.sesse.net Git - vlc/blob - src/osd/osd.c
Forward port of branches/0.8.1-jpsaman-thedj revision 12070. The OSD menu subsystem...
[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 \r
43 osd_menu_t *__osd_MenuCreate( vlc_object_t *p_this, const char *psz_file )\r
44 {\r
45     osd_menu_t  *p_osd = NULL;\r
46     vlc_value_t lockval;\r
47     int         i_volume = 0;\r
48     int         i_steps = 0;\r
49 \r
50     /* to be sure to avoid multiple creation */\r
51     var_Create( p_this->p_libvlc, "osd_mutex", VLC_VAR_MUTEX );\r
52     var_Get( p_this->p_libvlc, "osd_mutex", &lockval );\r
53     vlc_mutex_lock( lockval.p_address );\r
54     \r
55     if( ( p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE ) ) == NULL )\r
56     {\r
57         vlc_value_t val;\r
58         \r
59         msg_Dbg( p_this, "creating osd menu object" );\r
60         if( ( p_osd = vlc_object_create( p_this, VLC_OBJECT_OSDMENU ) ) == NULL )\r
61         {\r
62             msg_Err( p_this, "out of memory" );\r
63             vlc_mutex_unlock( lockval.p_address );\r
64             return NULL;\r
65         }\r
66 \r
67         /* Parse configuration file */\r
68         if( osd_ConfigLoader( p_this, psz_file, &p_osd ) )\r
69             goto error;\r
70         \r
71         /* Setup default button (first button) */\r
72         p_osd->p_state->p_visible = p_osd->p_button;\r
73         p_osd->p_state->p_visible->p_current_state =\r
74             osd_StateChange( p_osd->p_state->p_visible->p_states, OSD_BUTTON_SELECT );\r
75         p_osd->i_width  = p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch;\r
76         p_osd->i_height = p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_lines;\r
77 \r
78         /* Update the volume state images to match the current volume */\r
79         i_volume = config_GetInt( p_this, "volume" );\r
80         i_steps = (i_volume / AOUT_VOLUME_STEP / 3); /* 3 is a magic number for 32 volume decrease steps */\r
81         p_osd->p_state->p_volume->p_current_state = osd_VolumeStateChange( p_osd->p_state->p_volume->p_states, i_steps );\r
82 \r
83         /* Initialize OSD state */\r
84         osd_UpdateState( p_osd->p_state, p_osd->i_x, p_osd->i_y,\r
85                          p_osd->i_width, p_osd->i_height, NULL );\r
86         \r
87         vlc_object_yield( p_osd );\r
88         vlc_object_attach( p_osd, p_this->p_vlc );\r
89         \r
90         /* Signal when an update of OSD menu is needed */\r
91         var_Create( p_osd, "osd-menu-update", VLC_VAR_BOOL );\r
92         var_Create( p_osd, "osd-menu-visible", VLC_VAR_BOOL );\r
93 \r
94         val.b_bool = VLC_FALSE;\r
95         var_Set( p_osd, "osd-menu-update", val );\r
96         var_Set( p_osd, "osd-menu-visible", val );        \r
97     }\r
98     vlc_mutex_unlock( lockval.p_address );\r
99     return p_osd;\r
100     \r
101 error:\r
102     msg_Err( p_this, "creating osd menu object failed" );\r
103     vlc_mutex_unlock( lockval.p_address );\r
104     vlc_object_destroy( p_osd );\r
105     return NULL;    \r
106 }\r
107 \r
108 void __osd_MenuDelete( vlc_object_t *p_this, osd_menu_t *p_osd )\r
109 {\r
110     vlc_value_t lockval;\r
111 \r
112     if( !p_osd || !p_this ) return;\r
113     \r
114     var_Get( p_this->p_libvlc, "osd_mutex", &lockval );\r
115     vlc_mutex_lock( lockval.p_address );\r
116 \r
117     vlc_object_release( p_osd );    \r
118     if( p_osd->i_refcount > 0 )\r
119     {\r
120         vlc_mutex_unlock( lockval.p_address );        \r
121         return;\r
122     }    \r
123 \r
124     var_Destroy( p_osd, "osd-menu-visible" );\r
125     var_Destroy( p_osd, "osd-menu-update" );\r
126     \r
127     osd_ConfigUnload( p_this, &p_osd );\r
128     vlc_object_detach( p_osd );\r
129     vlc_object_destroy( p_osd );\r
130     p_osd = NULL;\r
131     \r
132     vlc_mutex_unlock( lockval.p_address );        \r
133 }\r
134 \r
135 osd_state_t *__osd_StateChange( osd_state_t *p_states, const int i_state )\r
136 {\r
137     osd_state_t *p_current = p_states;\r
138     osd_state_t *p_temp = NULL;\r
139     int i = 0;\r
140 \r
141     for( i=0; p_current != NULL; i++ )\r
142     {\r
143         if( p_current->i_state == i_state )\r
144             return p_current;\r
145         p_temp = p_current->p_next;\r
146         p_current = p_temp;\r
147     }\r
148     return p_states;\r
149 }\r
150 \r
151 /* The volume can be modified in another interface while the OSD Menu \r
152  * has not been instantiated yet. This routines updates the "volume OSD menu item"\r
153  * to reflect the current state of the GUI.\r
154  */\r
155 static inline osd_state_t *osd_VolumeStateChange( osd_state_t *p_current, int i_steps )\r
156 {\r
157     osd_state_t *p_temp = NULL;\r
158     int i;\r
159     \r
160     for( i=0; (i < i_steps) && (p_current != NULL); i++ )\r
161     {    \r
162         p_temp = p_current->p_next;\r
163         if( !p_temp ) return p_current;\r
164         p_current = p_temp;\r
165     }\r
166     return (!p_temp) ? p_current : p_temp;\r
167 }\r
168 \r
169 /* Update the state of the OSD Menu */\r
170 static void osd_UpdateState( osd_menu_state_t *p_state, int i_x, int i_y,\r
171         int i_width, int i_height, picture_t *p_pic )\r
172 {\r
173     p_state->i_x = i_x;\r
174     p_state->i_y = i_y;\r
175     p_state->i_width = i_width;\r
176     p_state->i_height = i_height;\r
177     p_state->p_pic = p_pic;\r
178 }\r
179 \r
180 void __osd_MenuShow( vlc_object_t *p_this )\r
181 {\r
182     osd_menu_t *p_osd = NULL;\r
183     osd_button_t *p_button = NULL;\r
184     vlc_value_t lockval;\r
185     \r
186     if( ( p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE ) ) == NULL )\r
187     {\r
188         msg_Err( p_this, "osd_MenuNext failed" );\r
189         return;\r
190     }        \r
191 \r
192     var_Get( p_this->p_libvlc, "osd_mutex", &lockval );\r
193     vlc_mutex_lock( lockval.p_address );\r
194 \r
195 #if defined(OSD_MENU_DEBUG)\r
196     msg_Dbg( p_osd, "menu on" );\r
197 #endif            \r
198     p_button = p_osd->p_state->p_visible;\r
199     if( p_button )\r
200     {                    \r
201         if( !p_button->b_range ) \r
202             p_button->p_current_state = osd_StateChange( p_button->p_states, OSD_BUTTON_UNSELECT );\r
203         p_osd->p_state->p_visible = p_osd->p_button;\r
204         \r
205         if( !p_osd->p_state->p_visible->b_range ) \r
206             p_osd->p_state->p_visible->p_current_state =\r
207                 osd_StateChange( p_osd->p_state->p_visible->p_states, OSD_BUTTON_SELECT );\r
208         \r
209         osd_UpdateState( p_osd->p_state,\r
210                 p_osd->p_state->p_visible->i_x, p_osd->p_state->p_visible->i_y,\r
211                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch,\r
212                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_lines,\r
213                 p_osd->p_state->p_visible->p_current_state->p_pic );                \r
214         osd_SetMenuUpdate( p_osd, VLC_TRUE );\r
215     }\r
216     osd_SetMenuVisible( p_osd, VLC_TRUE );\r
217     \r
218     vlc_object_release( (vlc_object_t*) p_osd );\r
219     vlc_mutex_unlock( lockval.p_address );\r
220 }\r
221             \r
222 void __osd_MenuHide( vlc_object_t *p_this )\r
223 {\r
224     osd_menu_t *p_osd = NULL;\r
225     vlc_value_t lockval;\r
226     \r
227     if( ( p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE ) ) == NULL )\r
228     {\r
229         msg_Err( p_this, "osd_MenuNext failed" );\r
230         return;\r
231     }\r
232         \r
233     var_Get( p_this->p_libvlc, "osd_mutex", &lockval );\r
234     vlc_mutex_lock( lockval.p_address );\r
235 \r
236 #if defined(OSD_MENU_DEBUG)\r
237     msg_Dbg( p_osd, "menu off" );\r
238 #endif\r
239     osd_UpdateState( p_osd->p_state,\r
240                 p_osd->p_state->i_x, p_osd->p_state->i_y,\r
241                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch,\r
242                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_lines,\r
243                 NULL );\r
244     osd_SetMenuUpdate( p_osd, VLC_TRUE );\r
245 \r
246     vlc_object_release( (vlc_object_t*) p_osd );\r
247     vlc_mutex_unlock( lockval.p_address );\r
248 }\r
249 \r
250 void __osd_MenuActivate( vlc_object_t *p_this )\r
251 {\r
252     osd_menu_t *p_osd = NULL;\r
253     osd_button_t *p_button = NULL;\r
254     vlc_value_t lockval;\r
255     \r
256     if( ( p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE ) ) == NULL )\r
257     {\r
258         msg_Err( p_this, "osd_MenuNext failed" );\r
259         return;\r
260     }\r
261     \r
262     var_Get( p_this->p_libvlc, "osd_mutex", &lockval );\r
263     vlc_mutex_lock( lockval.p_address );\r
264     \r
265 #if defined(OSD_MENU_DEBUG)\r
266     msg_Dbg( p_osd, "select" );\r
267 #endif\r
268     p_button = p_osd->p_state->p_visible;\r
269     /*\r
270      * Is there a menu item above or below? If so, then select it.\r
271      */\r
272     if( p_button && p_button->p_up)\r
273     {\r
274         vlc_object_release( (vlc_object_t*) p_osd );\r
275         vlc_mutex_unlock( lockval.p_address );\r
276         __osd_MenuUp( p_this );   /* "menu select" means go to menu item above. */\r
277         return;\r
278     }    \r
279     if( p_button && p_button->p_down)\r
280     {    \r
281         vlc_object_release( (vlc_object_t*) p_osd );\r
282         vlc_mutex_unlock( lockval.p_address );\r
283         __osd_MenuDown( p_this ); /* "menu select" means go to menu item below. */\r
284         return;\r
285     }\r
286 \r
287     if( p_button && !p_button->b_range )\r
288     {\r
289         p_button->p_current_state = osd_StateChange( p_button->p_states, OSD_BUTTON_PRESSED );\r
290         osd_UpdateState( p_osd->p_state,\r
291                 p_button->i_x, p_button->i_y,\r
292                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch,\r
293                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_lines,\r
294                 p_button->p_current_state->p_pic );\r
295         osd_SetMenuUpdate( p_osd, VLC_TRUE );\r
296         osd_SetMenuVisible( p_osd, VLC_TRUE );\r
297         osd_SetKeyPressed( VLC_OBJECT(p_osd->p_vlc), config_GetInt( p_osd, p_button->psz_action ) );\r
298 #if defined(OSD_MENU_DEBUG)\r
299         msg_Dbg( p_osd, "select (%d, %s)", config_GetInt( p_osd, p_button->psz_action ), p_button->psz_action );\r
300 #endif\r
301     }\r
302     vlc_object_release( (vlc_object_t*) p_osd );\r
303     vlc_mutex_unlock( lockval.p_address );            \r
304 }           \r
305 \r
306 void __osd_MenuNext( vlc_object_t *p_this )\r
307 {\r
308     osd_menu_t *p_osd = NULL;\r
309     osd_button_t *p_button = NULL;\r
310     vlc_value_t lockval;\r
311     \r
312     if( ( p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE ) ) == NULL )\r
313     {\r
314         msg_Err( p_this, "osd_MenuNext failed" );\r
315         return;\r
316     }\r
317             \r
318     var_Get( p_this->p_libvlc, "osd_mutex", &lockval );\r
319     vlc_mutex_lock( lockval.p_address );\r
320     \r
321     p_button = p_osd->p_state->p_visible;\r
322     if( p_button )\r
323     {\r
324         if( !p_button->b_range ) \r
325             p_button->p_current_state = osd_StateChange( p_button->p_states, OSD_BUTTON_UNSELECT );\r
326         if( p_button->p_next )\r
327             p_osd->p_state->p_visible = p_button->p_next;\r
328         else\r
329             p_osd->p_state->p_visible = p_osd->p_button;\r
330             \r
331         if( !p_osd->p_state->p_visible->b_range ) \r
332             p_osd->p_state->p_visible->p_current_state =\r
333                 osd_StateChange( p_osd->p_state->p_visible->p_states, OSD_BUTTON_SELECT );\r
334         \r
335         osd_UpdateState( p_osd->p_state, \r
336                 p_osd->p_state->p_visible->i_x, p_osd->p_state->p_visible->i_y,\r
337                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch,\r
338                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_lines,\r
339                 p_osd->p_state->p_visible->p_current_state->p_pic );\r
340         osd_SetMenuUpdate( p_osd, VLC_TRUE );\r
341     }\r
342 #if defined(OSD_MENU_DEBUG)\r
343     msg_Dbg( p_osd, "direction right [button %s]", p_osd->p_state->p_visible->psz_action );            \r
344 #endif\r
345     \r
346     vlc_object_release( (vlc_object_t*) p_osd );\r
347     vlc_mutex_unlock( lockval.p_address );\r
348 }\r
349 \r
350 void __osd_MenuPrev( vlc_object_t *p_this )\r
351 {\r
352     osd_menu_t *p_osd = NULL;\r
353     osd_button_t *p_button = NULL;\r
354     vlc_value_t lockval;\r
355     \r
356     if( ( p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE ) ) == NULL )\r
357     {\r
358         msg_Err( p_this, "osd_MenuPrev failed" );\r
359         return;\r
360     }\r
361 \r
362     var_Get( p_this->p_libvlc, "osd_mutex", &lockval );\r
363     vlc_mutex_lock( lockval.p_address );\r
364     \r
365     p_button = p_osd->p_state->p_visible;\r
366     if( p_button )\r
367     {                    \r
368         if( !p_button->b_range ) \r
369             p_button->p_current_state = osd_StateChange( p_button->p_states, OSD_BUTTON_UNSELECT );\r
370         if( p_button->p_prev )\r
371             p_osd->p_state->p_visible = p_button->p_prev;\r
372         else\r
373             p_osd->p_state->p_visible = p_osd->p_last_button;                \r
374         \r
375         if( !p_osd->p_state->p_visible->b_range ) \r
376             p_osd->p_state->p_visible->p_current_state =\r
377                 osd_StateChange( p_osd->p_state->p_visible->p_states, OSD_BUTTON_SELECT );\r
378         \r
379         osd_UpdateState( p_osd->p_state, \r
380                 p_osd->p_state->p_visible->i_x, p_osd->p_state->p_visible->i_y,\r
381                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch,\r
382                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_lines,\r
383                 p_osd->p_state->p_visible->p_current_state->p_pic );\r
384         osd_SetMenuUpdate( p_osd, VLC_TRUE );\r
385     }\r
386 #if defined(OSD_MENU_DEBUG)\r
387     msg_Dbg( p_osd, "direction left [button %s]", p_osd->p_state->p_visible->psz_action );            \r
388 #endif\r
389             \r
390     vlc_object_release( (vlc_object_t*) p_osd );\r
391     vlc_mutex_unlock( lockval.p_address );\r
392 }\r
393 \r
394 void __osd_MenuUp( vlc_object_t *p_this )\r
395 {\r
396     osd_menu_t *p_osd = NULL;\r
397     osd_button_t *p_button = NULL;\r
398     vlc_value_t lockval;\r
399 #if defined(OSD_MENU_DEBUG)    \r
400     vlc_value_t val;\r
401 #endif\r
402         \r
403     if( ( p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE ) ) == NULL )\r
404     {\r
405         msg_Err( p_this, "osd_MenuDown failed" );\r
406         return;\r
407     }\r
408             \r
409     var_Get( p_this->p_libvlc, "osd_mutex", &lockval );\r
410     vlc_mutex_lock( lockval.p_address );\r
411 \r
412     p_button = p_osd->p_state->p_visible;\r
413     if( p_button )\r
414     {\r
415         if( !p_button->b_range ) \r
416         {\r
417             p_button->p_current_state = osd_StateChange( p_button->p_states, OSD_BUTTON_SELECT );\r
418             if( p_button->p_up )\r
419                 p_osd->p_state->p_visible = p_button->p_up;                    \r
420         }\r
421         \r
422         if( p_button->b_range && p_osd->p_state->p_visible->b_range ) \r
423         {                    \r
424             osd_state_t *p_temp = p_osd->p_state->p_visible->p_current_state;\r
425             if( p_temp && p_temp->p_next )\r
426                 p_osd->p_state->p_visible->p_current_state = p_temp->p_next;\r
427         }\r
428         else if( !p_osd->p_state->p_visible->b_range )\r
429         {    \r
430             p_osd->p_state->p_visible->p_current_state =\r
431                 osd_StateChange( p_osd->p_state->p_visible->p_states, OSD_BUTTON_SELECT );\r
432         } \r
433         \r
434         osd_UpdateState( p_osd->p_state, \r
435                 p_osd->p_state->p_visible->i_x, p_osd->p_state->p_visible->i_y,\r
436                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch,\r
437                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_lines,\r
438                 p_osd->p_state->p_visible->p_current_state->p_pic );\r
439         osd_SetMenuUpdate( p_osd, VLC_TRUE );\r
440         /* If this is a range style action with associated images of only one state, \r
441             * then perform "menu select" on every menu navigation\r
442             */\r
443         if( p_button->b_range ) \r
444         {\r
445             osd_SetKeyPressed( VLC_OBJECT(p_osd->p_vlc), config_GetInt(p_osd, p_button->psz_action) );\r
446 #if defined(OSD_MENU_DEBUG)\r
447             msg_Dbg( p_osd, "select (%d, %s)", val.i_int, p_button->psz_action );\r
448 #endif\r
449         }\r
450     }\r
451 #if defined(OSD_MENU_DEBUG)\r
452     msg_Dbg( p_osd, "direction up [button %s]", p_osd->p_state->p_visible->psz_action );            \r
453 #endif            \r
454     \r
455     vlc_object_release( (vlc_object_t*) p_osd );\r
456     vlc_mutex_unlock( lockval.p_address );\r
457 }\r
458 \r
459 void __osd_MenuDown( vlc_object_t *p_this )\r
460 {\r
461     osd_menu_t *p_osd = NULL;\r
462     osd_button_t *p_button = NULL;\r
463     vlc_value_t lockval;\r
464 #if defined(OSD_MENU_DEBUG)    \r
465     vlc_value_t val;\r
466 #endif\r
467         \r
468     if( ( p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE ) ) == NULL )\r
469     {\r
470         msg_Err( p_this, "osd_MenuDown failed" );\r
471         return;\r
472     }\r
473     \r
474     var_Get( p_this->p_libvlc, "osd_mutex", &lockval );\r
475     vlc_mutex_lock( lockval.p_address );\r
476     \r
477     p_button = p_osd->p_state->p_visible;\r
478     if( p_button )\r
479     {\r
480         if( !p_button->b_range ) \r
481         {\r
482             p_button->p_current_state = osd_StateChange( p_button->p_states, OSD_BUTTON_SELECT );\r
483             if( p_button->p_down )\r
484                 p_osd->p_state->p_visible = p_button->p_down;\r
485         }\r
486         \r
487         if( p_button->b_range && p_osd->p_state->p_visible->b_range ) \r
488         {\r
489             osd_state_t *p_temp = p_osd->p_state->p_visible->p_current_state;\r
490             if( p_temp && p_temp->p_prev )\r
491                 p_osd->p_state->p_visible->p_current_state = p_temp->p_prev;\r
492         }\r
493         else if( !p_osd->p_state->p_visible->b_range )\r
494         {\r
495             p_osd->p_state->p_visible->p_current_state =\r
496                 osd_StateChange( p_osd->p_state->p_visible->p_states, OSD_BUTTON_SELECT );\r
497         }\r
498 \r
499         osd_UpdateState( p_osd->p_state, \r
500                 p_osd->p_state->p_visible->i_x, p_osd->p_state->p_visible->i_y,\r
501                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch,\r
502                 p_osd->p_state->p_visible->p_current_state->p_pic->p[Y_PLANE].i_visible_lines,\r
503                 p_osd->p_state->p_visible->p_current_state->p_pic );\r
504         osd_SetMenuUpdate( p_osd, VLC_TRUE );\r
505         /* If this is a range style action with associated images of only one state, \r
506          * then perform "menu select" on every menu navigation\r
507          */\r
508         if( p_button->b_range ) \r
509         {\r
510             osd_SetKeyPressed( VLC_OBJECT(p_osd->p_vlc), config_GetInt(p_osd, p_button->psz_action_down) );\r
511 #if defined(OSD_MENU_DEBUG)\r
512             msg_Dbg( p_osd, "select (%d, %s)", val.i_int, p_button->psz_action_down );\r
513 #endif\r
514         }\r
515     }\r
516 #if defined(OSD_MENU_DEBUG)\r
517     msg_Dbg( p_osd, "direction down [button %s]", p_osd->p_state->p_visible->psz_action );            \r
518 #endif            \r
519 \r
520     vlc_object_release( (vlc_object_t*) p_osd );\r
521     vlc_mutex_unlock( lockval.p_address );\r
522 }\r
523 \r
524 /**\r
525  * Audio volume up\r
526  *\r
527  * The OSD Menu audio volume bar is updated to reflect the new audio volume. Call this function\r
528  * when the audio volume is updated outside the OSD menu command "menu up".\r
529  */\r
530 void __osd_VolumeUp( vlc_object_t *p_this )\r
531 {\r
532     osd_menu_t *p_osd = NULL;\r
533     osd_button_t *p_button = NULL;\r
534     vlc_value_t lockval;\r
535     int i_volume = 0;\r
536     int i_steps = 0;\r
537     \r
538     if( ( p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE ) ) == NULL )\r
539     {\r
540         msg_Err( p_this, "osd_VolumeUp failed" );\r
541         return;\r
542     }\r
543     \r
544     var_Get( p_this->p_libvlc, "osd_mutex", &lockval );\r
545     vlc_mutex_lock( lockval.p_address );\r
546 \r
547     /* Update the volume state images to match the current volume */\r
548     i_volume = config_GetInt( p_this, "volume" );\r
549     i_steps = (i_volume / AOUT_VOLUME_STEP / 3); /* 3 is a magic number for 32 volume decrease steps */\r
550     p_osd->p_state->p_volume->p_current_state = osd_VolumeStateChange( p_osd->p_state->p_volume->p_states, i_steps );\r
551     \r
552     p_button = p_osd->p_state->p_volume;\r
553     if( p_osd->p_state->p_volume ) \r
554         p_osd->p_state->p_visible = p_osd->p_state->p_volume;\r
555     if( p_button && p_button->b_range )\r
556     {\r
557         osd_state_t *p_temp = p_button->p_current_state;\r
558         if( p_temp->p_next )\r
559             p_button->p_current_state = p_temp->p_next;\r
560         \r
561         osd_UpdateState( p_osd->p_state, \r
562                 p_button->i_x, p_button->i_y,\r
563                 p_button->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch,\r
564                 p_button->p_current_state->p_pic->p[Y_PLANE].i_visible_lines,\r
565                 p_button->p_current_state->p_pic );\r
566         osd_SetMenuUpdate( p_osd, VLC_TRUE );\r
567         osd_SetMenuVisible( p_osd, VLC_TRUE );\r
568     }\r
569     vlc_object_release( (vlc_object_t*) p_osd );\r
570     vlc_mutex_unlock( lockval.p_address );\r
571 }\r
572 \r
573 /**\r
574  * Audio volume down\r
575  *\r
576  * The OSD Menu audio volume bar is updated to reflect the new audio volume. Call this function\r
577  * when the audio volume is updated outside the OSD menu command "menu down".\r
578  */\r
579 void __osd_VolumeDown( vlc_object_t *p_this )\r
580 {\r
581     osd_menu_t *p_osd = NULL;\r
582     osd_button_t *p_button = NULL;\r
583     vlc_value_t lockval;\r
584     int i_volume = 0;\r
585     int i_steps = 0;\r
586         \r
587     if( ( p_osd = vlc_object_find( p_this, VLC_OBJECT_OSDMENU, FIND_ANYWHERE ) ) == NULL )\r
588     {\r
589         msg_Err( p_this, "osd_VolumeDown failed" );\r
590         return;\r
591     }\r
592     \r
593     var_Get( p_this->p_libvlc, "osd_mutex", &lockval );\r
594     vlc_mutex_lock( lockval.p_address );\r
595 \r
596     /* Update the volume state images to match the current volume */\r
597     i_volume = config_GetInt( p_this, "volume" );\r
598     i_steps = (i_volume / AOUT_VOLUME_STEP / 3); /* 3 is a magic number for 32 volume decrease steps */\r
599     p_osd->p_state->p_volume->p_current_state = osd_VolumeStateChange( p_osd->p_state->p_volume->p_states, i_steps );\r
600 \r
601     p_button = p_osd->p_state->p_volume;\r
602     if( p_osd->p_state->p_volume ) \r
603         p_osd->p_state->p_visible = p_osd->p_state->p_volume;            \r
604     if( p_button && p_button->b_range )\r
605     {\r
606         osd_state_t *p_temp = p_button->p_current_state;\r
607         if( p_temp && p_temp->p_prev )\r
608             p_button->p_current_state = p_temp->p_prev;\r
609 \r
610         osd_UpdateState( p_osd->p_state, \r
611                 p_button->i_x, p_button->i_y,\r
612                 p_button->p_current_state->p_pic->p[Y_PLANE].i_visible_pitch,\r
613                 p_button->p_current_state->p_pic->p[Y_PLANE].i_visible_lines,\r
614                 p_button->p_current_state->p_pic );\r
615         osd_SetMenuUpdate( p_osd, VLC_TRUE );\r
616         osd_SetMenuVisible( p_osd, VLC_TRUE );\r
617     }\r
618     vlc_object_release( (vlc_object_t*) p_osd );\r
619     vlc_mutex_unlock( lockval.p_address );\r
620 }\r