1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 Robert E. Hak
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
21 - Multi screen support
22 - Rewrote/removed a lot of code now useless with the new gui API
30 #include "backlight.h"
38 #include "settings_list.h"
45 #include "menus/exported_menus.h"
47 #include "root_menu.h"
49 #include "gwps-common.h" /* for fade() */
52 #ifdef HAVE_LCD_BITMAP
58 #include "statusbar.h"
59 #include "buttonbar.h"
62 /* used to allow for dynamic menus */
63 #define MAX_MENU_SUBITEMS 64
64 static struct menu_item_ex
*current_submenus_menu
;
65 static int current_subitems
[MAX_MENU_SUBITEMS
];
66 static int current_subitems_count
= 0;
68 static void get_menu_callback(const struct menu_item_ex
*m
,
69 menu_callback_type
*menu_callback
)
71 if (m
->flags
&(MENU_HAS_DESC
|MENU_DYNAMIC_DESC
))
72 *menu_callback
= m
->callback_and_desc
->menu_callback
;
74 *menu_callback
= m
->menu_callback
;
77 static int get_menu_selection(int selected_item
, const struct menu_item_ex
*menu
)
79 int type
= (menu
->flags
&MENU_TYPE_MASK
);
80 if (type
== MT_MENU
&& (selected_item
<current_subitems_count
))
81 return current_subitems
[selected_item
];
84 static int find_menu_selection(int selected
)
87 for (i
=0; i
< current_subitems_count
; i
++)
88 if (current_subitems
[i
] == selected
)
92 static char * get_menu_item_name(int selected_item
,void * data
, char *buffer
)
94 const struct menu_item_ex
*menu
= (const struct menu_item_ex
*)data
;
95 int type
= (menu
->flags
&MENU_TYPE_MASK
);
96 selected_item
= get_menu_selection(selected_item
, menu
);
99 /* only MT_MENU or MT_RETURN_ID is allowed in here */
100 if (type
== MT_RETURN_ID
)
102 if (menu
->flags
&MENU_DYNAMIC_DESC
)
103 return menu
->menu_get_name_and_icon
->list_get_name(selected_item
,
104 menu
->menu_get_name_and_icon
->list_get_name_data
, buffer
);
105 return (char*)menu
->strings
[selected_item
];
108 menu
= menu
->submenus
[selected_item
];
110 if ((menu
->flags
&MENU_DYNAMIC_DESC
) && (type
!= MT_SETTING_W_TEXT
))
111 return menu
->menu_get_name_and_icon
->list_get_name(selected_item
,
112 menu
->menu_get_name_and_icon
->list_get_name_data
, buffer
);
114 type
= (menu
->flags
&MENU_TYPE_MASK
);
115 if ((type
== MT_SETTING
) || (type
== MT_SETTING_W_TEXT
))
117 const struct settings_list
*v
118 = find_setting(menu
->variable
, NULL
);
120 return str(v
->lang_id
);
121 else return "Not Done yet!";
123 return P2STR(menu
->callback_and_desc
->desc
);
125 #ifdef HAVE_LCD_BITMAP
126 static int menu_get_icon(int selected_item
, void * data
)
128 const struct menu_item_ex
*menu
= (const struct menu_item_ex
*)data
;
129 int menu_icon
= Icon_NOICON
;
130 selected_item
= get_menu_selection(selected_item
, menu
);
132 if ((menu
->flags
&MENU_TYPE_MASK
) == MT_RETURN_ID
)
134 return Icon_Menu_functioncall
;
136 menu
= menu
->submenus
[selected_item
];
137 if (menu
->flags
&MENU_HAS_DESC
)
138 menu_icon
= menu
->callback_and_desc
->icon_id
;
139 else if (menu
->flags
&MENU_DYNAMIC_DESC
)
140 menu_icon
= menu
->menu_get_name_and_icon
->icon_id
;
142 if (menu_icon
== Icon_NOICON
)
144 switch (menu
->flags
&MENU_TYPE_MASK
)
147 case MT_SETTING_W_TEXT
:
148 menu_icon
= Icon_Menu_setting
;
151 menu_icon
= Icon_Submenu
;
153 case MT_FUNCTION_CALL
:
154 case MT_RETURN_VALUE
:
155 menu_icon
= Icon_Menu_functioncall
;
163 static void init_menu_lists(const struct menu_item_ex
*menu
,
164 struct gui_synclist
*lists
, int selected
, bool callback
)
166 int i
, count
= MENU_GET_COUNT(menu
->flags
);
167 int type
= (menu
->flags
&MENU_TYPE_MASK
);
168 menu_callback_type menu_callback
= NULL
;
170 current_subitems_count
= 0;
172 if (type
== MT_RETURN_ID
)
173 get_menu_callback(menu
, &menu_callback
);
175 for (i
=0; i
<count
; i
++)
177 if (type
!= MT_RETURN_ID
)
178 get_menu_callback(menu
->submenus
[i
],&menu_callback
);
181 if (menu_callback(ACTION_REQUEST_MENUITEM
,
182 type
==MT_RETURN_ID
? (void*)(intptr_t)i
: menu
->submenus
[i
])
183 != ACTION_EXIT_MENUITEM
)
185 current_subitems
[current_subitems_count
] = i
;
186 current_subitems_count
++;
191 current_subitems
[current_subitems_count
] = i
;
192 current_subitems_count
++;
195 current_submenus_menu
= (struct menu_item_ex
*)menu
;
197 gui_synclist_init(lists
,get_menu_item_name
,(void*)menu
,false,1);
198 #ifdef HAVE_LCD_BITMAP
199 if (menu
->callback_and_desc
->icon_id
== Icon_NOICON
)
200 icon
= Icon_Submenu_Entered
;
202 icon
= menu
->callback_and_desc
->icon_id
;
203 gui_synclist_set_title(lists
, P2STR(menu
->callback_and_desc
->desc
), icon
);
204 gui_synclist_set_icon_callback(lists
, menu_get_icon
);
207 gui_synclist_set_icon_callback(lists
, NULL
);
209 gui_synclist_set_nb_items(lists
,current_subitems_count
);
210 gui_synclist_limit_scroll(lists
,true);
211 gui_synclist_select_item(lists
, find_menu_selection(selected
));
213 get_menu_callback(menu
,&menu_callback
);
214 if (callback
&& menu_callback
)
215 menu_callback(ACTION_ENTER_MENUITEM
,menu
);
216 gui_synclist_draw(lists
);
219 static void talk_menu_item(const struct menu_item_ex
*menu
,
220 struct gui_synclist
*lists
)
227 if (global_settings
.talk_menu
)
229 sel
= get_menu_selection(gui_synclist_get_sel_pos(lists
),menu
);
230 if ((menu
->flags
&MENU_TYPE_MASK
) == MT_MENU
)
232 type
= menu
->submenus
[sel
]->flags
&MENU_TYPE_MASK
;
233 if ((type
== MT_SETTING
) || (type
== MT_SETTING_W_TEXT
))
234 talk_setting(menu
->submenus
[sel
]->variable
);
237 if (menu
->submenus
[sel
]->flags
&(MENU_DYNAMIC_DESC
))
240 str
= menu
->submenus
[sel
]->menu_get_name_and_icon
->
241 list_get_name(sel
, menu
->submenus
[sel
]->
242 menu_get_name_and_icon
->
243 list_get_name_data
, buffer
);
247 id
= P2ID(menu
->submenus
[sel
]->callback_and_desc
->desc
);
254 #define MAX_OPTIONS 32
255 /* returns true if the menu needs to be redrwan */
256 bool do_setting_from_menu(const struct menu_item_ex
*temp
)
259 const struct settings_list
*setting
= find_setting(
262 bool ret_val
= false;
263 unsigned char *title
;
266 if ((temp
->flags
&MENU_TYPE_MASK
) == MT_SETTING_W_TEXT
)
267 title
= temp
->callback_and_desc
->desc
;
269 title
= ID2P(setting
->lang_id
);
271 if ((setting
->flags
&F_BOOL_SETTING
) == F_BOOL_SETTING
)
274 bool show_icons
= global_settings
.show_icons
;
275 if (setting
->flags
&F_TEMPVAR
)
277 temp_var
= *(bool*)setting
->setting
;
282 var
= (bool*)setting
->setting
;
284 set_bool_options(P2STR(title
), var
,
285 STR(setting
->bool_setting
->lang_yes
),
286 STR(setting
->bool_setting
->lang_no
),
287 setting
->bool_setting
->option_callback
);
288 if (setting
->flags
&F_TEMPVAR
)
289 *(bool*)setting
->setting
= temp_var
;
290 if (show_icons
!= global_settings
.show_icons
)
293 else if (setting
->flags
&F_T_SOUND
)
295 set_sound(P2STR(title
), setting
->setting
,
296 setting
->sound_setting
->setting
);
298 else /* other setting, must be an INT type */
301 if (setting
->flags
&F_TEMPVAR
)
303 temp_var
= *(int*)setting
->setting
;
308 var
= (int*)setting
->setting
;
310 if (setting
->flags
&F_INT_SETTING
)
313 if (setting
->flags
&F_FLIPLIST
)
315 min
= setting
->int_setting
->max
;
316 max
= setting
->int_setting
->min
;
317 step
= -setting
->int_setting
->step
;
321 max
= setting
->int_setting
->max
;
322 min
= setting
->int_setting
->min
;
323 step
= setting
->int_setting
->step
;
325 set_int_ex(P2STR(title
), NULL
,
326 setting
->int_setting
->unit
,var
,
327 setting
->int_setting
->option_callback
,
329 setting
->int_setting
->formatter
,
330 setting
->int_setting
->get_talk_id
);
332 else if (setting
->flags
&F_CHOICE_SETTING
)
334 static struct opt_items options
[MAX_OPTIONS
];
336 char *buf_start
= buffer
;
338 int i
,j
, count
= setting
->choice_setting
->count
;
339 for (i
=0, j
=0; i
<count
&& i
<MAX_OPTIONS
; i
++)
341 if (setting
->flags
&F_CHOICETALKS
)
343 if (cfg_int_to_string(setting_id
, i
,
344 buf_start
, buf_free
))
346 int len
= strlen(buf_start
) +1;
347 options
[j
].string
= buf_start
;
350 options
[j
].voice_id
=
351 setting
->choice_setting
->talks
[i
];
359 choice_setting
->desc
[i
]);
360 options
[j
].voice_id
=
362 choice_setting
->desc
[i
]);
366 set_option(P2STR(title
), var
, INT
,
369 choice_setting
->option_callback
);
371 if (setting
->flags
&F_TEMPVAR
)
372 *(int*)setting
->setting
= temp_var
;
378 int do_menu(const struct menu_item_ex
*start_menu
, int *start_selected
)
380 int selected
= start_selected
? *start_selected
: 0;
382 struct gui_synclist lists
;
383 const struct menu_item_ex
*temp
, *menu
;
386 struct gui_buttonbar buttonbar
;
389 const struct menu_item_ex
*menu_stack
[MAX_MENUS
];
390 int menu_stack_selected_item
[MAX_MENUS
];
392 bool in_stringlist
, done
= false;
393 menu_callback_type menu_callback
= NULL
;
394 if (start_menu
== NULL
)
396 else menu
= start_menu
;
398 gui_buttonbar_init(&buttonbar
);
399 gui_buttonbar_set_display(&buttonbar
, &(screens
[SCREEN_MAIN
]) );
400 gui_buttonbar_set(&buttonbar
, "<<<", "", "");
401 gui_buttonbar_draw(&buttonbar
);
403 init_menu_lists(menu
,&lists
,selected
,true);
404 in_stringlist
= ((menu
->flags
&MENU_TYPE_MASK
) == MT_RETURN_ID
);
406 talk_menu_item(menu
, &lists
);
408 action_signalscreenchange();
410 /* load the callback, and only reload it if menu changes */
411 get_menu_callback(menu
, &menu_callback
);
412 gui_synclist_draw(&lists
);
416 gui_syncstatusbar_draw(&statusbars
, true);
417 action
= get_action(CONTEXT_MAINMENU
,HZ
);
418 /* HZ so the status bar redraws corectly */
419 if (action
== ACTION_NONE
)
423 gui_synclist_draw(&lists
);
427 int old_action
= action
;
428 action
= menu_callback(action
, menu
);
429 if (action
== ACTION_EXIT_AFTER_THIS_MENUITEM
)
432 ret
= MENU_SELECTED_EXIT
; /* will exit after returning
437 if (gui_synclist_do_button(&lists
,action
,LIST_WRAP_UNLESS_HELD
))
439 talk_menu_item(menu
, &lists
);
441 else if (action
== ACTION_TREE_WPS
)
443 ret
= GO_TO_PREVIOUS_MUSIC
;
446 else if (action
== ACTION_TREE_STOP
)
450 else if (action
== ACTION_STD_CONTEXT
&&
453 ret
= GO_TO_ROOTITEM_CONTEXT
;
456 else if (action
== ACTION_STD_MENU
)
458 if (menu
!= &root_menu_
)
461 ret
= GO_TO_PREVIOUS
;
464 else if (action
== ACTION_STD_CANCEL
)
466 in_stringlist
= false;
468 menu_callback(ACTION_EXIT_MENUITEM
, menu
);
470 if (menu
->flags
&MENU_EXITAFTERTHISMENU
)
475 menu
= menu_stack
[stack_top
];
476 if (menu
->flags
&MENU_EXITAFTERTHISMENU
)
478 init_menu_lists(menu
, &lists
,
479 menu_stack_selected_item
[stack_top
], false);
480 talk_menu_item(menu
, &lists
);
481 /* new menu, so reload the callback */
482 get_menu_callback(menu
, &menu_callback
);
484 else if (menu
!= &root_menu_
)
486 ret
= GO_TO_PREVIOUS
;
490 else if (action
== ACTION_STD_OK
)
494 gui_buttonbar_unset(&buttonbar
);
495 gui_buttonbar_draw(&buttonbar
);
497 selected
= get_menu_selection(gui_synclist_get_sel_pos(&lists
), menu
);
498 temp
= menu
->submenus
[selected
];
500 type
= (menu
->flags
&MENU_TYPE_MASK
);
503 type
= (temp
->flags
&MENU_TYPE_MASK
);
504 get_menu_callback(temp
, &menu_callback
);
507 action
= menu_callback(ACTION_ENTER_MENUITEM
,temp
);
508 if (action
== ACTION_EXIT_MENUITEM
)
515 if (stack_top
< MAX_MENUS
)
517 menu_stack
[stack_top
] = menu
;
518 menu_stack_selected_item
[stack_top
] = selected
;
520 init_menu_lists(temp
, &lists
, 0, true);
522 talk_menu_item(menu
, &lists
);
525 case MT_FUNCTION_CALL
:
528 action_signalscreenchange();
529 if (temp
->flags
&MENU_FUNC_USEPARAM
)
530 return_value
= temp
->function
->function_w_param(
531 temp
->function
->param
);
533 return_value
= temp
->function
->function();
534 if (temp
->flags
&MENU_FUNC_CHECK_RETVAL
)
536 if (return_value
== 1)
545 case MT_SETTING_W_TEXT
:
547 if (do_setting_from_menu(temp
))
548 init_menu_lists(menu
, &lists
, 0, true);
554 action_signalscreenchange();
558 else if (stack_top
< MAX_MENUS
)
560 menu_stack
[stack_top
] = menu
;
561 menu_stack_selected_item
[stack_top
] = selected
;
564 init_menu_lists(menu
,&lists
,0,false);
565 in_stringlist
= true;
568 case MT_RETURN_VALUE
:
576 menu_callback(ACTION_EXIT_MENUITEM
,temp
);
578 if (current_submenus_menu
!= menu
)
579 init_menu_lists(menu
,&lists
,selected
,true);
580 /* callback was changed, so reload the menu's callback */
581 get_menu_callback(menu
, &menu_callback
);
582 if ((menu
->flags
&MENU_EXITAFTERTHISMENU
) &&
583 !(temp
->flags
&MENU_EXITAFTERTHISMENU
))
589 gui_buttonbar_set(&buttonbar
, "<<<", "", "");
590 gui_buttonbar_draw(&buttonbar
);
592 gui_synclist_draw(&lists
);
594 else if(default_event_handler(action
) == SYS_USB_CONNECTED
)
596 ret
= MENU_ATTACHED_USB
;
600 action_signalscreenchange();
603 /* make sure the start_selected variable is set to
604 the selected item from the menu do_menu() was called from */
607 menu
= menu_stack
[0];
608 init_menu_lists(menu
,&lists
,menu_stack_selected_item
[0],true);
610 *start_selected
= get_menu_selection(
611 gui_synclist_get_sel_pos(&lists
), menu
);