1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 by Kevin Ferrare
11 * Copyright (C) 2007 by Jonathan Gordon
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
23 #include "string-extra.h"
26 #include "option_select.h"
30 #include "settings_list.h"
37 #include "quickscreen.h"
40 static int selection_to_val(const struct settings_list
*setting
, int selection
);
41 int option_value_as_int(const struct settings_list
*setting
)
43 int type
= (setting
->flags
& F_T_MASK
);
46 temp
= *(bool*)setting
->setting
?1:0;
47 else if (type
== F_T_UINT
|| type
== F_T_INT
)
48 temp
= *(int*)setting
->setting
;
51 static const char *unit_strings
[] =
53 [UNIT_INT
] = "", [UNIT_MS
] = "ms",
54 [UNIT_SEC
] = "s", [UNIT_MIN
] = "min",
55 [UNIT_HOUR
]= "hr", [UNIT_KHZ
] = "kHz",
56 [UNIT_DB
] = "dB", [UNIT_PERCENT
] = "%",
57 [UNIT_MAH
] = "mAh", [UNIT_PIXEL
] = "px",
58 [UNIT_PER_SEC
] = "per sec",
60 [UNIT_MB
] = "MB", [UNIT_KBIT
] = "kb/s",
61 [UNIT_PM_TICK
] = "units/10ms",
63 /* these two vars are needed so arbitrary values can be added to the
64 TABLE_SETTING settings if the F_ALLOW_ARBITRARY_VALS flag is set */
65 static int table_setting_oldval
= 0, table_setting_array_position
= 0;
66 const char *option_get_valuestring(const struct settings_list
*setting
,
67 char *buffer
, int buf_len
,
70 const char* str
= buffer
;
71 if ((setting
->flags
& F_BOOL_SETTING
) == F_BOOL_SETTING
)
73 bool val
= (bool)temp_var
;
74 strlcpy(buffer
, str(val
? setting
->bool_setting
->lang_yes
:
75 setting
->bool_setting
->lang_no
), buf_len
);
77 #if 0 /* probably dont need this one */
78 else if ((setting
->flags
& F_FILENAME
) == F_FILENAME
)
80 struct filename_setting
*info
= setting
->filename_setting
;
81 snprintf(buffer
, buf_len
, "%s%s%s", info
->prefix
,
82 (char*)temp_var
, info
->suffix
);
85 else if (((setting
->flags
& F_INT_SETTING
) == F_INT_SETTING
) ||
86 ((setting
->flags
& F_TABLE_SETTING
) == F_TABLE_SETTING
))
88 const struct int_setting
*int_info
= setting
->int_setting
;
89 const struct table_setting
*tbl_info
= setting
->table_setting
;
91 const char* (*formatter
)(char*, size_t, int, const char*);
92 if ((setting
->flags
& F_INT_SETTING
) == F_INT_SETTING
)
94 formatter
= int_info
->formatter
;
95 unit
= unit_strings
[int_info
->unit
];
99 formatter
= tbl_info
->formatter
;
100 unit
= unit_strings
[tbl_info
->unit
];
103 str
= formatter(buffer
, buf_len
, (int)temp_var
, unit
);
105 snprintf(buffer
, buf_len
, "%d %s", (int)temp_var
, unit
?unit
:"");
107 else if ((setting
->flags
& F_T_SOUND
) == F_T_SOUND
)
110 const char *unit
= sound_unit(setting
->sound_setting
->setting
);
111 int val
= sound_val2phys(setting
->sound_setting
->setting
, (int)temp_var
);
112 if (sound_numdecimals(setting
->sound_setting
->setting
))
122 snprintf(buffer
, buf_len
, "%c%d.%d %s", sign
, integer
, dec
, unit
);
125 snprintf(buffer
, buf_len
, "%d %s", val
, unit
);
127 else if ((setting
->flags
& F_CHOICE_SETTING
) == F_CHOICE_SETTING
)
129 if (setting
->flags
& F_CHOICETALKS
)
132 const struct choice_setting
*info
= setting
->choice_setting
;
133 if (info
->talks
[(int)temp_var
] < LANG_LAST_INDEX_IN_ARRAY
)
135 strlcpy(buffer
, str(info
->talks
[(int)temp_var
]), buf_len
);
139 find_setting(setting
->setting
, &setting_id
);
140 cfg_int_to_string(setting_id
, (int)temp_var
, buffer
, buf_len
);
145 int value
= (int)temp_var
;
146 char *val
= P2STR(setting
->choice_setting
->desc
[value
]);
147 strlcpy(buffer
, val
, buf_len
);
152 void option_talk_value(const struct settings_list
*setting
, int value
, bool enqueue
)
154 if ((setting
->flags
& F_BOOL_SETTING
) == F_BOOL_SETTING
)
156 bool val
= (value
==1);
157 talk_id(val
? setting
->bool_setting
->lang_yes
:
158 setting
->bool_setting
->lang_no
, enqueue
);
160 #if 0 /* probably dont need this one */
161 else if ((setting
->flags
& F_FILENAME
) == F_FILENAME
)
165 else if (((setting
->flags
& F_INT_SETTING
) == F_INT_SETTING
) ||
166 ((setting
->flags
& F_TABLE_SETTING
) == F_TABLE_SETTING
))
168 const struct int_setting
*int_info
= setting
->int_setting
;
169 const struct table_setting
*tbl_info
= setting
->table_setting
;
171 int32_t (*get_talk_id
)(int, int);
172 if ((setting
->flags
& F_INT_SETTING
) == F_INT_SETTING
)
174 unit
= int_info
->unit
;
175 get_talk_id
= int_info
->get_talk_id
;
179 unit
= tbl_info
->unit
;
180 get_talk_id
= tbl_info
->get_talk_id
;
183 talk_id(get_talk_id(value
, unit
), enqueue
);
185 talk_value(value
, unit
, enqueue
);
187 else if ((setting
->flags
& F_T_SOUND
) == F_T_SOUND
)
189 int talkunit
= UNIT_INT
;
190 int sound_setting
= setting
->sound_setting
->setting
;
191 const char *unit
= sound_unit(sound_setting
);
192 int decimals
= sound_numdecimals(sound_setting
);
193 int phys
= sound_val2phys(sound_setting
, value
);
194 if (!strcmp(unit
, "dB"))
196 else if (!strcmp(unit
, "%"))
197 talkunit
= UNIT_PERCENT
;
198 else if (!strcmp(unit
, "Hz"))
199 talkunit
= UNIT_HERTZ
;
200 talk_value_decimal(phys
, talkunit
, decimals
, false);
202 else if ((setting
->flags
& F_CHOICE_SETTING
) == F_CHOICE_SETTING
)
204 if (setting
->flags
& F_CHOICETALKS
)
206 talk_id(setting
->choice_setting
->talks
[value
], enqueue
);
210 talk_id(P2ID(setting
->choice_setting
->desc
[value
]), enqueue
);
215 static int option_talk(int selected_item
, void * data
)
217 struct settings_list
*setting
= (struct settings_list
*)data
;
218 int temp_var
= selection_to_val(setting
, selected_item
);
219 option_talk_value(setting
, temp_var
, false);
223 #if defined(HAVE_QUICKSCREEN) || defined(HAVE_RECORDING) || defined(HAVE_TOUCHSCREEN)
224 /* only the quickscreen and recording trigger needs this */
225 void option_select_next_val(const struct settings_list
*setting
,
226 bool previous
, bool apply
)
229 int *value
= setting
->setting
;
230 if ((setting
->flags
& F_BOOL_SETTING
) == F_BOOL_SETTING
)
232 *(bool*)value
= !*(bool*)value
;
233 if (apply
&& setting
->bool_setting
->option_callback
)
234 setting
->bool_setting
->option_callback(*(bool*)value
);
237 else if ((setting
->flags
& F_INT_SETTING
) == F_INT_SETTING
)
239 struct int_setting
*info
= (struct int_setting
*)setting
->int_setting
;
240 bool neg_step
= (info
->step
< 0);
243 val
= *value
+ info
->step
;
244 if (neg_step
? (val
< info
->max
) : (val
> info
->max
))
249 val
= *value
- info
->step
;
250 if (neg_step
? (val
> info
->min
) : (val
< info
->min
))
254 if (apply
&& info
->option_callback
)
255 info
->option_callback(val
);
257 else if ((setting
->flags
& F_T_SOUND
) == F_T_SOUND
)
259 int setting_id
= setting
->sound_setting
->setting
;
260 int steps
= sound_steps(setting_id
);
261 int min
= sound_min(setting_id
);
262 int max
= sound_max(setting_id
);
265 val
= *value
+ steps
;
271 val
= *value
- steps
;
277 sound_set(setting_id
, val
);
279 else if ((setting
->flags
& F_CHOICE_SETTING
) == F_CHOICE_SETTING
)
281 struct choice_setting
*info
= (struct choice_setting
*)setting
->choice_setting
;
285 if (val
>= info
->count
)
295 if (apply
&& info
->option_callback
)
296 info
->option_callback(val
);
298 else if ((setting
->flags
& F_TABLE_SETTING
) == F_TABLE_SETTING
)
300 const struct table_setting
*tbl_info
= setting
->table_setting
;
302 add
= previous
?tbl_info
->count
-1:1;
303 for (i
=0; i
<tbl_info
->count
;i
++)
305 if ((*value
== tbl_info
->values
[i
]) ||
306 (settings
->flags
&F_ALLOW_ARBITRARY_VALS
&&
307 *value
< tbl_info
->values
[i
]))
309 val
= tbl_info
->values
[(i
+add
)%tbl_info
->count
];
314 if (apply
&& tbl_info
->option_callback
)
315 tbl_info
->option_callback(val
);
320 static int selection_to_val(const struct settings_list
*setting
, int selection
)
322 /* rockbox: comment 'set but unused' variables
325 int max
= 0, step
= 1;
326 if (((setting
->flags
& F_BOOL_SETTING
) == F_BOOL_SETTING
) ||
327 ((setting
->flags
& F_CHOICE_SETTING
) == F_CHOICE_SETTING
))
329 else if ((setting
->flags
& F_TABLE_SETTING
) == F_TABLE_SETTING
)
331 const struct table_setting
*info
= setting
->table_setting
;
332 if (setting
->flags
&F_ALLOW_ARBITRARY_VALS
&&
333 table_setting_array_position
!= -1 &&
334 (selection
>= table_setting_array_position
))
336 if (selection
== table_setting_array_position
)
337 return table_setting_oldval
;
338 return info
->values
[selection
-1];
341 return info
->values
[selection
];
343 else if ((setting
->flags
& F_T_SOUND
) == F_T_SOUND
)
345 int setting_id
= setting
->sound_setting
->setting
;
346 #ifndef ASCENDING_INT_SETTINGS
347 step
= sound_steps(setting_id
);
348 max
= sound_max(setting_id
);
349 /* min = sound_min(setting_id); */
351 step
= -sound_steps(setting_id
);
352 /* min = sound_max(setting_id); */
353 max
= sound_min(setting_id
);
356 else if ((setting
->flags
& F_INT_SETTING
) == F_INT_SETTING
)
358 const struct int_setting
*info
= setting
->int_setting
;
359 #ifndef ASCENDING_INT_SETTINGS
360 /* min = info->min; */
365 /* min = info->max; */
369 return max
- (selection
* step
);
372 static const char * value_setting_get_name_cb(int selected_item
,
377 selected_item
= selection_to_val(data
, selected_item
);
378 return option_get_valuestring(data
, buffer
, buffer_len
, selected_item
);
381 /* wrapper to convert from int param to bool param in option_screen */
382 static void (*boolfunction
)(bool);
383 static void bool_funcwrapper(int value
)
391 static void val_to_selection(const struct settings_list
*setting
, int oldvalue
,
392 int *nb_items
, int *selected
,
393 void (**function
)(int))
395 int var_type
= setting
->flags
&F_T_MASK
;
396 /* set the number of items and current selection */
397 if (var_type
== F_T_INT
|| var_type
== F_T_UINT
)
399 if (setting
->flags
&F_CHOICE_SETTING
)
401 *nb_items
= setting
->choice_setting
->count
;
402 *selected
= oldvalue
;
403 *function
= setting
->choice_setting
->option_callback
;
405 else if (setting
->flags
&F_TABLE_SETTING
)
407 const struct table_setting
*info
= setting
->table_setting
;
409 *nb_items
= info
->count
;
411 table_setting_array_position
= -1;
412 for (i
=0;*selected
==-1 && i
<*nb_items
;i
++)
414 if (setting
->flags
&F_ALLOW_ARBITRARY_VALS
&&
415 (oldvalue
< info
->values
[i
]))
417 table_setting_oldval
= oldvalue
;
418 table_setting_array_position
= i
;
422 else if (oldvalue
== info
->values
[i
])
425 *function
= info
->option_callback
;
427 else if (setting
->flags
&F_T_SOUND
)
429 int setting_id
= setting
->sound_setting
->setting
;
430 int steps
= sound_steps(setting_id
);
431 int min
= sound_min(setting_id
);
432 int max
= sound_max(setting_id
);
433 *nb_items
= (max
-min
)/steps
+ 1;
434 #ifndef ASCENDING_INT_SETTINGS
435 *selected
= (max
- oldvalue
) / steps
;
437 *selected
= (oldvalue
- min
) / steps
;
439 *function
= sound_get_fn(setting_id
);
443 const struct int_setting
*info
= setting
->int_setting
;
448 *nb_items
= (max
-min
)/step
+ 1;
449 #ifndef ASCENDING_INT_SETTINGS
450 *selected
= (max
- oldvalue
) / step
;
452 *selected
= (oldvalue
- min
) / step
;
454 *function
= info
->option_callback
;
457 else if (var_type
== F_T_BOOL
)
459 *selected
= oldvalue
;
461 boolfunction
= setting
->bool_setting
->option_callback
;
463 *function
= bool_funcwrapper
;
467 bool option_screen(const struct settings_list
*setting
,
468 struct viewport parent
[NB_SCREENS
],
469 bool use_temp_var
, unsigned char* option_title
)
473 struct gui_synclist lists
;
474 int oldvalue
, nb_items
= 0, selected
= 0, temp_var
;
476 bool allow_wrap
= setting
->flags
& F_NO_WRAP
? false : true;
477 int var_type
= setting
->flags
&F_T_MASK
;
478 void (*function
)(int) = NULL
;
480 if (var_type
== F_T_INT
|| var_type
== F_T_UINT
)
482 variable
= use_temp_var
? &temp_var
: (int*)setting
->setting
;
483 temp_var
= oldvalue
= *(int*)setting
->setting
;
485 else if (var_type
== F_T_BOOL
)
487 /* bools always use the temp variable...
488 if use_temp_var is false it will be copied to setting->setting every change */
489 variable
= &temp_var
;
490 temp_var
= oldvalue
= *(bool*)setting
->setting
?1:0;
492 else return false; /* only int/bools can go here */
493 push_current_activity(ACTIVITY_OPTIONSELECT
);
494 gui_synclist_init(&lists
, value_setting_get_name_cb
,
495 (void*)setting
, false, 1, parent
);
496 if (setting
->lang_id
== -1)
497 title
= (char*)setting
->cfg_vals
;
499 title
= P2STR(option_title
);
501 gui_synclist_set_title(&lists
, title
, Icon_Questionmark
);
502 gui_synclist_set_icon_callback(&lists
, NULL
);
503 if(global_settings
.talk_menu
)
504 gui_synclist_set_voice_callback(&lists
, option_talk
);
506 val_to_selection(setting
, oldvalue
, &nb_items
, &selected
, &function
);
507 gui_synclist_set_nb_items(&lists
, nb_items
);
508 gui_synclist_select_item(&lists
, selected
);
510 gui_synclist_limit_scroll(&lists
, true);
511 gui_synclist_draw(&lists
);
513 gui_synclist_speak_item(&lists
);
516 if (list_do_action(CONTEXT_LIST
, HZ
, /* HZ so the status bar redraws */
518 allow_wrap
? LIST_WRAP_UNLESS_HELD
: LIST_WRAP_OFF
))
520 /* setting changed */
521 selected
= gui_synclist_get_sel_pos(&lists
);
522 *variable
= selection_to_val(setting
, selected
);
523 if (var_type
== F_T_BOOL
&& !use_temp_var
)
524 *(bool*)setting
->setting
= (*variable
==1);
526 else if (action
== ACTION_NONE
)
528 else if (action
== ACTION_STD_CANCEL
)
530 /* setting canceled, restore old value if changed */
531 if (*variable
!= oldvalue
)
533 *variable
= oldvalue
;
534 if (var_type
== F_T_BOOL
&& !use_temp_var
)
535 *(bool*)setting
->setting
= (oldvalue
==1);
536 splash(HZ
/2, ID2P(LANG_CANCEL
));
540 else if (action
== ACTION_STD_CONTEXT
)
542 /* reset setting to default */
543 reset_setting(setting
, variable
);
544 if (var_type
== F_T_BOOL
&& !use_temp_var
)
545 *(bool*)setting
->setting
= (*variable
==1);
546 val_to_selection(setting
, *variable
, &nb_items
,
547 &selected
, &function
);
548 gui_synclist_select_item(&lists
, selected
);
549 gui_synclist_draw(&lists
);
550 gui_synclist_speak_item(&lists
);
552 else if (action
== ACTION_STD_OK
)
554 /* setting accepted, store now if it used a temp var */
557 if (var_type
== F_T_INT
|| var_type
== F_T_UINT
)
558 *(int*)setting
->setting
= *variable
;
560 *(bool*)setting
->setting
= (*variable
==1);
565 else if(default_event_handler(action
) == SYS_USB_CONNECTED
)
570 /* if the volume is changing we need to let the skins know */
571 if (function
== sound_get_fn(SOUND_VOLUME
))
572 global_status
.last_volume_change
= current_tick
;
574 pop_current_activity();
578 int get_setting_info_for_bar(int setting_id
, int *count
, int *val
)
580 const struct settings_list
*setting
= &settings
[setting_id
];
581 int var_type
= setting
->flags
&F_T_MASK
;
582 void (*function
)(int) = NULL
;
585 if (var_type
== F_T_INT
|| var_type
== F_T_UINT
)
587 oldvalue
= *(int*)setting
->setting
;
589 else if (var_type
== F_T_BOOL
)
591 oldvalue
= *(bool*)setting
->setting
?1:0;
597 return false; /* only int/bools can go here */
600 val_to_selection(setting
, oldvalue
, count
, val
, &function
);
604 #ifdef HAVE_TOUCHSCREEN
605 void update_setting_value_from_touch(int setting_id
, int selection
)
607 const struct settings_list
*setting
= &settings
[setting_id
];
608 int new_val
= selection_to_val(setting
, selection
);
609 int var_type
= setting
->flags
&F_T_MASK
;
611 if (var_type
== F_T_INT
|| var_type
== F_T_UINT
)
613 *(int*)setting
->setting
= new_val
;
615 else if (var_type
== F_T_BOOL
)
617 *(bool*)setting
->setting
= new_val
? true : false;