make sure closing the application aborts the remaining HttpGet objects. Should fix...
[Rockbox.git] / apps / menus / main_menu.c
blob822301fe524c5e4bbe8cfd8bd54894492eff3fde
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 Jonathan Gordon
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 ****************************************************************************/
20 #include <stdbool.h>
21 #include <stddef.h>
22 #include <limits.h>
23 #include "config.h"
24 #include "string.h"
25 #include "lang.h"
26 #include "action.h"
27 #include "settings.h"
28 #include "powermgmt.h"
29 #include "menu.h"
30 #include "misc.h"
31 #include "exported_menus.h"
32 #include "tree.h"
33 #ifdef HAVE_RECORDING
34 #include "recording.h"
35 #endif
36 #include "bookmark.h"
37 #include "yesno.h"
38 #include "keyboard.h"
39 #include "screens.h"
40 #include "plugin.h"
41 #include "talk.h"
42 #include "buffer.h"
43 #include "splash.h"
44 #include "debug_menu.h"
45 #if defined(SIMULATOR) && defined(ROCKBOX_HAS_LOGF)
46 #include "logfdisp.h"
47 #endif
48 #include "version.h"
52 struct browse_folder_info {
53 const char* dir;
54 int show_options;
56 static struct browse_folder_info theme = {THEME_DIR, SHOW_CFG};
57 static struct browse_folder_info config = {ROCKBOX_DIR, SHOW_CFG};
58 int browse_folder(void *param)
60 const struct browse_folder_info *info =
61 (const struct browse_folder_info*)param;
62 return rockbox_browse(info->dir, info->show_options);
65 /***********************************/
66 /* MANAGE SETTINGS MENU */
68 static int reset_settings(void)
70 unsigned char *lines[]={ID2P(LANG_RESET_ASK)};
71 unsigned char *yes_lines[]={
72 str(LANG_SETTINGS),
73 ID2P(LANG_RESET_DONE_CLEAR)
75 unsigned char *no_lines[]={yes_lines[0], ID2P(LANG_CANCEL)};
76 struct text_message message={(char **)lines, 1};
77 struct text_message yes_message={(char **)yes_lines, 2};
78 struct text_message no_message={(char **)no_lines, 2};
80 switch(gui_syncyesno_run(&message, &yes_message, &no_message))
82 case YESNO_YES:
83 settings_reset();
84 settings_apply();
85 settings_save();
86 break;
87 case YESNO_NO:
88 break;
89 case YESNO_USB:
90 return 1;
92 return 0;
94 static int write_settings_file(void* param)
96 return settings_save_config((intptr_t)param);
99 MENUITEM_FUNCTION(browse_configs, MENU_FUNC_USEPARAM, ID2P(LANG_CUSTOM_CFG),
100 browse_folder, (void*)&config, NULL, Icon_NOICON);
101 MENUITEM_FUNCTION(save_settings_item, MENU_FUNC_USEPARAM, ID2P(LANG_SAVE_SETTINGS),
102 write_settings_file, (void*)SETTINGS_SAVE_ALL, NULL, Icon_NOICON);
103 MENUITEM_FUNCTION(save_theme_item, MENU_FUNC_USEPARAM, ID2P(LANG_SAVE_THEME),
104 write_settings_file, (void*)SETTINGS_SAVE_THEME, NULL, Icon_NOICON);
105 MENUITEM_FUNCTION(reset_settings_item, 0, ID2P(LANG_RESET),
106 reset_settings, NULL, NULL, Icon_NOICON);
108 MAKE_MENU(manage_settings, ID2P(LANG_MANAGE_MENU), NULL, Icon_Config,
109 &browse_configs, &reset_settings_item,
110 &save_settings_item, &save_theme_item);
111 /* MANAGE SETTINGS MENU */
112 /**********************************/
114 /***********************************/
115 /* INFO MENU */
117 static bool show_credits(void)
119 if (plugin_load(VIEWERS_DIR "/credits.rock",NULL) != PLUGIN_OK)
121 /* show the rockbox logo and version untill a button is pressed */
122 show_logo();
123 get_action(CONTEXT_STD, TIMEOUT_BLOCK);
125 return false;
128 #ifdef HAVE_LCD_CHARCELLS
129 #define SIZE_FMT "%s%s"
130 #else
131 #define SIZE_FMT "%s %s"
132 #endif
134 static bool show_info(void)
136 char s[64], s1[32];
137 unsigned long size, free;
138 long buflen = ((audiobufend - audiobuf) * 2) / 2097; /* avoid overflow */
139 int key;
140 int i;
141 bool done = false;
142 bool new_info = true;
143 #ifdef HAVE_MULTIVOLUME
144 char s2[32];
145 unsigned long size2, free2;
146 #endif
147 #ifdef HAVE_LCD_CHARCELLS
148 int page = 0;
149 #endif
151 const unsigned char *kbyte_units[] = {
152 ID2P(LANG_KILOBYTE),
153 ID2P(LANG_MEGABYTE),
154 ID2P(LANG_GIGABYTE)
156 #if defined(HAVE_LCD_BITMAP)
157 FOR_NB_SCREENS(i)
158 screens[i].setmargins(0, 0);
159 #endif
160 while (!done)
162 int y=0;
164 if (new_info)
166 fat_size( IF_MV2(0,) &size, &free );
167 #ifdef HAVE_MULTIVOLUME
168 if (fat_ismounted(1))
169 fat_size( 1, &size2, &free2 );
170 else
171 size2 = 0;
172 #endif
174 if (talk_menus_enabled())
176 /* say whatever is reasonable, no real connection to the screen */
177 bool enqueue = false; /* enqueue all but the first */
178 if (battery_level() >= 0)
180 talk_id(LANG_BATTERY_TIME, enqueue);
181 enqueue = true;
182 talk_value(battery_level(), UNIT_PERCENT, true);
183 #if CONFIG_CHARGING >= CHARGING_MONITOR
184 if (charge_state == CHARGING)
185 talk_id(LANG_BATTERY_CHARGE, true);
186 #if CONFIG_CHARGING == CHARGING_CONTROL
187 else if (charge_state == TOPOFF)
188 talk_id(LANG_BATTERY_TOPOFF_CHARGE, true);
189 #endif
190 else if (charge_state == TRICKLE)
191 talk_id(LANG_BATTERY_TRICKLE_CHARGE, true);
192 #endif
195 talk_id(LANG_DISK_FREE_INFO, enqueue);
196 #ifdef HAVE_MULTIVOLUME
197 talk_id(LANG_DISK_NAME_INTERNAL, true);
198 output_dyn_value(NULL, 0, free, kbyte_units, true);
199 if (size2)
201 talk_id(LANG_DISK_NAME_MMC, true);
202 output_dyn_value(NULL, 0, free2, kbyte_units, true);
204 #else
205 output_dyn_value(NULL, 0, free, kbyte_units, true);
206 #endif
208 #if CONFIG_RTC
210 struct tm* tm = get_time();
211 talk_id(VOICE_CURRENT_TIME, true);
212 if (global_settings.timeformat == 1)
214 long am_pm_id = VOICE_AM;
215 int hour = tm->tm_hour;
217 if (hour >= 12)
219 am_pm_id = VOICE_PM;
220 hour -= 12;
222 if (hour == 0)
223 hour = 12;
225 talk_number(hour, true);
227 /* Voice the minutes */
228 if (tm->tm_min == 0)
230 /* Say o'clock if the minute is 0. */
231 talk_id(VOICE_OCLOCK, true);
233 else
235 /* Pronounce the leading 0 */
236 if(tm->tm_min < 10)
238 talk_id(VOICE_OH, true);
240 talk_number(tm->tm_min, true);
242 talk_id(am_pm_id, true);
244 else
246 /* Voice the time in 24 hour format */
247 talk_number(tm->tm_hour, true);
248 if (tm->tm_min == 0)
250 talk_id(VOICE_HUNDRED, true);
251 talk_id(VOICE_HOUR, true);
253 else
255 /* Pronounce the leading 0 */
256 if(tm->tm_min < 10)
258 talk_id(VOICE_OH, true);
260 talk_number(tm->tm_min, true);
264 talk_id(LANG_MONTH_JANUARY + tm->tm_mon, true);
265 talk_number(tm->tm_mday, true);
266 talk_number(1900 + tm->tm_year, true);
268 #endif
270 new_info = false;
273 FOR_NB_SCREENS(i)
275 screens[i].clear_display();
276 #ifdef HAVE_LCD_BITMAP
277 screens[i].puts(0, y, str(LANG_ROCKBOX_INFO));
278 #endif
280 #ifdef HAVE_LCD_BITMAP
281 y++;
282 #endif
283 #ifdef HAVE_LCD_CHARCELLS
284 if (page == 0)
285 #endif
287 snprintf(s, sizeof(s), "%s: %s", str(LANG_VERSION), appsversion);
288 FOR_NB_SCREENS(i)
289 screens[i].puts_scroll(0, y, (unsigned char *)s);
290 #ifdef HAVE_LCD_BITMAP
291 y += 2;
292 #endif
295 #ifdef HAVE_LCD_CHARCELLS
296 if (page == 1)
297 #endif
299 int integer = buflen / 1000;
300 int decimal = buflen % 1000;
302 snprintf(s, sizeof(s), (char *)str(LANG_BUFFER_STAT),
303 integer, decimal);
305 FOR_NB_SCREENS(i)
306 screens[i].puts_scroll(0, y, (unsigned char *)s);
307 y++;
308 #if CONFIG_CHARGING == CHARGING_CONTROL
309 if (charge_state == CHARGING)
310 snprintf(s, sizeof(s), (char *)str(LANG_BATTERY_CHARGE));
311 else if (charge_state == TOPOFF)
312 snprintf(s, sizeof(s), (char *)str(LANG_BATTERY_TOPOFF_CHARGE));
313 else if (charge_state == TRICKLE)
314 snprintf(s, sizeof(s), (char *)str(LANG_BATTERY_TRICKLE_CHARGE));
315 else
316 #endif
317 if (battery_level() >= 0)
318 snprintf(s, sizeof(s), (char *)str(LANG_BATTERY_TIME), battery_level(),
319 battery_time() / 60, battery_time() % 60);
320 else
321 strncpy(s, "(n/a)", sizeof(s));
322 FOR_NB_SCREENS(i)
323 screens[i].puts_scroll(0, y, (unsigned char *)s);
324 y++;
327 #ifdef HAVE_LCD_CHARCELLS
328 if (page == 2)
329 #endif
331 #ifdef HAVE_MULTIVOLUME
332 output_dyn_value(s1, sizeof s1, free, kbyte_units, true);
333 output_dyn_value(s2, sizeof s2, size, kbyte_units, true);
334 snprintf(s, sizeof s, "%s %s/%s", str(LANG_DISK_NAME_INTERNAL),
335 s1, s2);
336 FOR_NB_SCREENS(i)
337 screens[i].puts_scroll(0, y, (unsigned char *)s);
338 y++;
340 if (size2) {
341 output_dyn_value(s1, sizeof s1, free2, kbyte_units, true);
342 output_dyn_value(s2, sizeof s2, size2, kbyte_units, true);
343 snprintf(s, sizeof s, "%s %s/%s", str(LANG_DISK_NAME_MMC),
344 s1, s2);
345 FOR_NB_SCREENS(i)
346 screens[i].puts_scroll(0, y, (unsigned char *)s);
347 y++;
349 #else
350 output_dyn_value(s1, sizeof s1, size, kbyte_units, true);
351 snprintf(s, sizeof s, SIZE_FMT, str(LANG_DISK_SIZE_INFO), s1);
352 FOR_NB_SCREENS(i)
353 screens[i].puts_scroll(0, y, (unsigned char *)s);
354 y++;
355 output_dyn_value(s1, sizeof s1, free, kbyte_units, true);
356 snprintf(s, sizeof s, SIZE_FMT, str(LANG_DISK_FREE_INFO), s1);
357 FOR_NB_SCREENS(i)
358 screens[i].puts_scroll(0, y, (unsigned char *)s);
359 y++;
360 #endif
363 FOR_NB_SCREENS(i)
364 screens[i].update();
366 /* Wait for a key to be pushed */
367 key = get_action(CONTEXT_MAINMENU,HZ*5);
368 switch(key) {
370 case ACTION_STD_CANCEL:
371 done = true;
372 break;
374 #ifdef HAVE_LCD_CHARCELLS
375 case ACTION_STD_NEXT:
376 page = (page+1)%3;
377 break;
378 case ACTION_STD_PREV:
379 page--;
380 if (page < 0)
381 page = 2;
382 break;
383 #endif
385 #ifndef SIMULATOR
386 case ACTION_STD_OK:
387 gui_syncsplash(0, str(LANG_SCANNING_DISK));
388 fat_recalc_free(IF_MV(0));
389 #ifdef HAVE_MULTIVOLUME
390 if (fat_ismounted(1))
391 fat_recalc_free(1);
392 #endif
393 new_info = true;
394 break;
395 #endif
397 default:
398 if (default_event_handler(key) == SYS_USB_CONNECTED)
399 return true;
400 break;
403 return false;
405 MENUITEM_FUNCTION(show_info_item, 0, ID2P(LANG_ROCKBOX_INFO),
406 (menu_function)show_info, NULL, NULL, Icon_NOICON);
409 /* sleep Menu */
410 static void sleep_timer_formatter(char* buffer, size_t buffer_size, int value,
411 const char* unit)
413 int minutes, hours;
415 (void) unit;
417 if (value) {
418 hours = value / 60;
419 minutes = value - (hours * 60);
420 snprintf(buffer, buffer_size, "%d:%02d", hours, minutes);
421 } else {
422 snprintf(buffer, buffer_size, "%s", str(LANG_OFF));
426 static void sleep_timer_set(int minutes)
428 set_sleep_timer(minutes * 60);
431 static int sleep_timer(void)
433 int minutes = (get_sleep_timer() + 59) / 60; /* round up */
434 return (int)set_int(str(LANG_SLEEP_TIMER), "", UNIT_MIN, &minutes,
435 &sleep_timer_set, -5, 300, 0, sleep_timer_formatter);
438 MENUITEM_FUNCTION(sleep_timer_call, 0, ID2P(LANG_SLEEP_TIMER), sleep_timer,
439 NULL, NULL, Icon_Menu_setting); /* make it look like a
440 setting to the user */
441 MENUITEM_FUNCTION(show_credits_item, 0, ID2P(LANG_VERSION),
442 (menu_function)show_credits, NULL, NULL, Icon_NOICON);
443 MENUITEM_FUNCTION(show_runtime_item, 0, ID2P(LANG_RUNNING_TIME),
444 (menu_function)view_runtime, NULL, NULL, Icon_NOICON);
445 MENUITEM_FUNCTION(debug_menu_item, 0, ID2P(LANG_DEBUG),
446 (menu_function)debug_menu, NULL, NULL, Icon_NOICON);
448 MAKE_MENU(info_menu, ID2P(LANG_SYSTEM), 0, Icon_Questionmark,
449 &show_info_item, &show_credits_item, &show_runtime_item,
450 &sleep_timer_call, &debug_menu_item);
451 /* INFO MENU */
452 /***********************************/
454 /***********************************/
455 /* MAIN MENU */
457 MENUITEM_FUNCTION(browse_themes, MENU_FUNC_USEPARAM, ID2P(LANG_CUSTOM_THEME),
458 browse_folder, (void*)&theme, NULL, Icon_Folder);
460 #ifdef HAVE_LCD_CHARCELLS
461 int mainmenu_callback(int action,const struct menu_item_ex *this_item)
463 (void)this_item;
464 switch (action)
466 case ACTION_ENTER_MENUITEM:
467 status_set_param(true);
468 break;
469 case ACTION_EXIT_MENUITEM:
470 status_set_param(false);
471 break;
473 return action;
475 #else
476 #define mainmenu_callback NULL
477 #endif
478 MAKE_MENU(main_menu_, ID2P(LANG_SETTINGS), mainmenu_callback,
479 Icon_Submenu_Entered,
480 &sound_settings,
481 &settings_menu_item, &manage_settings, &browse_themes,
482 #ifdef HAVE_RECORDING
483 &recording_settings,
484 #endif
486 /* MAIN MENU */
487 /***********************************/