]> git.sesse.net Git - vlc/blob - modules/misc/osd/osd_menu.c
1f6fb3ba9872047759a49044addd9eb803fac112
[vlc] / modules / misc / osd / osd_menu.c
1 /*****************************************************************************
2  * parser.c : OSD import module
3  *****************************************************************************
4  * Copyright (C) 2007 M2X
5  * $Id$
6  *
7  * Authors: Jean-Paul Saman
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <vlc/vlc.h>
33 #include <vlc_vout.h>
34 #include <vlc_config.h>
35
36 #include <vlc_keys.h>
37 #include <vlc_image.h>
38 #include <vlc_osd.h>
39 #include <vlc_charset.h>
40
41 #include "osd_menu.h"
42
43 #undef OSD_MENU_DEBUG
44
45 /*****************************************************************************
46  * Local prototypes
47  *****************************************************************************/
48
49 /*****************************************************************************
50  * Create a new Menu structure
51  *****************************************************************************/
52 osd_menu_t *osd_MenuNew( osd_menu_t *p_menu, const char *psz_path,
53                          int i_x, int i_y )
54 {
55     if( !p_menu ) return NULL;
56
57     p_menu->p_state = (osd_menu_state_t *) malloc( sizeof( osd_menu_state_t ) );
58     if( !p_menu->p_state )
59     {
60         msg_Err( p_menu, "Memory allocation for OSD Menu state failed" );
61         return NULL;
62     }
63
64     memset(p_menu->p_state, 0, sizeof(osd_menu_state_t));
65     if( psz_path != NULL )
66         p_menu->psz_path = strdup( psz_path );
67     else
68         p_menu->psz_path = NULL;
69
70     p_menu->i_x = i_x;
71     p_menu->i_y = i_y;
72     p_menu->i_style = OSD_MENU_STYLE_SIMPLE;
73
74     return p_menu;
75 }
76
77 /*****************************************************************************
78  * Free the menu
79  *****************************************************************************/
80 void osd_MenuFree( osd_menu_t *p_menu )
81 {
82     msg_Dbg( p_menu, "freeing menu" );
83     osd_ButtonFree( p_menu, p_menu->p_button );
84
85     if( p_menu->psz_path ) free( p_menu->psz_path );
86     if( p_menu->p_state ) free( p_menu->p_state );
87
88     p_menu->p_button = NULL;
89     p_menu->p_last_button = NULL;
90     p_menu->psz_path = NULL;
91     p_menu->p_state = NULL;
92 }
93
94 /*****************************************************************************
95  * Create a new button
96  *****************************************************************************/
97 osd_button_t *osd_ButtonNew( const char *psz_action, int i_x, int i_y )
98 {
99     osd_button_t *p_button = NULL;
100     p_button = (osd_button_t*) malloc( sizeof(osd_button_t) );
101     if( !p_button )
102         return NULL;
103
104     memset( p_button, 0, sizeof(osd_button_t) );
105     p_button->psz_action = strdup(psz_action);
106     p_button->psz_action_down = NULL;
107     p_button->p_feedback = NULL;
108     p_button->i_x = i_x;
109     p_button->i_y = i_y;
110
111     return p_button;
112 }
113
114 /*****************************************************************************
115  * Free a button
116  *****************************************************************************/
117 void osd_ButtonFree( osd_menu_t *p_menu, osd_button_t *p_button )
118 {
119     osd_button_t *p_current = p_button;
120     osd_button_t *p_next = NULL;
121     osd_button_t *p_prev = NULL;
122
123     /* First walk to the end. */
124     while( p_current->p_next )
125     {
126         p_next = p_current->p_next;
127         p_current = p_next;
128     }
129     /* Then free end first and walk to the start. */
130     while( p_current->p_prev )
131     {
132         msg_Dbg( p_menu, "+ freeing button %s [%p]",
133                  p_current->psz_action, p_current );
134         p_prev = p_current->p_prev;
135         p_current = p_prev;
136         if( p_current->p_next )
137         {
138             if( p_current->p_next->psz_name )
139                 free( p_current->p_next->psz_name );
140             if( p_current->p_next->psz_action )
141                 free( p_current->p_next->psz_action );
142             if( p_current->p_next->psz_action_down )
143                 free( p_current->p_next->psz_action_down );
144             if( p_current->p_feedback && p_current->p_feedback->p_data_orig )
145                 free( p_current->p_feedback->p_data_orig );
146             if( p_current->p_feedback )
147                 free( p_current->p_feedback );
148
149             p_current->p_feedback = NULL;
150
151             /* Free all states first */
152             if( p_current->p_next->p_states )
153                 osd_StatesFree( p_menu, p_current->p_next->p_states );
154
155             free( p_current->p_next );
156             p_current->p_next = NULL;
157         }
158
159         if( p_current->p_up )
160         {
161             if( p_current->p_up->psz_name )
162                 free( p_current->p_up->psz_name );
163             if( p_current->p_up->psz_action )
164                 free( p_current->p_up->psz_action );
165             if( p_current->p_up->psz_action_down )
166                 free( p_current->p_up->psz_action_down );
167             if( p_current->p_feedback && p_current->p_feedback->p_data_orig )
168                 free( p_current->p_feedback->p_data_orig );
169             if( p_current->p_feedback )
170                 free( p_current->p_feedback );
171
172             p_current->p_feedback = NULL;
173
174             /* Free all states first */
175             if( p_current->p_up->p_states )
176                 osd_StatesFree( p_menu, p_current->p_up->p_states );
177             free( p_current->p_up );
178             p_current->p_up = NULL;
179         }
180     }
181     /* Free the last one. */
182     if( p_button )
183     {
184         msg_Dbg( p_menu, "+ freeing button %s [%p]",
185                  p_button->psz_action, p_button );
186         if( p_button->psz_name ) free( p_button->psz_name );
187         if( p_button->psz_action ) free( p_button->psz_action );
188         if( p_button->psz_action_down ) free( p_button->psz_action_down );
189         if( p_current->p_feedback && p_current->p_feedback->p_data_orig )
190             free( p_current->p_feedback->p_data_orig );
191         if( p_current->p_feedback )
192             free( p_current->p_feedback );
193         p_current->p_feedback = NULL;
194
195         if( p_button->p_states )
196             osd_StatesFree( p_menu, p_button->p_states );
197
198         free( p_button );
199         p_button = NULL;
200     }
201 }
202
203 /*****************************************************************************
204  * Create a new state image
205  *****************************************************************************/
206 osd_state_t *osd_StateNew( osd_menu_t *p_menu, const char *psz_file,
207                            const char *psz_state )
208 {
209     osd_state_t *p_state = NULL;
210     video_format_t fmt_in, fmt_out;
211
212     p_state = (osd_state_t*) malloc( sizeof(osd_state_t) );
213     if( !p_state )
214         return NULL;
215
216     memset( p_state, 0, sizeof(osd_state_t) );
217     memset( &fmt_in, 0, sizeof(video_format_t) );
218     memset( &fmt_out, 0, sizeof(video_format_t) );
219
220     fmt_out.i_chroma = VLC_FOURCC('Y','U','V','A');
221     if( p_menu->p_image )
222     {
223         p_state->p_pic = image_ReadUrl( p_menu->p_image, psz_file,
224                                         &fmt_in, &fmt_out );
225
226         p_state->i_width  = p_state->p_pic->p[Y_PLANE].i_visible_pitch;
227         p_state->i_height = p_state->p_pic->p[Y_PLANE].i_visible_lines;
228     }
229
230     if( psz_state )
231     {
232         p_state->psz_state = strdup( psz_state );
233         if( strncmp( ppsz_button_states[0], psz_state,
234                      strlen(ppsz_button_states[0]) ) == 0 )
235             p_state->i_state = OSD_BUTTON_UNSELECT;
236         else if( strncmp( ppsz_button_states[1], psz_state,
237                           strlen(ppsz_button_states[1]) ) == 0 )
238             p_state->i_state = OSD_BUTTON_SELECT;
239         else if( strncmp( ppsz_button_states[2], psz_state,
240                           strlen(ppsz_button_states[2]) ) == 0 )
241             p_state->i_state = OSD_BUTTON_PRESSED;
242     }
243     return p_state;
244 }
245
246 /*****************************************************************************
247  * Free state images
248  *****************************************************************************/
249 void osd_StatesFree( osd_menu_t *p_menu, osd_state_t *p_states )
250 {
251     osd_state_t *p_state = p_states;
252     osd_state_t *p_next = NULL;
253     osd_state_t *p_prev = NULL;
254
255     while( p_state->p_next )
256     {
257         p_next = p_state->p_next;
258         p_state = p_next;
259     }
260     /* Then free end first and walk to the start. */
261     while( p_state->p_prev )
262     {
263         msg_Dbg( p_menu, " |- freeing state %s [%p]",
264                  p_state->psz_state, p_state );
265         p_prev = p_state->p_prev;
266         p_state = p_prev;
267         if( p_state->p_next )
268         {
269             if( p_state->p_next->p_pic )
270             {
271                 if( p_state->p_next->p_pic->p_data_orig )
272                     free( p_state->p_next->p_pic->p_data_orig );
273                 free( p_state->p_next->p_pic );
274             }
275             if( p_state->p_next->psz_state )
276                 free( p_state->p_next->psz_state );
277             free( p_state->p_next );
278             p_state->p_next = NULL;
279         }
280     }
281     /* Free the last one. */
282     if( p_states )
283     {
284         msg_Dbg( p_menu, " |- freeing state %s [%p]",
285                  p_state->psz_state, p_states );
286         if( p_states->p_pic )
287         {
288             if( p_states->p_pic->p_data_orig )
289                 free( p_states->p_pic->p_data_orig );
290             free( p_states->p_pic );
291         }
292         if( p_state->psz_state ) free( p_state->psz_state );
293         free( p_states );
294         p_states = NULL;
295     }
296 }