1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 by Kevin Ferrare
11 * Copyright (C) 2007 by Jonathan Gordon
13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement.
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
19 ****************************************************************************/
23 #include "option_select.h"
28 #include "settings_list.h"
32 #include "statusbar.h"
36 #if defined (HAVE_SCROLLWHEEL) || \
37 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
38 (CONFIG_KEYPAD == IPOD_4G_PAD) || \
39 (CONFIG_KEYPAD == IPOD_1G2G_PAD) || \
40 (CONFIG_KEYPAD == PLAYER_PAD)
41 /* Define this if your target makes sense to have
42 smaller values at the top of the list increasing down the list */
43 #define ASCENDING_INT_SETTINGS
46 static int selection_to_val(struct settings_list
*setting
, int selection
);
48 static const char *unit_strings
[] =
50 [UNIT_INT
] = "", [UNIT_MS
] = "ms",
51 [UNIT_SEC
] = "s", [UNIT_MIN
] = "min",
52 [UNIT_HOUR
]= "hr", [UNIT_KHZ
] = "kHz",
53 [UNIT_DB
] = "dB", [UNIT_PERCENT
] = "%",
54 [UNIT_MAH
] = "mAh", [UNIT_PIXEL
] = "px",
55 [UNIT_PER_SEC
] = "per sec",
57 [UNIT_MB
] = "MB", [UNIT_KBIT
] = "kb/s",
58 [UNIT_PM_TICK
] = "units/10ms",
60 /* these two vars are needed so arbitrary values can be added to the
61 TABLE_SETTING settings if the F_ALLOW_ARBITRARY_VALS flag is set */
62 static int table_setting_oldval
= 0, table_setting_array_position
= 0;
63 static char *option_get_valuestring(struct settings_list
*setting
,
64 char *buffer
, int buf_len
,
67 if ((setting
->flags
& F_BOOL_SETTING
) == F_BOOL_SETTING
)
69 bool val
= (bool)temp_var
;
70 snprintf(buffer
, buf_len
, "%s",
71 str(val
? setting
->bool_setting
->lang_yes
:
72 setting
->bool_setting
->lang_no
));
74 #if 0 /* probably dont need this one */
75 else if ((setting
->flags
& F_FILENAME
) == F_FILENAME
)
77 struct filename_setting
*info
= setting
->filename_setting
;
78 snprintf(buffer
, buf_len
, "%s%s%s", info
->prefix
,
79 (char*)temp_var
, info
->suffix
);
82 else if (((setting
->flags
& F_INT_SETTING
) == F_INT_SETTING
) ||
83 ((setting
->flags
& F_TABLE_SETTING
) == F_TABLE_SETTING
))
85 const struct int_setting
*int_info
= setting
->int_setting
;
86 const struct table_setting
*tbl_info
= setting
->table_setting
;
88 void (*formatter
)(char*, size_t, int, const char*);
89 if ((setting
->flags
& F_INT_SETTING
) == F_INT_SETTING
)
91 formatter
= int_info
->formatter
;
92 unit
= unit_strings
[int_info
->unit
];
96 formatter
= tbl_info
->formatter
;
97 unit
= unit_strings
[tbl_info
->unit
];
100 formatter(buffer
, buf_len
, (int)temp_var
, unit
);
102 snprintf(buffer
, buf_len
, "%d %s", (int)temp_var
, unit
?unit
:"");
104 else if ((setting
->flags
& F_T_SOUND
) == F_T_SOUND
)
106 char sign
= ' ', *unit
;
107 unit
= (char*)sound_unit(setting
->sound_setting
->setting
);
108 if (sound_numdecimals(setting
->sound_setting
->setting
))
111 int val
= sound_val2phys(setting
->sound_setting
->setting
,
118 integer
= val
/ 10; dec
= val
% 10;
119 snprintf(buffer
, buf_len
, "%c%d.%d %s", sign
, integer
, dec
, unit
);
122 snprintf(buffer
, buf_len
, "%d %s", (int)temp_var
, unit
);
124 else if ((setting
->flags
& F_CHOICE_SETTING
) == F_CHOICE_SETTING
)
126 if (setting
->flags
& F_CHOICETALKS
)
129 const struct choice_setting
*info
= setting
->choice_setting
;
130 if (info
->talks
[(int)temp_var
] < LANG_LAST_INDEX_IN_ARRAY
)
132 snprintf(buffer
, buf_len
, "%s", str(info
->talks
[(int)temp_var
]));
136 find_setting(setting
->setting
, &setting_id
);
137 cfg_int_to_string(setting_id
, (int)temp_var
, buffer
, buf_len
);
142 int value
= (int)temp_var
;
143 char *val
= P2STR(setting
->choice_setting
->desc
[value
]);
144 snprintf(buffer
, buf_len
, "%s", val
);
150 static int option_talk(int selected_item
, void * data
)
152 struct settings_list
*setting
= (struct settings_list
*)data
;
153 int temp_var
= selection_to_val(setting
, selected_item
);
154 if ((setting
->flags
& F_BOOL_SETTING
) == F_BOOL_SETTING
)
156 bool val
= temp_var
==1?true:false;
157 talk_id(val
? setting
->bool_setting
->lang_yes
:
158 setting
->bool_setting
->lang_no
, false);
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((int)temp_var
, unit
), false);
185 talk_value((int)temp_var
, unit
, false);
187 else if ((setting
->flags
& F_T_SOUND
) == F_T_SOUND
)
189 int talkunit
= UNIT_INT
;
190 const char *unit
= sound_unit(setting
->sound_setting
->setting
);
191 if (!strcmp(unit
, "dB"))
193 else if (!strcmp(unit
, "%"))
194 talkunit
= UNIT_PERCENT
;
195 else if (!strcmp(unit
, "Hz"))
196 talkunit
= UNIT_HERTZ
;
197 talk_value((int)temp_var
, talkunit
, false);
199 else if ((setting
->flags
& F_CHOICE_SETTING
) == F_CHOICE_SETTING
)
201 int value
= (int)temp_var
;
202 if (setting
->flags
& F_CHOICETALKS
)
204 talk_id(setting
->choice_setting
->talks
[value
], false);
208 talk_id(P2ID(setting
->choice_setting
->desc
[value
]), false);
214 int option_select_next_val(struct settings_list
*setting
,
218 if ((setting
->flags
& F_BOOL_SETTING
) == F_BOOL_SETTING
)
220 val
= (bool)temp_var
? 0 : 1;
222 else if ((setting
->flags
& F_INT_SETTING
) == F_INT_SETTING
)
224 struct int_setting
*info
= setting
->int_setting
;
225 val
= (int)temp_var
+ info
->step
;
229 else if ((setting
->flags
& F_T_SOUND
) == F_T_SOUND
)
231 int setting_id
= setting
->sound_setting
->setting
;
232 int steps
= sound_steps(setting_id
);
233 int min
= sound_min(setting_id
);
234 int max
= sound_max(setting_id
);
235 val
= (int)temp_var
+ steps
;
239 else if ((setting
->flags
& F_CHOICE_SETTING
) == F_CHOICE_SETTING
)
241 struct choice_setting
*info
= setting
->choice_setting
;
243 if (val
> info
->count
)
249 int option_select_prev_val(struct settings_list
*setting
,
253 if ((setting
->flags
& F_BOOL_SETTING
) == F_BOOL_SETTING
)
255 val
= (bool)temp_var
? 0 : 1;
257 else if ((setting
->flags
& F_INT_SETTING
) == F_INT_SETTING
)
259 struct int_setting
*info
= setting
->int_setting
;
260 val
= (int)temp_var
- info
->step
;
264 else if ((setting
->flags
& F_T_SOUND
) == F_T_SOUND
)
266 int setting_id
= setting
->sound_setting
->setting
;
267 int steps
= sound_steps(setting_id
);
268 int min
= sound_min(setting_id
);
269 int max
= sound_max(setting_id
);
270 val
= (int)temp_var
-+ steps
;
274 else if ((setting
->flags
& F_CHOICE_SETTING
) == F_CHOICE_SETTING
)
276 struct choice_setting
*info
= setting
->choice_setting
;
279 val
= info
->count
- 1;
285 static int selection_to_val(struct settings_list
*setting
, int selection
)
287 int min
= 0, max
= 0, step
= 1;
288 if (((setting
->flags
& F_BOOL_SETTING
) == F_BOOL_SETTING
) ||
289 ((setting
->flags
& F_CHOICE_SETTING
) == F_CHOICE_SETTING
))
291 else if ((setting
->flags
& F_TABLE_SETTING
) == F_TABLE_SETTING
)
293 const struct table_setting
*info
= setting
->table_setting
;
294 if (setting
->flags
&F_ALLOW_ARBITRARY_VALS
&&
295 table_setting_array_position
!= -1 &&
296 (selection
>= table_setting_array_position
))
298 if (selection
== table_setting_array_position
)
299 return table_setting_oldval
;
300 return info
->values
[selection
-1];
303 return info
->values
[selection
];
305 else if ((setting
->flags
& F_T_SOUND
) == F_T_SOUND
)
307 int setting_id
= setting
->sound_setting
->setting
;
308 #ifndef ASCENDING_INT_SETTINGS
309 step
= sound_steps(setting_id
);
310 max
= sound_max(setting_id
);
311 min
= sound_min(setting_id
);
313 step
= -sound_steps(setting_id
);
314 min
= sound_max(setting_id
);
315 max
= sound_min(setting_id
);
318 else if ((setting
->flags
& F_INT_SETTING
) == F_INT_SETTING
)
320 const struct int_setting
*info
= setting
->int_setting
;
321 #ifndef ASCENDING_INT_SETTINGS
331 return max
- (selection
* step
);
333 static char * value_setting_get_name_cb(int selected_item
,
334 void * data
, char *buffer
)
336 selected_item
= selection_to_val(data
, selected_item
);
337 return option_get_valuestring(data
, buffer
, MAX_PATH
, selected_item
);
340 /* wrapper to convert from int param to bool param in option_screen */
341 static void (*boolfunction
)(bool);
342 static void bool_funcwrapper(int value
)
350 bool option_screen(struct settings_list
*setting
,
351 bool use_temp_var
, unsigned char* option_title
)
355 struct gui_synclist lists
;
356 int oldvalue
, nb_items
= 0, selected
= 0, temp_var
;
358 bool allow_wrap
= setting
->flags
& F_NO_WRAP
? false : true;
359 int var_type
= setting
->flags
&F_T_MASK
;
360 void (*function
)(int) = NULL
;
362 if (var_type
== F_T_INT
|| var_type
== F_T_UINT
)
364 variable
= use_temp_var
? &temp_var
: (int*)setting
->setting
;
365 temp_var
= oldvalue
= *(int*)setting
->setting
;
367 else if (var_type
== F_T_BOOL
)
369 /* bools always use the temp variable...
370 if use_temp_var is false it will be copied to setting->setting every change */
371 variable
= &temp_var
;
372 temp_var
= oldvalue
= *(bool*)setting
->setting
?1:0;
374 else return false; /* only int/bools can go here */
375 gui_synclist_init(&lists
, value_setting_get_name_cb
,
376 (void*)setting
, false, 1);
377 if (setting
->lang_id
== -1)
378 title
= (char*)setting
->cfg_vals
;
380 title
= P2STR(option_title
);
382 gui_synclist_set_title(&lists
, title
, Icon_Questionmark
);
383 gui_synclist_set_icon_callback(&lists
, NULL
);
384 if(global_settings
.talk_menu
)
385 gui_synclist_set_voice_callback(&lists
, option_talk
);
387 /* set the number of items and current selection */
388 if (var_type
== F_T_INT
|| var_type
== F_T_UINT
)
390 if (setting
->flags
&F_CHOICE_SETTING
)
392 nb_items
= setting
->choice_setting
->count
;
394 function
= setting
->choice_setting
->option_callback
;
396 else if (setting
->flags
&F_TABLE_SETTING
)
398 const struct table_setting
*info
= setting
->table_setting
;
400 nb_items
= info
->count
;
402 table_setting_array_position
= -1;
403 for (i
=0;selected
==-1 && i
<nb_items
;i
++)
405 if (setting
->flags
&F_ALLOW_ARBITRARY_VALS
&&
406 (oldvalue
< info
->values
[i
]))
408 table_setting_oldval
= oldvalue
;
409 table_setting_array_position
= i
;
413 else if (oldvalue
== info
->values
[i
])
416 function
= info
->option_callback
;
418 else if (setting
->flags
&F_T_SOUND
)
420 int setting_id
= setting
->sound_setting
->setting
;
421 int steps
= sound_steps(setting_id
);
422 int min
= sound_min(setting_id
);
423 int max
= sound_max(setting_id
);
424 nb_items
= (max
-min
)/steps
+ 1;
425 #ifndef ASCENDING_INT_SETTINGS
426 selected
= (max
- oldvalue
) / steps
;
428 selected
= (oldvalue
- min
) / steps
;
430 function
= sound_get_fn(setting_id
);
434 const struct int_setting
*info
= setting
->int_setting
;
439 nb_items
= (max
-min
)/step
+ 1;
440 #ifndef ASCENDING_INT_SETTINGS
441 selected
= (max
- oldvalue
) / step
;
443 selected
= (oldvalue
- min
) / step
;
445 function
= info
->option_callback
;
448 else if (var_type
== F_T_BOOL
)
452 boolfunction
= setting
->bool_setting
->option_callback
;
454 function
= bool_funcwrapper
;
456 gui_synclist_set_nb_items(&lists
, nb_items
);
457 gui_synclist_select_item(&lists
, selected
);
459 gui_synclist_limit_scroll(&lists
, true);
460 gui_synclist_draw(&lists
);
462 gui_synclist_speak_item(&lists
);
465 if (list_do_action(CONTEXT_LIST
, TIMEOUT_BLOCK
,
467 allow_wrap
? LIST_WRAP_UNLESS_HELD
: LIST_WRAP_OFF
))
469 selected
= gui_synclist_get_sel_pos(&lists
);
470 *variable
= selection_to_val(setting
, selected
);
471 if (var_type
== F_T_BOOL
)
474 *(bool*)setting
->setting
= selected
==1?true:false;
477 else if (action
== ACTION_NONE
)
479 else if (action
== ACTION_STD_CANCEL
)
481 bool show_cancel
= false;
484 else if (var_type
== F_T_INT
|| var_type
== F_T_UINT
)
486 if (*variable
!= oldvalue
)
489 *variable
= oldvalue
;
494 if (*variable
!= oldvalue
)
498 *(bool*)setting
->setting
= oldvalue
==1?true:false;
499 *variable
= oldvalue
;
503 gui_syncsplash(HZ
/2, ID2P(LANG_CANCEL
));
506 else if (action
== ACTION_STD_OK
)
510 else if(default_event_handler(action
) == SYS_USB_CONNECTED
)
512 gui_syncstatusbar_draw(&statusbars
, false);
518 if (oldvalue
!= *variable
&& (action
!= ACTION_STD_CANCEL
))
522 if (var_type
== F_T_INT
|| var_type
== F_T_UINT
)
523 *(int*)setting
->setting
= *variable
;
525 *(bool*)setting
->setting
= *variable
?true:false;
533 /******************************************************
534 Compatability functions
535 *******************************************************/
536 #define MAX_OPTIONS 32
537 const struct opt_items
*set_option_options
;
538 void set_option_formatter(char* buf
, size_t size
, int item
, const char* unit
)
541 const unsigned char *text
= set_option_options
[item
].string
;
542 snprintf(buf
, size
, "%s", P2STR(text
));
544 int32_t set_option_get_talk_id(int value
, int unit
)
547 return set_option_options
[value
].voice_id
;
549 bool set_option(const char* string
, void* variable
, enum optiontype type
,
550 const struct opt_items
* options
,
551 int numoptions
, void (*function
)(int))
554 struct settings_list item
;
555 struct int_setting data
= {
556 function
, UNIT_INT
, 0, numoptions
-1, 1,
557 set_option_formatter
, set_option_get_talk_id
559 set_option_options
= options
;
560 item
.int_setting
= &data
;
561 item
.flags
= F_INT_SETTING
|F_T_INT
;
563 item
.cfg_vals
= (char*)string
;
564 item
.setting
= &temp
;
566 temp
= *(bool*)variable
? 1: 0;
568 temp
= *(int*)variable
;
569 if (!option_screen(&item
, false, NULL
))
572 *(bool*)variable
= (temp
== 1? true: false);
574 *(int*)variable
= temp
;
580 bool set_int_ex(const unsigned char* string
,
584 void (*function
)(int),
588 void (*formatter
)(char*, size_t, int, const char*),
589 int32_t (*get_talk_id
)(int, int))
592 struct settings_list item
;
593 struct int_setting data
= {
594 function
, voice_unit
, min
, max
, step
,
595 formatter
, get_talk_id
597 item
.int_setting
= &data
;
598 item
.flags
= F_INT_SETTING
|F_T_INT
;
600 item
.cfg_vals
= (char*)string
;
601 item
.setting
= variable
;
602 return option_screen(&item
, false, NULL
);
606 void option_select_init_items(struct option_select
* opt
,
609 const struct opt_items
* items
,
614 opt
->max_value
=nb_items
;
615 opt
->option
=selected
;
619 void option_select_next(struct option_select
* opt
)
621 if(opt
->option
+ 1 >= opt
->max_value
)
623 if(opt
->option
==opt
->max_value
-1)
624 opt
->option
=opt
->min_value
;
626 opt
->option
=opt
->max_value
-1;
632 void option_select_prev(struct option_select
* opt
)
634 if(opt
->option
- 1 < opt
->min_value
)
636 /* the dissimilarity to option_select_next() arises from the
637 * sleep timer problem (bug #5000 and #5001):
638 * there we have min=0, step = 5 but the value itself might
639 * not be a multiple of 5 -- as time elapsed;
640 * We need to be able to set timer to 0 (= Off) nevertheless. */
641 if(opt
->option
!=opt
->min_value
)
642 opt
->option
=opt
->min_value
;
644 opt
->option
=opt
->max_value
-1;
650 const char * option_select_get_text(struct option_select
* opt
)
652 return(P2STR(opt
->items
[opt
->option
].string
));