rockbox/apps/menus/settings_menu.c
Christian Gmeiner 57c2a5fa5a add support to switch device driver at runtime
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14508 a1c6a512-1295-4272-9138-f99709370657
2007-08-29 11:55:23 +00:00

553 lines
17 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2007 Jonathan Gordon
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include <stdbool.h>
#include <stddef.h>
#include <limits.h>
#include <string.h>
#include "config.h"
#include "lang.h"
#include "action.h"
#include "settings.h"
#include "menu.h"
#include "sound_menu.h"
#include "exported_menus.h"
#include "tree.h"
#include "tagtree.h"
#include "usb.h"
#include "splash.h"
#include "talk.h"
#include "sprintf.h"
#include "powermgmt.h"
#ifdef HAVE_RTC_ALARM
#include "alarm_menu.h"
#endif
#if CONFIG_TUNER
#include "radio.h"
#endif
#ifdef HAVE_USBSTACK
#include "list.h"
#include "usbstack.h"
#include "statusbar.h"
#include "misc.h"
#endif
/***********************************/
/* TAGCACHE MENU */
#ifdef HAVE_TAGCACHE
static void tagcache_rebuild_with_splash(void)
{
tagcache_rebuild();
gui_syncsplash(HZ*2, ID2P(LANG_TAGCACHE_FORCE_UPDATE_SPLASH));
}
static void tagcache_update_with_splash(void)
{
tagcache_update();
gui_syncsplash(HZ*2, ID2P(LANG_TAGCACHE_FORCE_UPDATE_SPLASH));
}
#ifdef HAVE_TC_RAMCACHE
MENUITEM_SETTING(tagcache_ram, &global_settings.tagcache_ram, NULL);
#endif
MENUITEM_SETTING(tagcache_autoupdate, &global_settings.tagcache_autoupdate, NULL);
MENUITEM_FUNCTION(tc_init, 0, ID2P(LANG_TAGCACHE_FORCE_UPDATE),
(int(*)(void))tagcache_rebuild_with_splash,
NULL, NULL, Icon_NOICON);
MENUITEM_FUNCTION(tc_update, 0, ID2P(LANG_TAGCACHE_UPDATE),
(int(*)(void))tagcache_update_with_splash,
NULL, NULL, Icon_NOICON);
MENUITEM_SETTING(runtimedb, &global_settings.runtimedb, NULL);
MENUITEM_FUNCTION(tc_export, 0, ID2P(LANG_TAGCACHE_EXPORT),
(int(*)(void))tagtree_export, NULL,
NULL, Icon_NOICON);
MENUITEM_FUNCTION(tc_import, 0, ID2P(LANG_TAGCACHE_IMPORT),
(int(*)(void))tagtree_import, NULL,
NULL, Icon_NOICON);
MAKE_MENU(tagcache_menu, ID2P(LANG_TAGCACHE), 0, Icon_NOICON,
#ifdef HAVE_TC_RAMCACHE
&tagcache_ram,
#endif
&tagcache_autoupdate, &tc_init, &tc_update, &runtimedb,
&tc_export, &tc_import);
#endif /* HAVE_TAGCACHE */
/* TAGCACHE MENU */
/***********************************/
/***********************************/
/* FILE VIEW MENU */
static int fileview_callback(int action,const struct menu_item_ex *this_item);
MENUITEM_SETTING(sort_case, &global_settings.sort_case, NULL);
MENUITEM_SETTING(sort_dir, &global_settings.sort_dir, fileview_callback);
MENUITEM_SETTING(sort_file, &global_settings.sort_file, fileview_callback);
MENUITEM_SETTING(dirfilter, &global_settings.dirfilter, NULL);
MENUITEM_SETTING(show_filename_ext, &global_settings.show_filename_ext, NULL);
MENUITEM_SETTING(browse_current, &global_settings.browse_current, NULL);
MENUITEM_SETTING(show_path_in_browser, &global_settings.show_path_in_browser, NULL);
static int fileview_callback(int action,const struct menu_item_ex *this_item)
{
static int oldval;
int *variable = this_item->variable;
switch (action)
{
case ACTION_ENTER_MENUITEM: /* on entering an item */
oldval = *variable;
break;
case ACTION_EXIT_MENUITEM: /* on exit */
if (*variable != oldval)
reload_directory(); /* force reload if this has changed */
break;
}
return action;
}
MAKE_MENU(file_menu, ID2P(LANG_FILE), 0, Icon_file_view_menu,
&sort_case, &sort_dir, &sort_file,
&dirfilter, &show_filename_ext, &browse_current,
&show_path_in_browser);
/* FILE VIEW MENU */
/***********************************/
/***********************************/
/* SYSTEM MENU */
/* Battery */
#if BATTERY_CAPACITY_INC > 0
MENUITEM_SETTING(battery_capacity, &global_settings.battery_capacity, NULL);
#endif
#if BATTERY_TYPES_COUNT > 1
MENUITEM_SETTING(battery_type, &global_settings.battery_type, NULL);
#endif
#ifdef HAVE_USB_POWER
#if CONFIG_CHARGING
static int usbcharging_callback(int action,const struct menu_item_ex *this_item)
{
(void)this_item;
switch (action)
{
case ACTION_EXIT_MENUITEM: /* on exit */
usb_charging_enable(global_settings.usb_charging);
break;
}
return action;
}
MENUITEM_SETTING(usb_charging, &global_settings.usb_charging, usbcharging_callback);
#endif
#endif
MAKE_MENU(battery_menu, ID2P(LANG_BATTERY_MENU), 0, Icon_NOICON,
#if BATTERY_CAPACITY_INC > 0
&battery_capacity,
#endif
#if BATTERY_TYPES_COUNT > 1
&battery_type,
#endif
#ifdef HAVE_USB_POWER
#if CONFIG_CHARGING
&usb_charging,
#endif
#endif
);
/* Disk */
#ifndef HAVE_FLASH_STORAGE
MENUITEM_SETTING(disk_spindown, &global_settings.disk_spindown, NULL);
#endif
#ifdef HAVE_DIRCACHE
static int dircache_callback(int action,const struct menu_item_ex *this_item)
{
(void)this_item;
switch (action)
{
case ACTION_EXIT_MENUITEM: /* on exit */
switch (global_settings.dircache)
{
case true:
if (!dircache_is_enabled())
gui_syncsplash(HZ*2, ID2P(LANG_PLEASE_REBOOT));
break;
case false:
if (dircache_is_enabled())
dircache_disable();
break;
}
break;
}
return action;
}
MENUITEM_SETTING(dircache, &global_settings.dircache, dircache_callback);
#endif
#if defined(HAVE_DIRCACHE) || !defined(HAVE_FLASH_STORAGE)
MAKE_MENU(disk_menu, ID2P(LANG_DISK_MENU), 0, Icon_NOICON,
#ifndef HAVE_FLASH_STORAGE
&disk_spindown,
#endif
#ifdef HAVE_DIRCACHE
&dircache,
#endif
);
#endif
/* Time & Date */
#if CONFIG_RTC
static int timedate_set(void)
{
struct tm tm;
int result;
/* Make a local copy of the time struct */
memcpy(&tm, get_time(), sizeof(struct tm));
/* do some range checks */
/* This prevents problems with time/date setting after a power loss */
if (!valid_time(&tm))
{
/* Macros to convert a 2-digit string to a decimal constant.
(YEAR), MONTH and DAY are set by the date command, which outputs
DAY as 00..31 and MONTH as 01..12. The leading zero would lead to
misinterpretation as an octal constant. */
#define S100(x) 1 ## x
#define C2DIG2DEC(x) (S100(x)-100)
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
tm.tm_mday = C2DIG2DEC(DAY);
tm.tm_mon = C2DIG2DEC(MONTH)-1;
tm.tm_wday = 1;
tm.tm_year = YEAR-1900;
}
result = (int)set_time_screen(str(LANG_SET_TIME), &tm);
if(tm.tm_year != -1) {
set_time(&tm);
}
return result;
}
MENUITEM_FUNCTION(time_set, 0, ID2P(LANG_SET_TIME),
timedate_set, NULL, NULL, Icon_NOICON);
MENUITEM_SETTING(timeformat, &global_settings.timeformat, NULL);
MAKE_MENU(time_menu, ID2P(LANG_TIME_MENU), 0, Icon_NOICON, &time_set, &timeformat);
#endif
/* System menu */
MENUITEM_SETTING(poweroff, &global_settings.poweroff, NULL);
#ifdef HAVE_RTC_ALARM
MENUITEM_FUNCTION(alarm_screen_call, 0, ID2P(LANG_ALARM_MOD_ALARM_MENU),
(menu_function)alarm_screen, NULL, NULL, Icon_NOICON);
#if CONFIG_TUNER || defined(HAVE_RECORDING)
#if CONFIG_TUNER && !defined(HAVE_RECORDING)
/* This need only be shown if we dont have recording, because if we do
then always show the setting item, because there will always be at least
2 items */
static int alarm_callback(int action,const struct menu_item_ex *this_item)
{
(void)this_item;
switch (action)
{
case ACTION_REQUEST_MENUITEM:
if (radio_hardware_present() == 0)
return ACTION_EXIT_MENUITEM;
break;
}
return action;
}
#else
#define alarm_callback NULL
#endif /* CONFIG_TUNER && !HAVE_RECORDING */
/* have to do this manually because the setting screen
doesnt handle variable item count */
static int alarm_setting(void)
{
struct opt_items items[ALARM_START_COUNT];
int i = 0;
items[i].string = str(LANG_RESUME_PLAYBACK);
items[i].voice_id = LANG_RESUME_PLAYBACK;
i++;
#if CONFIG_TUNER
if (radio_hardware_present())
{
items[i].string = str(LANG_FM_RADIO);
items[i].voice_id = LANG_FM_RADIO;
i++;
}
#endif
#ifdef HAVE_RECORDING
items[i].string = str(LANG_RECORDING);
items[i].voice_id = LANG_RECORDING;
i++;
#endif
return set_option(str(LANG_ALARM_WAKEUP_SCREEN),
&global_settings.alarm_wake_up_screen,
INT, items, i, NULL);
}
MENUITEM_FUNCTION(alarm_wake_up_screen, 0, ID2P(LANG_ALARM_WAKEUP_SCREEN),
alarm_setting, NULL, alarm_callback, Icon_Menu_setting);
#endif /* CONFIG_TUNER || defined(HAVE_RECORDING) */
#endif /* HAVE_RTC_ALARM */
/* Limits menu */
MENUITEM_SETTING(max_files_in_dir, &global_settings.max_files_in_dir, NULL);
MENUITEM_SETTING(max_files_in_playlist, &global_settings.max_files_in_playlist, NULL);
MAKE_MENU(limits_menu, ID2P(LANG_LIMITS_MENU), 0, Icon_NOICON,
&max_files_in_dir, &max_files_in_playlist);
#if CONFIG_CODEC == MAS3507D
void dac_line_in(bool enable);
static int linein_callback(int action,const struct menu_item_ex *this_item)
{
(void)this_item;
switch (action)
{
case ACTION_EXIT_MENUITEM: /* on exit */
#ifndef SIMULATOR
dac_line_in(global_settings.line_in);
#endif
break;
}
return action;
}
MENUITEM_SETTING(line_in, &global_settings.line_in, linein_callback);
#endif
#if CONFIG_CHARGING
MENUITEM_SETTING(car_adapter_mode, &global_settings.car_adapter_mode, NULL);
#endif
MENUITEM_SETTING(start_screen, &global_settings.start_in_screen, NULL);
#ifdef HAVE_BUTTON_LIGHT
MENUITEM_SETTING(button_light_timeout, &global_settings.button_light_timeout, NULL);
#endif
#ifdef HAVE_BUTTONLIGHT_BRIGHTNESS
MENUITEM_SETTING(buttonlight_brightness, &global_settings.buttonlight_brightness, NULL);
#endif
MAKE_MENU(system_menu, ID2P(LANG_SYSTEM),
0, Icon_System_menu,
&start_screen,
#if (BATTERY_CAPACITY_INC > 0) || (BATTERY_TYPES_COUNT > 1)
&battery_menu,
#endif
#if defined(HAVE_DIRCACHE) || !defined(HAVE_FLASH_STORAGE)
&disk_menu,
#endif
#if CONFIG_RTC
&time_menu,
#endif
&poweroff,
#ifdef HAVE_RTC_ALARM
&alarm_screen_call,
#if defined(HAVE_RECORDING) || CONFIG_TUNER
&alarm_wake_up_screen,
#endif
#endif
&limits_menu,
#if CONFIG_CODEC == MAS3507D
&line_in,
#endif
#if CONFIG_CHARGING
&car_adapter_mode,
#endif
#ifdef HAVE_BUTTON_LIGHT
&button_light_timeout,
#endif
#ifdef HAVE_BUTTONLIGHT_BRIGHTNESS
&buttonlight_brightness
#endif
);
/* SYSTEM MENU */
/***********************************/
/***********************************/
/* BOOKMARK MENU */
static int bmark_callback(int action,const struct menu_item_ex *this_item)
{
(void)this_item;
switch (action)
{
case ACTION_EXIT_MENUITEM: /* on exit */
if(global_settings.autocreatebookmark == BOOKMARK_RECENT_ONLY_YES ||
global_settings.autocreatebookmark == BOOKMARK_RECENT_ONLY_ASK)
{
if(global_settings.usemrb == BOOKMARK_NO)
global_settings.usemrb = BOOKMARK_YES;
}
break;
}
return action;
}
MENUITEM_SETTING(autocreatebookmark,
&global_settings.autocreatebookmark, bmark_callback);
MENUITEM_SETTING(autoloadbookmark, &global_settings.autoloadbookmark, NULL);
MENUITEM_SETTING(usemrb, &global_settings.usemrb, NULL);
MAKE_MENU(bookmark_settings_menu, ID2P(LANG_BOOKMARK_SETTINGS), 0,
Icon_Bookmark,
&autocreatebookmark, &autoloadbookmark, &usemrb);
/* BOOKMARK MENU */
/***********************************/
/***********************************/
/* VOICE MENU */
static int talk_callback(int action,const struct menu_item_ex *this_item);
MENUITEM_SETTING(talk_menu_item, &global_settings.talk_menu, NULL);
MENUITEM_SETTING(talk_dir_item, &global_settings.talk_dir, NULL);
MENUITEM_SETTING(talk_dir_clip_item, &global_settings.talk_dir_clip, talk_callback);
MENUITEM_SETTING(talk_file_item, &global_settings.talk_file, NULL);
MENUITEM_SETTING(talk_file_clip_item, &global_settings.talk_file_clip, talk_callback);
static int talk_callback(int action,const struct menu_item_ex *this_item)
{
static int oldval = 0;
switch (action)
{
case ACTION_ENTER_MENUITEM:
oldval = global_settings.talk_file_clip;
break;
case ACTION_EXIT_MENUITEM:
#if CONFIG_CODEC == SWCODEC
audio_set_crossfade(global_settings.crossfade);
#endif
if (this_item == &talk_dir_clip_item)
break;
if (!oldval && global_settings.talk_file_clip)
{
/* force reload if newly talking thumbnails,
because the clip presence is cached only if enabled */
reload_directory();
}
break;
}
return action;
}
MAKE_MENU(voice_settings_menu, ID2P(LANG_VOICE), 0, Icon_Voice,
&talk_menu_item, &talk_dir_item, &talk_dir_clip_item,
&talk_file_item, &talk_file_clip_item);
/* VOICE MENU */
/***********************************/
#ifdef HAVE_USBSTACK
/***********************************/
/* USB STACK MENU */
char drivers[16][32];
static char* usb_menu_getname(int item, void * data, char *buffer)
{
(void)data; (void)buffer;
return drivers[item];
}
int usbdriver_menuitem(void)
{
struct gui_synclist lists;
int action, count = 0;
char *s = device_driver_names, *e;
do {
e = strchr(s, ',');
if (e)
{
strncpy(drivers[count++], s, e-s);
s = e+1;
}
} while (e && count < 16);
if (count < 16)
strcpy(drivers[count++], s);
for (action=0; action<count; action++)
{
if (!strcmp(drivers[action],
global_settings.usb_stack_device_driver))
break;
}
gui_synclist_init(&lists, usb_menu_getname, drivers, false, 1);
gui_synclist_set_title(&lists, str(LANG_USBSTACK_DEVICE_DRIVER), NOICON);
gui_synclist_set_icon_callback(&lists, NULL);
gui_synclist_set_nb_items(&lists, count);
gui_synclist_select_item(&lists, action==count?0:action);
gui_synclist_draw(&lists);
while(1)
{
gui_syncstatusbar_draw(&statusbars, true);
action = get_action(CONTEXT_STD, HZ/5);
if (gui_synclist_do_button(&lists, action, LIST_WRAP_UNLESS_HELD))
continue;
if (action == ACTION_STD_CANCEL)
{
/* setting was canceled */
break;
}
else if (action == ACTION_STD_OK)
{
/* setting was accepted... save */
strcpy(global_settings.usb_stack_device_driver,
drivers[gui_synclist_get_sel_pos(&lists)]);
/* switch device driver */
usb_device_driver_bind(drivers[gui_synclist_get_sel_pos(&lists)]);
break;
}
else if (action == ACTION_REDRAW)
gui_synclist_draw(&lists);
else if(default_event_handler(action) == SYS_USB_CONNECTED)
return true;
}
return false;
}
MENUITEM_SETTING(usbstack_mode, &global_settings.usb_stack_mode, NULL);
MENUITEM_FUNCTION(usbdriver, 0, ID2P(LANG_USBSTACK_DEVICE_DRIVER),
usbdriver_menuitem, 0, NULL, Icon_NOICON);
MAKE_MENU(usbstack_menu, ID2P(LANG_USBSTACK), 0, Icon_NOICON,
&usbstack_mode, &usbdriver);
/* USB STACK MENU */
/***********************************/
#endif
/***********************************/
/***********************************/
/* SETTINGS MENU */
static int language_browse(void)
{
return (int)rockbox_browse(LANG_DIR, SHOW_LNG);
}
MENUITEM_FUNCTION(browse_langs, 0, ID2P(LANG_LANGUAGE), language_browse,
NULL, NULL, Icon_Language);
MAKE_MENU(settings_menu_item, ID2P(LANG_GENERAL_SETTINGS), 0,
Icon_General_settings_menu,
&playback_menu_item, &playlist_settings, &file_menu,
#ifdef HAVE_TAGCACHE
&tagcache_menu,
#endif
&display_menu, &system_menu,
&bookmark_settings_menu, &browse_langs, &voice_settings_menu
#ifdef HAVE_USBSTACK
, &usbstack_menu
#endif
);
/* SETTINGS MENU */
/***********************************/