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"
39 #include "option_select.h"
46 #include "menus/exported_menus.h"
48 #include "root_menu.h"
50 #include "gwps-common.h" /* for fade() */
53 #ifdef HAVE_LCD_BITMAP
59 #include "statusbar.h"
60 #include "buttonbar.h"
63 /* used to allow for dynamic menus */
64 #define MAX_MENU_SUBITEMS 64
65 static struct menu_item_ex
*current_submenus_menu
;
66 static int current_subitems
[MAX_MENU_SUBITEMS
];
67 static int current_subitems_count
= 0;
69 static void get_menu_callback(const struct menu_item_ex
*m
,
70 menu_callback_type
*menu_callback
)
72 if (m
->flags
&(MENU_HAS_DESC
|MENU_DYNAMIC_DESC
))
73 *menu_callback
= m
->callback_and_desc
->menu_callback
;
75 *menu_callback
= m
->menu_callback
;
78 static int get_menu_selection(int selected_item
, const struct menu_item_ex
*menu
)
80 int type
= (menu
->flags
&MENU_TYPE_MASK
);
81 if (type
== MT_MENU
&& (selected_item
<current_subitems_count
))
82 return current_subitems
[selected_item
];
85 static int find_menu_selection(int selected
)
88 for (i
=0; i
< current_subitems_count
; i
++)
89 if (current_subitems
[i
] == selected
)
93 static char * get_menu_item_name(int selected_item
,void * data
, char *buffer
)
95 const struct menu_item_ex
*menu
= (const struct menu_item_ex
*)data
;
96 int type
= (menu
->flags
&MENU_TYPE_MASK
);
97 selected_item
= get_menu_selection(selected_item
, menu
);
100 /* only MT_MENU or MT_RETURN_ID is allowed in here */
101 if (type
== MT_RETURN_ID
)
103 if (menu
->flags
&MENU_DYNAMIC_DESC
)
104 return menu
->menu_get_name_and_icon
->list_get_name(selected_item
,
105 menu
->menu_get_name_and_icon
->list_get_name_data
, buffer
);
106 return (char*)menu
->strings
[selected_item
];
109 menu
= menu
->submenus
[selected_item
];
111 if ((menu
->flags
&MENU_DYNAMIC_DESC
) && (type
!= MT_SETTING_W_TEXT
))
112 return menu
->menu_get_name_and_icon
->list_get_name(selected_item
,
113 menu
->menu_get_name_and_icon
->list_get_name_data
, buffer
);
115 type
= (menu
->flags
&MENU_TYPE_MASK
);
116 if ((type
== MT_SETTING
) || (type
== MT_SETTING_W_TEXT
))
118 const struct settings_list
*v
119 = find_setting(menu
->variable
, NULL
);
121 return str(v
->lang_id
);
122 else return "Not Done yet!";
124 return P2STR(menu
->callback_and_desc
->desc
);
126 #ifdef HAVE_LCD_BITMAP
127 static int menu_get_icon(int selected_item
, void * data
)
129 const struct menu_item_ex
*menu
= (const struct menu_item_ex
*)data
;
130 int menu_icon
= Icon_NOICON
;
131 selected_item
= get_menu_selection(selected_item
, menu
);
133 if ((menu
->flags
&MENU_TYPE_MASK
) == MT_RETURN_ID
)
135 return Icon_Menu_functioncall
;
137 menu
= menu
->submenus
[selected_item
];
138 if (menu
->flags
&MENU_HAS_DESC
)
139 menu_icon
= menu
->callback_and_desc
->icon_id
;
140 else if (menu
->flags
&MENU_DYNAMIC_DESC
)
141 menu_icon
= menu
->menu_get_name_and_icon
->icon_id
;
143 if (menu_icon
== Icon_NOICON
)
145 switch (menu
->flags
&MENU_TYPE_MASK
)
148 case MT_SETTING_W_TEXT
:
149 menu_icon
= Icon_Menu_setting
;
152 menu_icon
= Icon_Submenu
;
154 case MT_FUNCTION_CALL
:
155 case MT_RETURN_VALUE
:
156 menu_icon
= Icon_Menu_functioncall
;
164 static void init_menu_lists(const struct menu_item_ex
*menu
,
165 struct gui_synclist
*lists
, int selected
, bool callback
)
167 int i
, count
= MENU_GET_COUNT(menu
->flags
);
168 int type
= (menu
->flags
&MENU_TYPE_MASK
);
169 menu_callback_type menu_callback
= NULL
;
171 current_subitems_count
= 0;
173 if (type
== MT_RETURN_ID
)
174 get_menu_callback(menu
, &menu_callback
);
176 for (i
=0; i
<count
; i
++)
178 if (type
!= MT_RETURN_ID
)
179 get_menu_callback(menu
->submenus
[i
],&menu_callback
);
182 if (menu_callback(ACTION_REQUEST_MENUITEM
,
183 type
==MT_RETURN_ID
? (void*)(intptr_t)i
: menu
->submenus
[i
])
184 != ACTION_EXIT_MENUITEM
)
186 current_subitems
[current_subitems_count
] = i
;
187 current_subitems_count
++;
192 current_subitems
[current_subitems_count
] = i
;
193 current_subitems_count
++;
196 current_submenus_menu
= (struct menu_item_ex
*)menu
;
198 gui_synclist_init(lists
,get_menu_item_name
,(void*)menu
,false,1);
199 #ifdef HAVE_LCD_BITMAP
200 if (menu
->callback_and_desc
->icon_id
== Icon_NOICON
)
201 icon
= Icon_Submenu_Entered
;
203 icon
= menu
->callback_and_desc
->icon_id
;
204 gui_synclist_set_title(lists
, P2STR(menu
->callback_and_desc
->desc
), icon
);
205 gui_synclist_set_icon_callback(lists
, menu_get_icon
);
208 gui_synclist_set_icon_callback(lists
, NULL
);
210 gui_synclist_set_nb_items(lists
,current_subitems_count
);
211 gui_synclist_limit_scroll(lists
,true);
212 gui_synclist_select_item(lists
, find_menu_selection(selected
));
214 get_menu_callback(menu
,&menu_callback
);
215 if (callback
&& menu_callback
)
216 menu_callback(ACTION_ENTER_MENUITEM
,menu
);
217 gui_synclist_draw(lists
);
220 static void talk_menu_item(const struct menu_item_ex
*menu
,
221 struct gui_synclist
*lists
)
228 if (talk_menus_enabled())
230 sel
= get_menu_selection(gui_synclist_get_sel_pos(lists
),menu
);
231 if ((menu
->flags
&MENU_TYPE_MASK
) == MT_MENU
)
233 type
= menu
->submenus
[sel
]->flags
&MENU_TYPE_MASK
;
234 if ((type
== MT_SETTING
) || (type
== MT_SETTING_W_TEXT
))
235 talk_setting(menu
->submenus
[sel
]->variable
);
238 if (menu
->submenus
[sel
]->flags
&(MENU_DYNAMIC_DESC
))
241 str
= menu
->submenus
[sel
]->menu_get_name_and_icon
->
242 list_get_name(sel
, menu
->submenus
[sel
]->
243 menu_get_name_and_icon
->
244 list_get_name_data
, buffer
);
248 id
= P2ID(menu
->submenus
[sel
]->callback_and_desc
->desc
);
255 #define MAX_OPTIONS 32
256 bool do_setting_from_menu(const struct menu_item_ex
*temp
)
259 const struct settings_list
*setting
= find_setting(
263 if ((temp
->flags
&MENU_TYPE_MASK
) == MT_SETTING_W_TEXT
)
264 title
= temp
->callback_and_desc
->desc
;
266 title
= ID2P(setting
->lang_id
);
267 option_screen((struct settings_list
*)setting
,
268 setting
->flags
&F_TEMPVAR
, title
);
272 int do_menu(const struct menu_item_ex
*start_menu
, int *start_selected
)
274 int selected
= start_selected
? *start_selected
: 0;
276 struct gui_synclist lists
;
277 const struct menu_item_ex
*temp
, *menu
;
281 struct gui_buttonbar buttonbar
;
284 const struct menu_item_ex
*menu_stack
[MAX_MENUS
];
285 int menu_stack_selected_item
[MAX_MENUS
];
287 bool in_stringlist
, done
= false;
288 menu_callback_type menu_callback
= NULL
;
289 bool talk_item
= false;
290 if (start_menu
== NULL
)
292 else menu
= start_menu
;
294 gui_buttonbar_init(&buttonbar
);
295 gui_buttonbar_set_display(&buttonbar
, &(screens
[SCREEN_MAIN
]) );
296 gui_buttonbar_set(&buttonbar
, "<<<", "", "");
297 gui_buttonbar_draw(&buttonbar
);
299 init_menu_lists(menu
,&lists
,selected
,true);
300 in_stringlist
= ((menu
->flags
&MENU_TYPE_MASK
) == MT_RETURN_ID
);
302 talk_menu_item(menu
, &lists
);
304 /* load the callback, and only reload it if menu changes */
305 get_menu_callback(menu
, &menu_callback
);
306 gui_synclist_draw(&lists
);
311 redraw_lists
= false;
312 gui_syncstatusbar_draw(&statusbars
, true);
313 action
= get_action(CONTEXT_MAINMENU
,HZ
);
314 /* HZ so the status bar redraws corectly */
315 if (action
== ACTION_NONE
)
322 int old_action
= action
;
323 action
= menu_callback(action
, menu
);
324 if (action
== ACTION_EXIT_AFTER_THIS_MENUITEM
)
327 ret
= MENU_SELECTED_EXIT
; /* will exit after returning
330 else if (action
== ACTION_REDRAW
)
337 if (gui_synclist_do_button(&lists
,action
,LIST_WRAP_UNLESS_HELD
))
339 talk_menu_item(menu
, &lists
);
343 #ifdef HAVE_RECORDING
344 if (action
== ACTION_STD_REC
)
346 ret
= GO_TO_RECSCREEN
;
351 if (action
== ACTION_TREE_WPS
)
353 ret
= GO_TO_PREVIOUS_MUSIC
;
356 else if (action
== ACTION_TREE_STOP
)
360 else if (action
== ACTION_STD_CONTEXT
&&
363 ret
= GO_TO_ROOTITEM_CONTEXT
;
366 else if (action
== ACTION_STD_MENU
)
368 if (menu
!= &root_menu_
)
371 ret
= GO_TO_PREVIOUS
;
374 else if (action
== ACTION_STD_CANCEL
)
376 in_stringlist
= false;
378 menu_callback(ACTION_EXIT_MENUITEM
, menu
);
380 if (menu
->flags
&MENU_EXITAFTERTHISMENU
)
385 menu
= menu_stack
[stack_top
];
386 if (menu
->flags
&MENU_EXITAFTERTHISMENU
)
388 init_menu_lists(menu
, &lists
,
389 menu_stack_selected_item
[stack_top
], false);
390 /* new menu, so reload the callback */
391 get_menu_callback(menu
, &menu_callback
);
394 else if (menu
!= &root_menu_
)
396 ret
= GO_TO_PREVIOUS
;
400 else if (action
== ACTION_STD_OK
)
404 gui_buttonbar_unset(&buttonbar
);
405 gui_buttonbar_draw(&buttonbar
);
407 selected
= get_menu_selection(gui_synclist_get_sel_pos(&lists
), menu
);
408 temp
= menu
->submenus
[selected
];
411 type
= (menu
->flags
&MENU_TYPE_MASK
);
414 type
= (temp
->flags
&MENU_TYPE_MASK
);
415 get_menu_callback(temp
, &menu_callback
);
418 action
= menu_callback(ACTION_ENTER_MENUITEM
,temp
);
419 if (action
== ACTION_EXIT_MENUITEM
)
426 if (stack_top
< MAX_MENUS
)
428 menu_stack
[stack_top
] = menu
;
429 menu_stack_selected_item
[stack_top
] = selected
;
431 init_menu_lists(temp
, &lists
, 0, true);
432 redraw_lists
= false; /* above does the redraw */
437 case MT_FUNCTION_CALL
:
441 if (temp
->flags
&MENU_FUNC_USEPARAM
)
442 return_value
= temp
->function
->function_w_param(
443 temp
->function
->param
);
445 return_value
= temp
->function
->function();
446 if (temp
->flags
&MENU_FUNC_CHECK_RETVAL
)
448 if (return_value
== 1)
457 case MT_SETTING_W_TEXT
:
459 if (do_setting_from_menu(temp
))
461 init_menu_lists(menu
, &lists
, selected
, true);
462 redraw_lists
= false; /* above does the redraw */
473 else if (stack_top
< MAX_MENUS
)
475 menu_stack
[stack_top
] = menu
;
476 menu_stack_selected_item
[stack_top
] = selected
;
479 init_menu_lists(menu
,&lists
,0,false);
480 redraw_lists
= false; /* above does the redraw */
482 in_stringlist
= true;
485 case MT_RETURN_VALUE
:
493 menu_callback(ACTION_EXIT_MENUITEM
,temp
);
495 if (current_submenus_menu
!= menu
)
496 init_menu_lists(menu
,&lists
,selected
,true);
497 /* callback was changed, so reload the menu's callback */
498 get_menu_callback(menu
, &menu_callback
);
499 if ((menu
->flags
&MENU_EXITAFTERTHISMENU
) &&
500 !(temp
->flags
&MENU_EXITAFTERTHISMENU
))
506 gui_buttonbar_set(&buttonbar
, "<<<", "", "");
507 gui_buttonbar_draw(&buttonbar
);
510 else if(default_event_handler(action
) == SYS_USB_CONNECTED
)
512 ret
= MENU_ATTACHED_USB
;
515 if (talk_item
&& !done
)
516 talk_menu_item(menu
, &lists
);
519 gui_synclist_draw(&lists
);
523 /* make sure the start_selected variable is set to
524 the selected item from the menu do_menu() was called from */
527 menu
= menu_stack
[0];
528 init_menu_lists(menu
,&lists
,menu_stack_selected_item
[0],true);
530 *start_selected
= get_menu_selection(
531 gui_synclist_get_sel_pos(&lists
), menu
);