1 /*****************************************************************************
2 * simple.c - The OSD Menu simple parser code.
3 *****************************************************************************
4 * Copyright (C) 2005-2007 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 *****************************************************************************/
34 #include <vlc_config.h>
37 #include <vlc_image.h>
39 #include <vlc_charset.h>
43 int osd_parser_simpleOpen( vlc_object_t
*p_this
);
45 /*****************************************************************************
46 * Simple parser open function
47 *****************************************************************************/
48 int osd_parser_simpleOpen( vlc_object_t
*p_this
)
50 osd_menu_t
*p_menu
= (osd_menu_t
*) p_this
;
51 osd_button_t
*p_current
= NULL
; /* button currently processed */
52 osd_button_t
*p_prev
= NULL
; /* previous processed button */
54 #define MAX_FILE_PATH 256
58 if( !p_menu
) return VLC_ENOOBJ
;
60 msg_Dbg( p_this
, "opening osdmenu definition file %s", p_menu
->psz_file
);
61 fd
= utf8_fopen( p_menu
->psz_file
, "r" );
64 msg_Err( p_this
, "failed to open osdmenu definition file %s",
74 char path
[MAX_FILE_PATH
] = "";
75 char *psz_path
= NULL
;
79 result
= fscanf(fd
, "%24s %255s", &action
[0], &path
[0] );
81 /* override images path ? */
82 psz_path
= config_GetPsz( p_this
, "osdmenu-file-path" );
85 /* psz_path is not null and therefor &path[0] cannot be NULL
86 * it might be null terminated.
88 strncpy( &path
[0], psz_path
, MAX_FILE_PATH
);
92 /* NULL terminate before asking the length of path[] */
93 path
[MAX_FILE_PATH
-1] = '\0';
94 i_len
= strlen(&path
[0]);
95 if( i_len
== MAX_FILE_PATH
)
96 i_len
--; /* truncate to prevent buffer overflow */
97 #if defined(WIN32) || defined(UNDER_CE)
98 if( (i_len
> 0) && path
[i_len
] != '\\' )
101 if( (i_len
> 0) && path
[i_len
] != '/' )
104 path
[i_len
+1] = '\0';
105 if( result
== 0 || result
== EOF
)
107 msg_Dbg( p_this
, "osdmenu dir %s", &path
[0] );
110 p_menu
= osd_MenuNew( p_menu
, NULL
, 0, 0 );
112 p_menu
= osd_MenuNew( p_menu
, &path
[0], 0, 0 );
114 /* Peek for 'style' argument */
119 result
= fscanf(fd
, "%24s %24s", &cmd
[0], &action
[0] );
120 if( result
== 0 || result
== EOF
)
123 msg_Dbg( p_this
, "osdmenu %s %s", &cmd
[0], &action
[0] );
124 if( strncmp( &cmd
[0], "style", 5 ) == 0 )
126 if( strncmp( &action
[0], "default", 7) == 0 )
128 p_menu
->i_style
= OSD_MENU_STYLE_SIMPLE
;
130 else if( strncmp( &action
[0], "concat", 6) == 0 )
132 p_menu
->i_style
= OSD_MENU_STYLE_CONCAT
;
137 result
= fseek( fd
, pos
, SEEK_SET
);
146 /* read successive lines */
149 osd_state_t
*p_state_current
= NULL
; /* button state currently processed */
150 osd_state_t
*p_state_prev
= NULL
; /* previous state processed button */
153 char action
[25] = "";
160 result
= fscanf( fd
, "%24s %24s (%d,%d)", &cmd
[0], &action
[0], &i_x
, &i_y
);
163 if( strncmp( &cmd
[0], "action", 6 ) != 0 )
165 msg_Dbg( p_this
, " + %s hotkey=%s (%d,%d)", &cmd
[0], &action
[0], i_x
, i_y
);
168 p_current
= osd_ButtonNew( &action
[0], i_x
, i_y
);
173 p_prev
->p_next
= p_current
;
175 p_menu
->p_button
= p_current
;
176 p_current
->p_prev
= p_prev
;
178 /* parse all states */
183 result
= fscanf( fd
, "\t%24s", &state
[0] );
187 /* FIXME: We only parse one level deep now */
188 if( strncmp( &state
[0], "action", 6 ) == 0 )
190 osd_button_t
*p_up
= NULL
;
192 result
= fscanf( fd
, "%24s (%d,%d)", &action
[0], &i_x
, &i_y
);
195 /* create new button */
196 p_up
= osd_ButtonNew( &action
[0], i_x
, i_y
);
200 p_up
->p_down
= p_current
;
201 p_current
->p_up
= p_up
;
202 msg_Dbg( p_this
, " + (menu up) hotkey=%s (%d,%d)", &action
[0], i_x
, i_y
);
203 /* Parse type state */
204 result
= fscanf( fd
, "\t%24s %24s", &cmd
[0], &type
[0] );
207 if( strncmp( &cmd
[0], "type", 4 ) == 0 )
209 if( strncmp( &type
[0], "volume", 6 ) == 0 )
211 p_menu
->p_state
->p_volume
= p_up
;
212 msg_Dbg( p_this
, " + type=%s", &type
[0] );
215 /* Parse range state */
216 result
= fscanf( fd
, "\t%24s", &state
[0] );
219 /* Parse the range state */
220 if( strncmp( &state
[0], "range", 5 ) == 0 )
222 osd_state_t
*p_range_current
= NULL
; /* range state currently processed */
223 osd_state_t
*p_range_prev
= NULL
; /* previous state processed range */
226 p_up
->b_range
= true;
228 result
= fscanf( fd
, "\t%24s", &action
[0] );
232 result
= fscanf( fd
, "\t%d", &i_index
);
236 msg_Dbg( p_this
, " + (menu up) hotkey down %s, file=%s%s",
237 &action
[0], p_menu
->psz_path
, &file
[0] );
239 free( p_up
->psz_action_down
);
240 p_up
->psz_action_down
= strdup( &action
[0] );
242 /* Parse range contstruction :
251 result
= fscanf( fd
, "\t%255s", &file
[0] );
254 if( strncmp( &file
[0], "end", 3 ) == 0 )
257 p_range_prev
= p_range_current
;
259 if( p_menu
->psz_path
)
261 size_t i_path_size
= strlen( p_menu
->psz_path
);
262 size_t i_file_size
= strlen( &file
[0] );
264 strncpy( &path
[0], p_menu
->psz_path
, i_path_size
);
265 strncpy( &path
[i_path_size
], &file
[0], 512 - (i_path_size
+ i_file_size
) );
266 path
[ i_path_size
+ i_file_size
] = '\0';
268 p_range_current
= osd_StateNew( p_menu
, &path
[0], "pressed" );
270 else /* absolute paths are used. */
271 p_range_current
= osd_StateNew( p_menu
, &file
[0], "pressed" );
273 if( !p_range_current
)
276 if( !p_range_current
->p_pic
)
278 osd_StatesFree( p_menu
, p_range_current
);
282 p_range_current
->i_x
= i_x
;
283 p_range_current
->i_y
= i_y
;
285 /* increment the number of ranges for this button */
289 p_range_prev
->p_next
= p_range_current
;
291 p_up
->p_states
= p_range_current
;
292 p_range_current
->p_prev
= p_range_prev
;
294 msg_Dbg( p_this
, " |- range=%d, file=%s%s",
296 p_menu
->psz_path
, &file
[0] );
300 osd_state_t
*p_range
= NULL
;
302 /* Find the default index for state range */
303 p_range
= p_up
->p_states
;
304 while( (--i_index
> 0) && p_range
->p_next
)
306 osd_state_t
*p_temp
= NULL
;
307 p_temp
= p_range
->p_next
;
310 p_up
->p_current_state
= p_range
;
312 else p_up
->p_current_state
= p_up
->p_states
;
315 result
= fscanf( fd
, "\t%24s", &state
[0] );
318 if( strncmp( &state
[0], "end", 3 ) != 0 )
321 /* Continue at the beginning of the while() */
325 /* Parse the range state */
326 if( strncmp( &state
[0], "range", 5 ) == 0 )
328 osd_state_t
*p_range_current
= NULL
; /* range state currently processed */
329 osd_state_t
*p_range_prev
= NULL
; /* previous state processed range */
332 p_current
->b_range
= true;
334 result
= fscanf( fd
, "\t%24s", &action
[0] );
338 result
= fscanf( fd
, "\t%d", &i_index
);
342 msg_Dbg( p_this
, " + hotkey down %s, file=%s%s",
343 &action
[0], p_menu
->psz_path
, &file
[0] );
344 free( p_current
->psz_action_down
);
345 p_current
->psz_action_down
= strdup( &action
[0] );
347 /* Parse range contstruction :
356 result
= fscanf( fd
, "\t%255s", &file
[0] );
359 if( strncmp( &file
[0], "end", 3 ) == 0 )
362 p_range_prev
= p_range_current
;
364 if( p_menu
->psz_path
)
366 size_t i_path_size
= strlen( p_menu
->psz_path
);
367 size_t i_file_size
= strlen( &file
[0] );
369 strncpy( &path
[0], p_menu
->psz_path
, i_path_size
);
370 strncpy( &path
[i_path_size
], &file
[0], 512 - (i_path_size
+ i_file_size
) );
371 path
[ i_path_size
+ i_file_size
] = '\0';
373 p_range_current
= osd_StateNew( p_menu
, &path
[0], "pressed" );
375 else /* absolute paths are used. */
376 p_range_current
= osd_StateNew( p_menu
, &file
[0], "pressed" );
378 if( !p_range_current
)
381 if( !p_range_current
->p_pic
)
383 osd_StatesFree( p_menu
, p_range_current
);
387 p_range_current
->i_x
= i_x
;
388 p_range_current
->i_y
= i_y
;
390 /* increment the number of ranges for this button */
391 p_current
->i_ranges
++;
394 p_range_prev
->p_next
= p_range_current
;
396 p_current
->p_states
= p_range_current
;
397 p_range_current
->p_prev
= p_range_prev
;
399 msg_Dbg( p_this
, " |- range=%d, file=%s%s",
401 p_menu
->psz_path
, &file
[0] );
405 osd_state_t
*p_range
= NULL
;
407 /* Find the default index for state range */
408 p_range
= p_current
->p_states
;
409 while( (--i_index
> 0) && p_range
->p_next
)
411 osd_state_t
*p_temp
= NULL
;
412 p_temp
= p_range
->p_next
;
415 p_current
->p_current_state
= p_range
;
417 else p_current
->p_current_state
= p_current
->p_states
;
418 /* Continue at the beginning of the while() */
421 if( strncmp( &state
[0], "end", 3 ) == 0 )
424 result
= fscanf( fd
, "\t%255s", &file
[0] );
428 p_state_prev
= p_state_current
;
430 if( ( strncmp( ppsz_button_states
[0], &state
[0], strlen(ppsz_button_states
[0]) ) != 0 ) &&
431 ( strncmp( ppsz_button_states
[1], &state
[0], strlen(ppsz_button_states
[1]) ) != 0 ) &&
432 ( strncmp( ppsz_button_states
[2], &state
[0], strlen(ppsz_button_states
[2]) ) != 0 ) )
434 msg_Err( p_this
, "invalid button state %s for button %s "
435 "expected %u: unselect, select or pressed)",
436 &state
[0], &action
[0], (unsigned)strlen(&state
[0]));
440 if( p_menu
->psz_path
)
442 size_t i_path_size
= strlen( p_menu
->psz_path
);
443 size_t i_file_size
= strlen( &file
[0] );
445 strncpy( &path
[0], p_menu
->psz_path
, i_path_size
);
446 strncpy( &path
[i_path_size
], &file
[0], 512 - (i_path_size
+ i_file_size
) );
447 path
[ i_path_size
+ i_file_size
] = '\0';
449 p_state_current
= osd_StateNew( p_menu
, &path
[0], &state
[0] );
451 else /* absolute paths are used. */
452 p_state_current
= osd_StateNew( p_menu
, &file
[0], &state
[0] );
454 if( !p_state_current
)
457 if( !p_state_current
->p_pic
)
459 osd_StatesFree( p_menu
, p_state_current
);
463 p_state_current
->i_x
= i_x
;
464 p_state_current
->i_y
= i_y
;
467 p_state_prev
->p_next
= p_state_current
;
469 p_current
->p_states
= p_state_current
;
470 p_state_current
->p_prev
= p_state_prev
;
472 msg_Dbg( p_this
, " |- state=%s, file=%s%s", &state
[0],
473 p_menu
->psz_path
, &file
[0] );
475 p_current
->p_current_state
= p_current
->p_states
;
478 /* Find the last button and store its pointer.
479 * The OSD menu behaves like a roundrobin list.
481 p_current
= p_menu
->p_button
;
482 while( p_current
&& p_current
->p_next
)
484 osd_button_t
*p_temp
= NULL
;
485 p_temp
= p_current
->p_next
;
488 p_menu
->p_last_button
= p_current
;
494 msg_Err( p_menu
, "parsing file failed (returned %d)", result
);
495 osd_MenuFree( p_menu
);