Fixed a bug in the multi-screen menus, the statusbar wasn't refreshed when coming from some custom wps that erases it ; Initial support for options in the menus

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7747 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Kevin Ferrare 2005-11-04 07:18:36 +00:00
parent 12a4ba0d76
commit cbbdc95d9c
5 changed files with 413 additions and 253 deletions

View file

@ -37,6 +37,7 @@ gui/buttonbar.c
gui/icon.c gui/icon.c
gui/list.c gui/list.c
gui/scrollbar.c gui/scrollbar.c
gui/select.c
gui/splash.c gui/splash.c
gui/statusbar.c gui/statusbar.c
gui/textarea.c gui/textarea.c

143
apps/gui/select.c Normal file
View file

@ -0,0 +1,143 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2005 by Kevin Ferrare
*
* 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 "select.h"
#include "lang.h"
#include "textarea.h"
#include "sprintf.h"
#include "kernel.h"
#include "screen_access.h"
void gui_select_init_numeric(struct gui_select * select,
const char * title,
int init_value,
int min_value,
int max_value,
int step,
const char * unit,
void (*formatter)(char* dest,
int dest_length,
int variable,
const char* unit)
)
{
select->canceled=false;
select->validated=false;
select->title=title;
select->min_value=min_value;
select->max_value=max_value;
select->option=init_value;
select->step=step;
select->extra_string=unit;
select->formatter=formatter;
select->items=NULL;
}
void gui_select_init_items(struct gui_select * select,
const char * title,
int selected,
const struct opt_items * items,
int nb_items)
{
select->canceled=false;
select->validated=false;
select->title=title;
select->min_value=0;
select->max_value=nb_items;
select->option=selected;
select->step=1;
select->formatter=NULL;
select->items=items;
}
//FIXME: si step>1, mettre d'abord au plus grand, ensuite passerau plus petit
void gui_select_next(struct gui_select * select)
{
select->option+=select->step;
if(select->option >= select->max_value)
select->option=select->min_value;
}
void gui_select_prev(struct gui_select * select)
{
select->option-=select->step;
if(select->option < select->min_value)
select->option=select->max_value-1;
}
void gui_select_draw(struct gui_select * select, struct screen * display)
{
screen_set_xmargin(display, 0);
gui_textarea_clear(display);
display->puts_scroll(0, 0, select->title);
if(gui_select_is_canceled(select))
display->puts_scroll(0, 0, str(LANG_MENU_SETTING_CANCEL));
if(select->items)
display->puts_scroll(0, 1, P2STR(select->items[select->option].string));
else
{
char buffer[30];
if(!select->formatter)
snprintf(buffer, sizeof buffer,"%d %s", select->option, select->extra_string);
else
select->formatter(buffer, sizeof buffer, select->option, select->extra_string);
display->puts_scroll(0, 1, buffer);
}
gui_textarea_update(display);
}
void gui_syncselect_draw(struct gui_select * select)
{
int i;
for(i=0;i<NB_SCREENS;i++)
gui_select_draw(select, &(screens[i]));
}
bool gui_syncselect_do_button(struct gui_select * select, int button)
{
bool moved=false;
switch(button)
{
case SELECT_INC :
case SELECT_INC | BUTTON_REPEAT :
gui_select_next(select);
moved=true;
break;
case SELECT_DEC :
case SELECT_DEC | BUTTON_REPEAT :
gui_select_prev(select);
moved=true;
break;
case SELECT_OK :
#ifdef SELECT_OK2
case SELECT_OK2 :
#endif
gui_select_validate(select);
break;
case SELECT_CANCEL :
case SELECT_CANCEL2 :
gui_select_cancel(select);
gui_syncselect_draw(select);
sleep(HZ/2);
break;
}
return(moved);
}

130
apps/gui/select.h Normal file
View file

@ -0,0 +1,130 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2005 by Kevin Ferrare
*
* 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.
*
****************************************************************************/
#ifndef _GUI_SELECT_H_
#define _GUI_SELECT_H_
#include "screen_access.h"
#include "settings.h"
#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
(CONFIG_KEYPAD == IRIVER_H300_PAD)
#define SELECT_INC BUTTON_UP
#define SELECT_DEC BUTTON_DOWN
#define SELECT_OK BUTTON_SELECT
#define SELECT_OK2 BUTTON_LEFT
#define SELECT_CANCEL BUTTON_OFF
#define SELECT_CANCEL2 BUTTON_MODE
#elif CONFIG_KEYPAD == RECORDER_PAD
#define SELECT_INC BUTTON_UP
#define SELECT_DEC BUTTON_DOWN
#define SELECT_OK BUTTON_PLAY
#define SELECT_OK2 BUTTON_LEFT
#define SELECT_CANCEL BUTTON_OFF
#define SELECT_CANCEL2 BUTTON_F1
#elif CONFIG_KEYPAD == PLAYER_PAD
#define SELECT_INC BUTTON_RIGHT
#define SELECT_DEC BUTTON_LEFT
#define SELECT_OK BUTTON_PLAY
#define SELECT_CANCEL BUTTON_STOP
#define SELECT_CANCEL2 BUTTON_MENU
#elif CONFIG_KEYPAD == ONDIO_PAD
#define SELECT_INC BUTTON_UP
#define SELECT_DEC BUTTON_DOWN
#define SELECT_OK BUTTON_RIGHT
#define SELECT_OK2 BUTTON_LEFT
#define SELECT_CANCEL BUTTON_MENU
#define SELECT_CANCEL2 BUTTON_OFF
#elif CONFIG_KEYPAD == GMINI100_PAD
#define SELECT_INC BUTTON_UP
#define SELECT_DEC BUTTON_DOWN
#define SELECT_OK BUTTON_PLAY
#define SELECT_OK2 BUTTON_LEFT
#define SELECT_CANCEL BUTTON_OFF
#define SELECT_CANCEL2 BUTTON_MENU
#endif
struct gui_select
{
bool canceled;
bool validated;
const char * title;
int min_value;
int max_value;
int step;
int option;
const char * extra_string;
/* In the case the option is a number */
void (*formatter)(char* dest,
int dest_length,
int variable,
const char* unit);
const struct opt_items * items;
};
extern void gui_select_init_numeric(struct gui_select * select,
const char * title,
int init_value,
int min_value,
int max_value,
int step,
const char * unit,
void (*formatter)(char* dest,
int dest_length,
int variable,
const char* unit));
extern void gui_select_init_items(struct gui_select * select,
const char * title,
int selected,
const struct opt_items * items,
int nb_items
);
extern void gui_select_next(struct gui_select * select);
extern void gui_select_prev(struct gui_select * select);
extern void gui_select_draw(struct gui_select * select, struct screen * display);
#define gui_select_get_selected(select) \
(select)->option
#define gui_select_cancel(select) \
(select)->canceled=true
#define gui_select_is_canceled(select) \
(select)->canceled
#define gui_select_validate(select) \
(select)->validated=true
#define gui_select_is_validated(select) \
(select)->validated
extern void gui_syncselect_draw(struct gui_select * select);
extern bool gui_syncselect_do_button(struct gui_select * select, int button);
#endif /* _GUI_SELECT_H_ */

