1 /*****************************************************************************
2 * simple.c - The OSD Menu simple parser code.
3 *****************************************************************************
4 * Copyright (C) 2005-2008 M2X
7 * Authors: Jean-Paul Saman
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>
40 int osd_parser_simpleOpen( vlc_object_t *p_this );
42 /*****************************************************************************
43 * Simple parser open function
44 *****************************************************************************/
45 int osd_parser_simpleOpen( vlc_object_t *p_this )
47 osd_menu_t *p_menu = (osd_menu_t *) p_this;
48 osd_button_t *p_current = NULL; /* button currently processed */
49 osd_button_t *p_prev = NULL; /* previous processed button */
54 if( !p_menu ) return VLC_ENOOBJ;
56 msg_Dbg( p_this, "opening osdmenu definition file %s", p_menu->psz_file );
57 fd = vlc_fopen( p_menu->psz_file, "r" );
60 msg_Err( p_this, "failed to open osdmenu definition file %s",
70 char path[PATH_MAX] = "";
71 char *psz_path = NULL;
75 result = fscanf(fd, "%24s %255s", action, path );
77 /* override images path ? */
78 psz_path = var_InheritString( p_this, "osdmenu-file-path" );
81 /* psz_path is not null and therefor path cannot be NULL
82 * it might be null terminated.
84 strncpy( path, psz_path, PATH_MAX );
88 /* NULL terminate before asking the length of path[] */
89 path[PATH_MAX-1] = '\0';
91 /* Protect against buffer overflow:
92 * max index is PATH_MAX-1 and we increment by 1 after
93 * so PATH_MAX-2 is the bigest we can have */
94 if( i_len > PATH_MAX - 2 )
96 #if defined(WIN32) || defined(UNDER_CE) || defined(__OS2__)
97 if( (i_len > 0) && path[i_len] != '\\' )
100 if( (i_len > 0) && path[i_len] != '/' )
103 path[i_len+1] = '\0';
104 if( result == 0 || result == EOF )
106 msg_Dbg( p_this, "osdmenu dir %s", path );
109 p_menu = osd_MenuNew( p_menu, NULL, 0, 0 );
111 p_menu = osd_MenuNew( p_menu, path, 0, 0 );
113 /* Peek for 'style' argument */
118 result = fscanf(fd, "%24s %24s", cmd, action );
119 if( result == 0 || result == EOF )
122 msg_Dbg( p_this, "osdmenu %s %s", cmd, action );
123 if( strncmp( cmd, "style", 5 ) == 0 )
125 if( strncmp( action, "default", 7) == 0 )
127 p_menu->i_style = OSD_MENU_STYLE_SIMPLE;
129 else if( strncmp( action, "concat", 6) == 0 )
131 p_menu->i_style = OSD_MENU_STYLE_CONCAT;
136 result = fseek( fd, pos, SEEK_SET );
145 /* read successive lines */
148 osd_state_t *p_state_current = NULL; /* button state currently processed */
149 osd_state_t *p_state_prev = NULL; /* previous state processed button */
152 char action[25] = "";
155 char path[PATH_MAX] = "";
159 result = fscanf( fd, "%24s %24s (%d,%d)", cmd, action, &i_x, &i_y );
162 if( strncmp( &cmd[0], "action", 6 ) != 0 )
164 msg_Dbg( p_this, " + %s hotkey=%s (%d,%d)", cmd, action, i_x, i_y );
167 p_current = osd_ButtonNew( action, i_x, i_y );
172 p_prev->p_next = p_current;
174 p_menu->p_button = p_current;
175 p_current->p_prev = p_prev;
177 /* parse all states */
182 result = fscanf( fd, "\t%24s", state );
186 /* FIXME: We only parse one level deep now */
187 if( strncmp( state, "action", 6 ) == 0 )
189 osd_button_t *p_up = NULL;
191 result = fscanf( fd, "%24s (%d,%d)", action, &i_x, &i_y );
194 /* create new button */
195 p_up = osd_ButtonNew( action, i_x, i_y );
199 p_up->p_down = p_current;
200 p_current->p_up = p_up;
201 msg_Dbg( p_this, " + (menu up) hotkey=%s (%d,%d)", action, i_x, i_y );
202 /* Parse type state */
203 result = fscanf( fd, "\t%24s %24s", cmd, type );
206 if( strncmp( cmd, "type", 4 ) == 0 )
208 if( strncmp( type, "volume", 6 ) == 0 )
210 p_menu->p_state->p_volume = p_up;
211 msg_Dbg( p_this, " + type=%s", type );
214 /* Parse range state */
215 result = fscanf( fd, "\t%24s", state );
218 /* Parse the range state */
219 if( strncmp( state, "range", 5 ) == 0 )
221 osd_state_t *p_range_current = NULL; /* range state currently processed */
222 osd_state_t *p_range_prev = NULL; /* previous state processed range */
225 p_up->b_range = true;
227 result = fscanf( fd, "\t%24s", action );
231 result = fscanf( fd, "\t%d", &i_index );
235 msg_Dbg( p_this, " + (menu up) hotkey down %s, file=%s%s",
236 action, p_menu->psz_path, file );
238 free( p_up->psz_action_down );
239 p_up->psz_action_down = strdup( action );
241 /* Parse range contstruction :
250 result = fscanf( fd, "\t%255s", file );
253 if( strncmp( file, "end", 3 ) == 0 )
256 p_range_prev = p_range_current;
258 if( p_menu->psz_path )
260 size_t i_path_size = strlen( p_menu->psz_path );
261 size_t i_file_size = strlen( file );
263 if( (i_path_size + i_file_size >= PATH_MAX) ||
264 (i_path_size >= PATH_MAX) )
267 strncpy( path, p_menu->psz_path, i_path_size );
268 strncpy( &path[i_path_size], file,
269 PATH_MAX - (i_path_size + i_file_size) );
270 path[ i_path_size + i_file_size ] = '\0';
272 p_range_current = osd_StateNew( p_menu, path, "pressed" );
274 else /* absolute paths are used. */
275 p_range_current = osd_StateNew( p_menu, file, "pressed" );
277 if( !p_range_current )
280 if( !p_range_current->p_pic )
282 osd_StatesFree( p_menu, p_range_current );
286 p_range_current->i_x = i_x;
287 p_range_current->i_y = i_y;
289 /* increment the number of ranges for this button */
293 p_range_prev->p_next = p_range_current;
295 p_up->p_states = p_range_current;
296 p_range_current->p_prev = p_range_prev;
298 msg_Dbg( p_this, " |- range=%d, file=%s%s",
300 p_menu->psz_path, file );
304 osd_state_t *p_range = NULL;
306 /* Find the default index for state range */
307 p_range = p_up->p_states;
308 while( (--i_index > 0) && p_range->p_next )
310 osd_state_t *p_temp = NULL;
311 p_temp = p_range->p_next;
314 p_up->p_current_state = p_range;
316 else p_up->p_current_state = p_up->p_states;
319 result = fscanf( fd, "\t%24s", state );
322 if( strncmp( state, "end", 3 ) != 0 )
325 /* Continue at the beginning of the while() */
329 /* Parse the range state */
330 if( strncmp( state, "range", 5 ) == 0 )
332 osd_state_t *p_range_current = NULL; /* range state currently processed */
333 osd_state_t *p_range_prev = NULL; /* previous state processed range */
336 p_current->b_range = true;
338 result = fscanf( fd, "\t%24s", action );
342 result = fscanf( fd, "\t%d", &i_index );
346 msg_Dbg( p_this, " + hotkey down %s, file=%s%s",
347 action, p_menu->psz_path, file );
348 free( p_current->psz_action_down );
349 p_current->psz_action_down = strdup( action );
351 /* Parse range contstruction :
360 result = fscanf( fd, "\t%255s", file );
363 if( strncmp( file, "end", 3 ) == 0 )
366 p_range_prev = p_range_current;
368 if( p_menu->psz_path )
370 size_t i_path_size = strlen( p_menu->psz_path );
371 size_t i_file_size = strlen( file );
373 if( (i_path_size + i_file_size >= PATH_MAX) ||
374 (i_path_size >= PATH_MAX) )
377 strncpy( path, p_menu->psz_path, i_path_size );
378 strncpy( &path[i_path_size], file,
379 PATH_MAX - (i_path_size + i_file_size) );
380 path[ i_path_size + i_file_size ] = '\0';
382 p_range_current = osd_StateNew( p_menu, path, "pressed" );
384 else /* absolute paths are used. */
385 p_range_current = osd_StateNew( p_menu, file, "pressed" );
387 if( !p_range_current )
390 if( !p_range_current->p_pic )
392 osd_StatesFree( p_menu, p_range_current );
396 p_range_current->i_x = i_x;
397 p_range_current->i_y = i_y;
399 /* increment the number of ranges for this button */
400 p_current->i_ranges++;
403 p_range_prev->p_next = p_range_current;
405 p_current->p_states = p_range_current;
406 p_range_current->p_prev = p_range_prev;
408 msg_Dbg( p_this, " |- range=%d, file=%s%s",
410 p_menu->psz_path, file );
414 osd_state_t *p_range = NULL;
416 /* Find the default index for state range */
417 p_range = p_current->p_states;
418 while( (--i_index > 0) && p_range->p_next )
420 osd_state_t *p_temp = NULL;
421 p_temp = p_range->p_next;
424 p_current->p_current_state = p_range;
426 else p_current->p_current_state = p_current->p_states;
427 /* Continue at the beginning of the while() */
430 if( strncmp( state, "end", 3 ) == 0 )
433 result = fscanf( fd, "\t%255s", file );
437 p_state_prev = p_state_current;
439 if( ( strncmp( ppsz_button_states[0], state, strlen(ppsz_button_states[0]) ) != 0 ) &&
440 ( strncmp( ppsz_button_states[1], state, strlen(ppsz_button_states[1]) ) != 0 ) &&
441 ( strncmp( ppsz_button_states[2], state, strlen(ppsz_button_states[2]) ) != 0 ) )
443 msg_Err( p_this, "invalid button state %s for button %s "
444 "expected %u: unselect, select or pressed)",
445 state, action, (unsigned)strlen(state));
449 if( p_menu->psz_path )
451 size_t i_path_size = strlen( p_menu->psz_path );
452 size_t i_file_size = strlen( file );
454 if( (i_path_size + i_file_size >= PATH_MAX) ||
455 (i_path_size >= PATH_MAX) )
458 strncpy( path, p_menu->psz_path, i_path_size );
459 strncpy( &path[i_path_size], file,
460 PATH_MAX - (i_path_size + i_file_size) );
461 path[ i_path_size + i_file_size ] = '\0';
463 p_state_current = osd_StateNew( p_menu, path, state );
465 else /* absolute paths are used. */
466 p_state_current = osd_StateNew( p_menu, file, state );
468 if( !p_state_current )
471 if( !p_state_current->p_pic )
473 osd_StatesFree( p_menu, p_state_current );
477 p_state_current->i_x = i_x;
478 p_state_current->i_y = i_y;
481 p_state_prev->p_next = p_state_current;
483 p_current->p_states = p_state_current;
484 p_state_current->p_prev = p_state_prev;
486 msg_Dbg( p_this, " |- state=%s, file=%s%s", state,
487 p_menu->psz_path, file );
489 p_current->p_current_state = p_current->p_states;
492 /* Find the last button and store its pointer.
493 * The OSD menu behaves like a roundrobin list.
495 p_current = p_menu->p_button;
496 while( p_current && p_current->p_next )
498 osd_button_t *p_temp = NULL;
499 p_temp = p_current->p_next;
502 p_menu->p_last_button = p_current;
507 msg_Err( p_this, "parsing file failed (returned %d)", result );
509 osd_MenuFree( p_menu );