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