View file

@ -125,6 +125,7 @@ int menu_show(int m)
int key; int key;
gui_synclist_draw(&(menus[m].synclist)); gui_synclist_draw(&(menus[m].synclist));
gui_syncstatusbar_draw(&statusbars, true);
menu_talk_selected(m); menu_talk_selected(m);
while (!exit) { while (!exit) {
key = button_get_w_tmo(HZ/2); key = button_get_w_tmo(HZ/2);

View file

@ -68,6 +68,8 @@
#include "rtc.h" #include "rtc.h"
#include "sound.h" #include "sound.h"
#include "dircache.h" #include "dircache.h"
#include "select.h"
#include "statusbar.h"
#if CONFIG_CODEC == MAS3507D #if CONFIG_CODEC == MAS3507D
void dac_line_in(bool enable); void dac_line_in(bool enable);
@ -112,7 +114,7 @@ struct bit_entry
/* store position in global_settings struct */ /* store position in global_settings struct */
short settings_offset; /* min 9 bit, better 10 */ short settings_offset; /* min 9 bit, better 10 */
/* default value */ /* default value */
int default_val; /* min 15 bit */ int default_val; /* min 15 bit */
/* variable name in a .cfg file, NULL if not to be saved */ /* variable name in a .cfg file, NULL if not to be saved */
const char* cfg_name; const char* cfg_name;
/* set of values, or NULL for a numerical value */ /* set of values, or NULL for a numerical value */
@ -135,7 +137,7 @@ offset abs
Config memory is reset to 0xff and initialized with 'factory defaults' if Config memory is reset to 0xff and initialized with 'factory defaults' if
a valid header & checksum is not found. Config version number is only a valid header & checksum is not found. Config version number is only
increased when information is _relocated_ or space is _reused_ so that old increased when information is _relocated_ or space is _reused_ so that old
versions can read and modify configuration changed by new versions. versions can read and modify configuration changed by new versions.
Memory locations not used by a given version should not be Memory locations not used by a given version should not be
modified unless the header & checksum test fails. modified unless the header & checksum test fails.
@ -150,8 +152,8 @@ Rest of config block, only saved to disk:
*************************************/ *************************************/
/* The persistence of the global_settings members is now controlled by /* The persistence of the global_settings members is now controlled by
the two tables below, rtc_bits and hd_bits. the two tables below, rtc_bits and hd_bits.
New values can just be added to the end, it will be backwards New values can just be added to the end, it will be backwards
compatible. If you however change order, bitsize, etc. of existing compatible. If you however change order, bitsize, etc. of existing
entries, you need to bump CONFIG_BLOCK_VERSION to break compatibility. entries, you need to bump CONFIG_BLOCK_VERSION to break compatibility.
*/ */
@ -176,7 +178,7 @@ static const char trig_durations_conf [] =
"0s,1s,2s,5s,10s,15s,20s,25s,30s,1min,2min,5min,10min"; "0s,1s,2s,5s,10s,15s,20s,25s,30s,1min,2min,5min,10min";
#endif #endif
/* the part of the settings which ends up in the RTC RAM, where available /* the part of the settings which ends up in the RTC RAM, where available
(those we either need early, save frequently, or without spinup) */ (those we either need early, save frequently, or without spinup) */
static const struct bit_entry rtc_bits[] = static const struct bit_entry rtc_bits[] =
{ {
@ -214,7 +216,7 @@ static const struct bit_entry rtc_bits[] =
{6, S_O(contrast), 40, "contrast", NULL }, {6, S_O(contrast), 40, "contrast", NULL },
#ifdef CONFIG_BACKLIGHT #ifdef CONFIG_BACKLIGHT
#ifdef HAVE_CHARGING #ifdef HAVE_CHARGING
{1, S_O(backlight_on_when_charging), false, {1, S_O(backlight_on_when_charging), false,
"backlight when plugged", off_on }, "backlight when plugged", off_on },
#endif #endif
{5, S_O(backlight_timeout), 5, "backlight timeout", {5, S_O(backlight_timeout), 5, "backlight timeout",
@ -240,9 +242,9 @@ static const struct bit_entry rtc_bits[] =
"idle poweroff", "off,1,2,3,4,5,6,7,8,9,10,15,30,45,60" }, "idle poweroff", "off,1,2,3,4,5,6,7,8,9,10,15,30,45,60" },
{18, S_O(runtime), 0, NULL, NULL }, {18, S_O(runtime), 0, NULL, NULL },
{18, S_O(topruntime), 0, NULL, NULL }, {18, S_O(topruntime), 0, NULL, NULL },
{15, S_O(max_files_in_playlist), 10000, {15, S_O(max_files_in_playlist), 10000,
"max files in playlist", NULL }, /* 1000...20000 */ "max files in playlist", NULL }, /* 1000...20000 */
{14, S_O(max_files_in_dir), 400, {14, S_O(max_files_in_dir), 400,
"max files in dir", NULL }, /* 50...10000 */ "max files in dir", NULL }, /* 50...10000 */
/* battery */ /* battery */
{12, S_O(battery_capacity), BATTERY_CAPACITY_MIN, "battery capacity", {12, S_O(battery_capacity), BATTERY_CAPACITY_MIN, "battery capacity",
@ -313,7 +315,7 @@ static const struct bit_entry hd_bits[] =
/* more playback */ /* more playback */
{1, S_O(play_selected), true, "play selected", off_on }, {1, S_O(play_selected), true, "play selected", off_on },
{1, S_O(fade_on_stop), true, "volume fade", off_on }, {1, S_O(fade_on_stop), true, "volume fade", off_on },
{4, S_O(ff_rewind_min_step), FF_REWIND_1000, {4, S_O(ff_rewind_min_step), FF_REWIND_1000,
"scan min step", "1,2,3,4,5,6,8,10,15,20,25,30,45,60" }, "scan min step", "1,2,3,4,5,6,8,10,15,20,25,30,45,60" },
{4, S_O(ff_rewind_accel), 3, "scan accel", NULL }, {4, S_O(ff_rewind_accel), 3, "scan accel", NULL },
#if CONFIG_CODEC == SWCODEC #if CONFIG_CODEC == SWCODEC
@ -330,7 +332,7 @@ static const struct bit_entry hd_bits[] =
{8, S_O(disk_spindown), 5, "disk spindown", NULL }, {8, S_O(disk_spindown), 5, "disk spindown", NULL },
#endif /* HAVE_MMC */ #endif /* HAVE_MMC */
/* browser */ /* browser */
{3, S_O(dirfilter), SHOW_SUPPORTED, {3, S_O(dirfilter), SHOW_SUPPORTED,
"show files", "all,supported,music,playlists,id3 database" }, "show files", "all,supported,music,playlists,id3 database" },
{1, S_O(sort_case), false, "sort case", off_on }, {1, S_O(sort_case), false, "sort case", off_on },
{1, S_O(browse_current), true, "follow playlist", off_on }, {1, S_O(browse_current), true, "follow playlist", off_on },
@ -338,16 +340,16 @@ static const struct bit_entry hd_bits[] =
{1, S_O(playlist_viewer_icons), true, "playlist viewer icons", off_on }, {1, S_O(playlist_viewer_icons), true, "playlist viewer icons", off_on },
{1, S_O(playlist_viewer_indices), true, {1, S_O(playlist_viewer_indices), true,
"playlist viewer indices", off_on }, "playlist viewer indices", off_on },
{1, S_O(playlist_viewer_track_display), 0, {1, S_O(playlist_viewer_track_display), 0,
"playlist viewer track display", "track name,full path" }, "playlist viewer track display", "track name,full path" },
{2, S_O(recursive_dir_insert), RECURSE_OFF, {2, S_O(recursive_dir_insert), RECURSE_OFF,
"recursive directory insert", off_on_ask }, "recursive directory insert", off_on_ask },
/* bookmarks */ /* bookmarks */
{3, S_O(autocreatebookmark), BOOKMARK_NO, "autocreate bookmarks", {3, S_O(autocreatebookmark), BOOKMARK_NO, "autocreate bookmarks",
"off,on,ask,recent only - on,recent only - ask" }, "off,on,ask,recent only - on,recent only - ask" },
{2, S_O(autoloadbookmark), BOOKMARK_NO, {2, S_O(autoloadbookmark), BOOKMARK_NO,
"autoload bookmarks", off_on_ask }, "autoload bookmarks", off_on_ask },
{2, S_O(usemrb), BOOKMARK_NO, {2, S_O(usemrb), BOOKMARK_NO,
"use most-recent-bookmarks", "off,on,unique only" }, "use most-recent-bookmarks", "off,on,unique only" },
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
/* peak meter */ /* peak meter */
@ -424,7 +426,7 @@ static const struct bit_entry hd_bits[] =
{3, S_O(backlight_fade_out), 3, "backlight fade out", {3, S_O(backlight_fade_out), 3, "backlight fade out",
"off,500ms,1s,2s,3s,4s,5s,10s"}, "off,500ms,1s,2s,3s,4s,5s,10s"},
#endif #endif
#ifdef HAVE_SPDIF_POWER #ifdef HAVE_SPDIF_POWER
{1, S_O(spdif_enable), false, "spdif enable", off_on}, {1, S_O(spdif_enable), false, "spdif enable", off_on},
#endif #endif
@ -435,7 +437,7 @@ static const struct bit_entry hd_bits[] =
#if CONFIG_CODEC == SWCODEC #if CONFIG_CODEC == SWCODEC
{2, S_O(crossfade), 0, "crossfade type", "off,crossfade,mix"}, {2, S_O(crossfade), 0, "crossfade type", "off,crossfade,mix"},
{1, S_O(replaygain), false, "replaygain", off_on }, {1, S_O(replaygain), false, "replaygain", off_on },
{2, S_O(replaygain_type), REPLAYGAIN_ALBUM, "replaygain type", {2, S_O(replaygain_type), REPLAYGAIN_ALBUM, "replaygain type",
"track,album,track shuffle" }, "track,album,track shuffle" },
{1, S_O(replaygain_noclip), false, "replaygain noclip", off_on }, {1, S_O(replaygain_noclip), false, "replaygain noclip", off_on },
{8 | SIGNED, S_O(replaygain_preamp), 0, "replaygain preamp", NULL }, {8 | SIGNED, S_O(replaygain_preamp), 0, "replaygain preamp", NULL },
@ -445,7 +447,7 @@ static const struct bit_entry hd_bits[] =
{1, S_O(dircache), false, "dircache", off_on }, {1, S_O(dircache), false, "dircache", off_on },
{22, S_O(dircache_size), 0, NULL, NULL }, {22, S_O(dircache_size), 0, NULL, NULL },
#endif #endif
/* If values are just added to the end, no need to bump the version. */ /* If values are just added to the end, no need to bump the version. */
/* new stuff to be added at the end */ /* new stuff to be added at the end */
@ -490,7 +492,7 @@ static void set_bits(
mask <<= bit_index; mask <<= bit_index;
if (bit_index + size > 32) if (bit_index + size > 32)
p[long_index+1] = p[long_index+1] =
(p[long_index+1] & (0xFFFFFFFF << (bit_index + size - 32))) (p[long_index+1] & (0xFFFFFFFF << (bit_index + size - 32)))
| (value >> (32 - bit_index)); | (value >> (32 - bit_index));
@ -506,7 +508,7 @@ static unsigned short calculate_config_checksum(const unsigned char* buf)
unsigned int i; unsigned int i;
unsigned char cksum[2]; unsigned char cksum[2];
cksum[0] = cksum[1] = 0; cksum[0] = cksum[1] = 0;
for (i=0; i < RTC_BLOCK_SIZE - 2; i+=2 ) { for (i=0; i < RTC_BLOCK_SIZE - 2; i+=2 ) {
cksum[0] ^= buf[i]; cksum[0] ^= buf[i];
cksum[1] ^= buf[i+1]; cksum[1] ^= buf[i+1];
@ -521,7 +523,7 @@ static unsigned short calculate_config_checksum(const unsigned char* buf)
static void init_config_buffer( void ) static void init_config_buffer( void )
{ {
DEBUGF( "init_config_buffer()\n" ); DEBUGF( "init_config_buffer()\n" );
/* reset to 0 - all unused */ /* reset to 0 - all unused */
memset(config_block, 0, CONFIG_BLOCK_SIZE); memset(config_block, 0, CONFIG_BLOCK_SIZE);
/* insert header */ /* insert header */
@ -546,7 +548,7 @@ static int save_config_buffer( void )
config_block[ RTC_BLOCK_SIZE - 2 ] = chksum >> 8; config_block[ RTC_BLOCK_SIZE - 2 ] = chksum >> 8;
config_block[ RTC_BLOCK_SIZE - 1 ] = chksum & 0xff; config_block[ RTC_BLOCK_SIZE - 1 ] = chksum & 0xff;
#ifdef HAVE_RTC #ifdef HAVE_RTC
/* FIXME: okay, it _would_ be cleaner and faster to implement rtc_write so /* FIXME: okay, it _would_ be cleaner and faster to implement rtc_write so
that it would write a number of bytes at a time since the RTC chip that it would write a number of bytes at a time since the RTC chip
supports that, but this will have to do for now 8-) */ supports that, but this will have to do for now 8-) */
@ -577,7 +579,7 @@ static int load_config_buffer(int which)
unsigned short chksum; unsigned short chksum;
bool correct = false; bool correct = false;
DEBUGF( "load_config_buffer()\n" ); DEBUGF( "load_config_buffer()\n" );
if (which & SETTINGS_HD) if (which & SETTINGS_HD)
@ -586,7 +588,7 @@ static int load_config_buffer(int which)
ata_read_sectors(IF_MV2(0,) config_sector, 1, config_block); ata_read_sectors(IF_MV2(0,) config_sector, 1, config_block);
/* calculate the checksum, check it and the header */ /* calculate the checksum, check it and the header */
chksum = calculate_config_checksum(config_block); chksum = calculate_config_checksum(config_block);
if (config_block[0] == 'R' && if (config_block[0] == 'R' &&
config_block[1] == 'o' && config_block[1] == 'o' &&
config_block[2] == 'c' && config_block[2] == 'c' &&
@ -600,7 +602,7 @@ static int load_config_buffer(int which)
} }
} }
#ifdef HAVE_RTC #ifdef HAVE_RTC
if(!correct) if(!correct)
{ {
/* If the disk sector was incorrect, reinit the buffer */ /* If the disk sector was incorrect, reinit the buffer */
@ -617,7 +619,7 @@ static int load_config_buffer(int which)
rtc_block[i] = rtc_read(0x14+i); rtc_block[i] = rtc_read(0x14+i);
chksum = calculate_config_checksum(rtc_block); chksum = calculate_config_checksum(rtc_block);
/* if rtc block is ok, use that */ /* if rtc block is ok, use that */
if (rtc_block[0] == 'R' && if (rtc_block[0] == 'R' &&
rtc_block[1] == 'o' && rtc_block[1] == 'o' &&
@ -631,7 +633,7 @@ static int load_config_buffer(int which)
} }
} }
#endif #endif
if ( !correct ) { if ( !correct ) {
/* if checksum is not valid, clear the config buffer */ /* if checksum is not valid, clear the config buffer */
DEBUGF( "load_config_buffer: header & checksum test failed\n" ); DEBUGF( "load_config_buffer: header & checksum test failed\n" );
@ -644,7 +646,7 @@ static int load_config_buffer(int which)
/* helper to save content of global_settings into a bitfield, /* helper to save content of global_settings into a bitfield,
as described per table */ as described per table */
static void save_bit_table(const struct bit_entry* p_table, int count, int bitstart) static void save_bit_table(const struct bit_entry* p_table, int count, int bitstart)
{ {
unsigned long* p_bitfield = (unsigned long*)config_block; /* 32 bit addr. */ unsigned long* p_bitfield = (unsigned long*)config_block; /* 32 bit addr. */
@ -682,7 +684,7 @@ static void save_bit_table(const struct bit_entry* p_table, int count, int bitst
/* /*
* figure out the config sector from the partition table and the * figure out the config sector from the partition table and the
* mounted file system * mounted file system
*/ */
void settings_calc_config_sector(void) void settings_calc_config_sector(void)
{ {
@ -705,7 +707,7 @@ void settings_calc_config_sector(void)
if (sector < 0) if (sector < 0)
sector = 0; sector = 0;
} }
config_sector = sector; config_sector = sector;
#endif #endif
} }
@ -753,8 +755,8 @@ int settings_save( void )
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
/** /**
* Applies the range infos stored in global_settings to * Applies the range infos stored in global_settings to
* the peak meter. * the peak meter.
*/ */
void settings_apply_pm_range(void) void settings_apply_pm_range(void)
{ {
@ -762,13 +764,13 @@ void settings_apply_pm_range(void)
/* depending on the scale mode (dBfs or percent) the values /* depending on the scale mode (dBfs or percent) the values
of global_settings.peak_meter_dbfs have different meanings */ of global_settings.peak_meter_dbfs have different meanings */
if (global_settings.peak_meter_dbfs) if (global_settings.peak_meter_dbfs)
{ {
/* convert to dBfs * 100 */ /* convert to dBfs * 100 */
pm_min = -(((int)global_settings.peak_meter_min) * 100); pm_min = -(((int)global_settings.peak_meter_min) * 100);
pm_max = -(((int)global_settings.peak_meter_max) * 100); pm_max = -(((int)global_settings.peak_meter_max) * 100);
} }
else else
{ {
/* percent is stored directly -> no conversion */ /* percent is stored directly -> no conversion */
pm_min = global_settings.peak_meter_min; pm_min = global_settings.peak_meter_min;
@ -807,7 +809,7 @@ void settings_apply(void)
sound_settings_apply(); sound_settings_apply();
audio_set_buffer_margin(global_settings.buffer_margin); audio_set_buffer_margin(global_settings.buffer_margin);
lcd_set_contrast(global_settings.contrast); lcd_set_contrast(global_settings.contrast);
lcd_scroll_speed(global_settings.scroll_speed); lcd_scroll_speed(global_settings.scroll_speed);
#ifdef HAVE_REMOTE_LCD #ifdef HAVE_REMOTE_LCD
@ -846,11 +848,11 @@ void settings_apply(void)
lcd_update(); /* refresh after flipping the screen */ lcd_update(); /* refresh after flipping the screen */
settings_apply_pm_range(); settings_apply_pm_range();
peak_meter_init_times( peak_meter_init_times(
global_settings.peak_meter_release, global_settings.peak_meter_hold, global_settings.peak_meter_release, global_settings.peak_meter_hold,
global_settings.peak_meter_clip_hold); global_settings.peak_meter_clip_hold);
#endif #endif
if ( global_settings.wps_file[0] && if ( global_settings.wps_file[0] &&
global_settings.wps_file[0] != 0xff ) { global_settings.wps_file[0] != 0xff ) {
snprintf(buf, sizeof buf, ROCKBOX_DIR "/%s.wps", snprintf(buf, sizeof buf, ROCKBOX_DIR "/%s.wps",
global_settings.wps_file); global_settings.wps_file);
@ -930,15 +932,15 @@ static void load_bit_table(const struct bit_entry* p_table, int count, int bitst
switch(p_run->byte_size) switch(p_run->byte_size)
{ {
case 1: case 1:
((unsigned char*)&global_settings)[p_run->settings_offset] = ((unsigned char*)&global_settings)[p_run->settings_offset] =
(unsigned char)value; (unsigned char)value;
break; break;
case 2: case 2:
((unsigned short*)&global_settings)[p_run->settings_offset/2] = ((unsigned short*)&global_settings)[p_run->settings_offset/2] =
(unsigned short)value; (unsigned short)value;
break; break;
case 4: case 4:
((unsigned int*)&global_settings)[p_run->settings_offset/4] = ((unsigned int*)&global_settings)[p_run->settings_offset/4] =
(unsigned int)value; (unsigned int)value;
break; break;
default: default:
@ -958,7 +960,7 @@ void settings_load(int which)
/* load the buffer from the RTC (resets it to all-unused if the block /* load the buffer from the RTC (resets it to all-unused if the block
is invalid) and decode the settings which are set in the block */ is invalid) and decode the settings which are set in the block */
if (!load_config_buffer(which)) if (!load_config_buffer(which))
{ {
/* load scalar values from RTC and HD sector, specified via table */ /* load scalar values from RTC and HD sector, specified via table */
if (which & SETTINGS_RTC) if (which & SETTINGS_RTC)
@ -970,7 +972,7 @@ void settings_load(int which)
load_bit_table(hd_bits, sizeof(hd_bits)/sizeof(hd_bits[0]), load_bit_table(hd_bits, sizeof(hd_bits)/sizeof(hd_bits[0]),
RTC_BLOCK_SIZE*8); RTC_BLOCK_SIZE*8);
} }
if ( global_settings.contrast < MIN_CONTRAST_SETTING ) if ( global_settings.contrast < MIN_CONTRAST_SETTING )
global_settings.contrast = lcd_default_contrast(); global_settings.contrast = lcd_default_contrast();
@ -999,11 +1001,11 @@ void set_file(char* filename, char* setting, int maxlen)
extlen++; extlen++;
ptr--; ptr--;
} }
if (strncasecmp(ROCKBOX_DIR, filename ,strlen(ROCKBOX_DIR)) || if (strncasecmp(ROCKBOX_DIR, filename ,strlen(ROCKBOX_DIR)) ||
(len-extlen > maxlen)) (len-extlen > maxlen))
return; return;
strncpy(setting, fptr, len-extlen); strncpy(setting, fptr, len-extlen);
setting[len-extlen]=0; setting[len-extlen]=0;
@ -1011,7 +1013,7 @@ void set_file(char* filename, char* setting, int maxlen)
} }
/* helper to sort a .cfg file entry into a global_settings member, /* helper to sort a .cfg file entry into a global_settings member,
as described per table. Returns the position if found, else 0. */ as described per table. Returns the position if found, else 0. */
static int load_cfg_table( static int load_cfg_table(
const struct bit_entry* p_table, /* the table which describes the entries */ const struct bit_entry* p_table, /* the table which describes the entries */
int count, /* number of entries in the table, including the first */ int count, /* number of entries in the table, including the first */
@ -1035,9 +1037,9 @@ static int load_cfg_table(
const char* item; const char* item;
const char* run; const char* run;
int len = strlen(value); int len = strlen(value);
item = run = p_table[i].cfg_val; item = run = p_table[i].cfg_val;
while(1) while(1)
{ {
/* count the length of the field */ /* count the length of the field */
@ -1046,7 +1048,7 @@ static int load_cfg_table(
if (!strncasecmp(value, item, MAX(run-item, len))) if (!strncasecmp(value, item, MAX(run-item, len)))
break; /* match, exit the search */ break; /* match, exit the search */
if (*run == '\0') /* reached the end of the choices */ if (*run == '\0') /* reached the end of the choices */
return i; /* return the position, but don't update */ return i; /* return the position, but don't update */
@ -1055,20 +1057,20 @@ static int load_cfg_table(
item = run; item = run;
} }
} }
/* could do a memcpy, but that would be endian-dependent */ /* could do a memcpy, but that would be endian-dependent */
switch(p_table[i].byte_size) switch(p_table[i].byte_size)
{ {
case 1: case 1:
((unsigned char*)&global_settings)[p_table[i].settings_offset] = ((unsigned char*)&global_settings)[p_table[i].settings_offset] =
(unsigned char)val; (unsigned char)val;
break; break;
case 2: case 2:
((unsigned short*)&global_settings)[p_table[i].settings_offset/2] = ((unsigned short*)&global_settings)[p_table[i].settings_offset/2] =
(unsigned short)val; (unsigned short)val;
break; break;
case 4: case 4:
((unsigned int*)&global_settings)[p_table[i].settings_offset/4] = ((unsigned int*)&global_settings)[p_table[i].settings_offset/4] =
(unsigned int)val; (unsigned int)val;
break; break;
default: default:
@ -1083,7 +1085,7 @@ static int load_cfg_table(
if (i==count) if (i==count)
i=1; /* wraparound */ i=1; /* wraparound */
} while (i != hint); /* back where we started, all searched */ } while (i != hint); /* back where we started, all searched */
return 0; /* indicate not found */ return 0; /* indicate not found */
} }
@ -1102,8 +1104,8 @@ bool settings_load_config(const char* file)
char* name; char* name;
char* value; char* value;
const struct bit_entry* table[2] = { rtc_bits, hd_bits }; const struct bit_entry* table[2] = { rtc_bits, hd_bits };
const int ta_size[2] = { const int ta_size[2] = {
sizeof(rtc_bits)/sizeof(rtc_bits[0]), sizeof(rtc_bits)/sizeof(rtc_bits[0]),
sizeof(hd_bits)/sizeof(hd_bits[0]) sizeof(hd_bits)/sizeof(hd_bits[0])
}; };
int last_table = 0; /* which table was used last round */ int last_table = 0; /* which table was used last round */
@ -1133,7 +1135,7 @@ bool settings_load_config(const char* file)
#endif #endif
/* check for scalar values, using the two tables */ /* check for scalar values, using the two tables */
pos = load_cfg_table(table[last_table], ta_size[last_table], pos = load_cfg_table(table[last_table], ta_size[last_table],
name, value, last_pos); name, value, last_pos);
if (pos) /* success */ if (pos) /* success */
{ {
@ -1160,7 +1162,7 @@ bool settings_load_config(const char* file)
/* helper to save content of global_settings into a file, /* helper to save content of global_settings into a file,
as described per table */ as described per table */
static void save_cfg_table(const struct bit_entry* p_table, int count, int fd) static void save_cfg_table(const struct bit_entry* p_table, int count, int fd)
{ {
long value; /* 32 bit content */ long value; /* 32 bit content */
@ -1197,7 +1199,7 @@ static void save_cfg_table(const struct bit_entry* p_table, int count, int fd)
DEBUGF( "illegal size!" ); DEBUGF( "illegal size!" );
continue; continue;
} }
if (p_run->cfg_val == NULL) /* write as number */ if (p_run->cfg_val == NULL) /* write as number */
{ {
fdprintf(fd, "%s: %ld\r\n", p_run->cfg_name, value); fdprintf(fd, "%s: %ld\r\n", p_run->cfg_name, value);
@ -1207,7 +1209,7 @@ static void save_cfg_table(const struct bit_entry* p_table, int count, int fd)
const char* p = p_run->cfg_val; const char* p = p_run->cfg_val;
fdprintf(fd, "%s: ", p_run->cfg_name); fdprintf(fd, "%s: ", p_run->cfg_name);
while(value >= 0) while(value >= 0)
{ {
char c = *p++; /* currently processed char */ char c = *p++; /* currently processed char */
@ -1231,7 +1233,7 @@ bool settings_save_config(void)
{ {
int fd; int fd;
char filename[MAX_PATH]; char filename[MAX_PATH];
create_numbered_filename(filename, ROCKBOX_DIR, "config", ".cfg", 2); create_numbered_filename(filename, ROCKBOX_DIR, "config", ".cfg", 2);
/* allow user to modify filename */ /* allow user to modify filename */
@ -1294,15 +1296,15 @@ static void default_table(const struct bit_entry* p_table, int count)
switch(p_table[i].byte_size) switch(p_table[i].byte_size)
{ {
case 1: case 1:
((unsigned char*)&global_settings)[p_table[i].settings_offset] = ((unsigned char*)&global_settings)[p_table[i].settings_offset] =
(unsigned char)p_table[i].default_val; (unsigned char)p_table[i].default_val;
break; break;
case 2: case 2:
((unsigned short*)&global_settings)[p_table[i].settings_offset/2] = ((unsigned short*)&global_settings)[p_table[i].settings_offset/2] =
(unsigned short)p_table[i].default_val; (unsigned short)p_table[i].default_val;
break; break;
case 4: case 4:
((unsigned int*)&global_settings)[p_table[i].settings_offset/4] = ((unsigned int*)&global_settings)[p_table[i].settings_offset/4] =
(unsigned int)p_table[i].default_val; (unsigned int)p_table[i].default_val;
break; break;
default: default:
@ -1314,10 +1316,10 @@ static void default_table(const struct bit_entry* p_table, int count)
/* /*
* reset all settings to their default value * reset all settings to their default value
*/ */
void settings_reset(void) { void settings_reset(void) {
DEBUGF( "settings_reset()\n" ); DEBUGF( "settings_reset()\n" );
/* read defaults from table(s) into global_settings */ /* read defaults from table(s) into global_settings */
@ -1349,8 +1351,8 @@ void settings_reset(void) {
bool set_bool(const char* string, bool* variable ) bool set_bool(const char* string, bool* variable )
{ {
return set_bool_options(string, variable, return set_bool_options(string, variable,
STR(LANG_SET_BOOL_YES), STR(LANG_SET_BOOL_YES),
STR(LANG_SET_BOOL_NO), STR(LANG_SET_BOOL_NO),
NULL); NULL);
} }
@ -1373,7 +1375,7 @@ bool set_bool_options(const char* string, bool* variable,
bool result; bool result;
boolfunction = function; boolfunction = function;
result = set_option(string, variable, BOOL, names, 2, result = set_option(string, variable, BOOL, names, 2,
function ? bool_funcwrapper : NULL); function ? bool_funcwrapper : NULL);
return result; return result;
} }
@ -1388,102 +1390,42 @@ bool set_int(const char* string,
int max, int max,
void (*formatter)(char*, int, int, const char*) ) void (*formatter)(char*, int, int, const char*) )
{ {
bool done = false;
int button; int button;
int org_value=*variable; int oldvalue=*variable;
int last_value = INT_MAX; /* out of range init */ struct gui_select select;
gui_select_init_numeric(&select, string, *variable, min, max, step, unit, formatter);
#ifdef HAVE_LCD_BITMAP gui_syncselect_draw(&select);
if(global_settings.statusbar) while (!gui_select_is_validated(&select))
lcd_setmargins(0, STATUSBAR_HEIGHT); {
else
lcd_setmargins(0, 0);
#endif
lcd_clear_display();
lcd_puts_scroll(0, 0, string);
while (!done) {
char str[32];
if (formatter)
{
formatter(str, sizeof str, *variable, unit);
}
else
{
snprintf(str,sizeof str,"%d %s ", *variable, unit);
}
lcd_puts(0, 1, str);
#ifdef HAVE_LCD_BITMAP
status_draw(true);
#endif
lcd_update();
if (global_settings.talk_menu && *variable != last_value)
{
if (voice_unit < UNIT_LAST)
{ /* use the available unit definition */
talk_value(*variable, voice_unit, false);
}
else
{ /* say the number, followed by an arbitrary voice ID */
talk_number(*variable, false);
talk_id(voice_unit, true);
}
last_value = *variable;
}
button = button_get_w_tmo(HZ/2); button = button_get_w_tmo(HZ/2);
switch(button) { if(gui_syncselect_do_button(&select, button))
case SETTINGS_INC: {
case SETTINGS_INC | BUTTON_REPEAT: *variable=gui_select_get_selected(&select);
*variable += step; if (global_settings.talk_menu)
break; {
gui_syncselect_draw(&select);
case SETTINGS_DEC: if (voice_unit < UNIT_LAST)
case SETTINGS_DEC | BUTTON_REPEAT: { /* use the available unit definition */
*variable -= step; talk_value(*variable, voice_unit, false);
break;
case SETTINGS_OK:
#ifdef SETTINGS_OK2
case SETTINGS_OK2:
#endif
done = true;
break;
case SETTINGS_CANCEL:
#ifdef SETTINGS_CANCEL2
case SETTINGS_CANCEL2:
#endif
if (*variable != org_value) {
*variable=org_value;
lcd_stop_scroll();
lcd_puts(0, 0, str(LANG_MENU_SETTING_CANCEL));
lcd_update();
sleep(HZ/2);
} }
done = true; else
break; { /* say the number, followed by an arbitrary voice ID */
talk_number(*variable, false);
default: talk_id(voice_unit, true);
if(default_event_handler(button) == SYS_USB_CONNECTED) }
return true; }
break; if ( function )
function(gui_select_get_selected(&select));
} }
if(*variable > max ) gui_syncstatusbar_draw(&statusbars, false);
*variable = max; if(gui_select_is_canceled(&select))
{
if(*variable < min ) *variable=oldvalue;
*variable = min; return false;
}
if ( function && button != BUTTON_NONE) if(default_event_handler(button) == SYS_USB_CONNECTED)
function(*variable); return true;
} }
lcd_stop_scroll();
return false; return false;
} }
@ -1495,109 +1437,52 @@ bool set_int(const char* string,
different and bit-incompatible types and can not share the same access different and bit-incompatible types and can not share the same access
code. */ code. */
#define set_type_fromint(type, dest, value) \
if (type == INT) \
*(int *)dest=value; \
else \
*(bool *)dest=value?true:false
#define set_int_fromtype(type, dest, var) \
if (type == INT) \
dest=*(int *)var; \
else \
dest=*(bool *)var?1:0
bool set_option(const char* string, void* variable, enum optiontype type, bool set_option(const char* string, void* variable, enum optiontype type,
const struct opt_items* options, int numoptions, void (*function)(int)) const struct opt_items* options, int numoptions, void (*function)(int))
{ {
bool done = false;
int button; int button;
int* intvar = (int*)variable; int oldvalue;
bool* boolvar = (bool*)variable; /* oldvalue=*variable; */
int oldval = 0; set_int_fromtype(type, oldvalue, variable);
int index, oldindex = -1; /* remember what we said */ struct gui_select select;
gui_select_init_items(&select, string, oldvalue, options, numoptions);
if (type==INT) gui_syncselect_draw(&select);
oldval=*intvar; while ( !gui_select_is_validated(&select) )
else {
oldval=*boolvar; gui_syncstatusbar_draw(&statusbars, true);
#ifdef HAVE_LCD_BITMAP
if(global_settings.statusbar)
lcd_setmargins(0, STATUSBAR_HEIGHT);
else
lcd_setmargins(0, 0);
#endif
lcd_clear_display();
lcd_puts_scroll(0, 0, string);
while ( !done ) {
index = type==INT ? *intvar : (int)*boolvar;
lcd_puts(0, 1, P2STR(options[index].string));
if (global_settings.talk_menu && index != oldindex)
{
talk_id(options[index].voice_id, false);
oldindex = index;
}
#ifdef HAVE_LCD_BITMAP
status_draw(true);
#endif
lcd_update();
button = button_get_w_tmo(HZ/2); button = button_get_w_tmo(HZ/2);
switch (button) { if(gui_syncselect_do_button(&select, button))
case SETTINGS_INC: {
case SETTINGS_INC | BUTTON_REPEAT: /* *variable = gui_select_get_selected(&select) */
if (type == INT) { set_type_fromint(type, variable, gui_select_get_selected(&select));
if ( *intvar < (numoptions-1) ) gui_syncselect_draw(&select);
(*intvar)++; if (global_settings.talk_menu)
else talk_id(options[gui_select_get_selected(&select)].voice_id, false);
(*intvar) -= (numoptions-1); if ( function )
} function(*(int *)variable);
else
*boolvar = !*boolvar;
break;
case SETTINGS_DEC:
case SETTINGS_DEC | BUTTON_REPEAT:
if (type == INT) {
if ( *intvar > 0 )
(*intvar)--;
else
(*intvar) += (numoptions-1);
}
else
*boolvar = !*boolvar;
break;
case SETTINGS_OK:
#ifdef SETTINGS_OK2
case SETTINGS_OK2:
#endif
done = true;
break;
case SETTINGS_CANCEL:
#ifdef SETTINGS_CANCEL2
case SETTINGS_CANCEL2:
#endif
if (((type==INT) && (*intvar != oldval)) ||
((type==BOOL) && (*boolvar != (bool)oldval))) {
if (type==INT)
*intvar=oldval;
else
*boolvar=oldval;
lcd_stop_scroll();
lcd_puts(0, 0, str(LANG_MENU_SETTING_CANCEL));
lcd_update();
sleep(HZ/2);
}
done = true;
break;
default:
if(default_event_handler(button) == SYS_USB_CONNECTED)
return true;
break;
} }
gui_syncstatusbar_draw(&statusbars, false);
if ( function && button != BUTTON_NONE) { if(gui_select_is_canceled(&select))
if (type == INT) {
function(*intvar); /* *variable=oldvalue; */
else set_type_fromint(type, variable, oldvalue);
function(*boolvar); return false;
} }
if(default_event_handler(button) == SYS_USB_CONNECTED)
return true;
} }
lcd_stop_scroll();
return false; return false;
} }