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(const struct settings_list
*setting
, int selection
);
47 int option_value_as_int(const struct settings_list
*setting
)
49 int type
= (setting
->flags
& F_T_MASK
);
52 temp
= *(bool*)setting
->setting
?1:0;
53 else if (type
== F_T_UINT
|| type
== F_T_INT
)
54 temp
= *(int*)setting
->setting
;
57 static const char *unit_strings
[] =
59 [UNIT_INT
] = "", [UNIT_MS
] = "ms",
60 [UNIT_SEC
] = "s", [UNIT_MIN
] = "min",
61 [UNIT_HOUR
]= "hr", [UNIT_KHZ
] = "kHz",
62 [UNIT_DB
] = "dB", [UNIT_PERCENT
] = "%",
63 [UNIT_MAH
] = "mAh", [UNIT_PIXEL
] = "px",
64 [UNIT_PER_SEC
] = "per sec",
66 [UNIT_MB
] = "MB", [UNIT_KBIT
] = "kb/s",
67 [UNIT_PM_TICK
] = "units/10ms",
69 /* these two vars are needed so arbitrary values can be added to the
70 TABLE_SETTING settings if the F_ALLOW_ARBITRARY_VALS flag is set */
71 static int table_setting_oldval
= 0, table_setting_array_position
= 0;
72 char *option_get_valuestring(const struct settings_list
*setting
,
73 char *buffer
, int buf_len
,
76 if ((setting
->flags
& F_BOOL_SETTING
) == F_BOOL_SETTING
)
78 bool val
= (bool)temp_var
;
79 snprintf(buffer
, buf_len
, "%s",
80 str(val
? setting
->bool_setting
->lang_yes
:
81 setting
->bool_setting
->lang_no
));
83 #if 0 /* probably dont need this one */
84 else if ((setting
->flags
& F_FILENAME
) == F_FILENAME
)
86 struct filename_setting
*info
= setting
->filename_setting
;
87 snprintf(buffer
, buf_len
, "%s%s%s", info
->prefix
,
88 (char*)temp_var
, info
->suffix
);
91 else if (((setting
->flags
& F_INT_SETTING
) == F_INT_SETTING
) ||
92 ((setting
->flags
& F_TABLE_SETTING
) == F_TABLE_SETTING
))
94 const struct int_setting
*int_info
= setting
->int_setting
;
95 const struct table_setting
*tbl_info
= setting
->table_setting
;
97 void (*formatter
)(char*, size_t, int, const char*);
98 if ((setting
->flags
& F_INT_SETTING
) == F_INT_SETTING
)
100 formatter
= int_info
->formatter
;
101 unit
= unit_strings
[int_info
->unit
];
105 formatter
= tbl_info
->formatter
;
106 unit
= unit_strings
[tbl_info
->unit
];
109 formatter(buffer
, buf_len
, (int)temp_var
, unit
);
111 snprintf(buffer
, buf_len
, "%d %s", (int)temp_var
, unit
?unit
:"");
113 else if ((setting
->flags
& F_T_SOUND
) == F_T_SOUND
)
115 char sign
= ' ', *unit
;
116 unit
= (char*)sound_unit(setting
->sound_setting
->setting
);
117 if (sound_numdecimals(setting
->sound_setting
->setting
))
120 int val
= sound_val2phys(setting
->sound_setting
->setting
,
127 integer
= val
/ 10; dec
= val
% 10;
128 snprintf(buffer
, buf_len
, "%c%d.%d %s", sign
, integer
, dec
, unit
);
131 snprintf(buffer
, buf_len
, "%d %s", (int)temp_var
, unit
);
133 else if ((setting
->flags
& F_CHOICE_SETTING
) == F_CHOICE_SETTING
)
135 if (setting
->flags
& F_CHOICETALKS
)
138 const struct choice_setting
*info
= setting
->choice_setting
;
139 if (info
->talks
[(int)temp_var
] < LANG_LAST_INDEX_IN_ARRAY
)
141 snprintf(buffer
, buf_len
, "%s", str(info
->talks
[(int)temp_var
]));
145 find_setting(setting
->setting
, &setting_id
);
146 cfg_int_to_string(setting_id
, (int)temp_var
, buffer
, buf_len
);
151 int value
= (int)temp_var
;
152 char *val
= P2STR(setting
->choice_setting
->desc
[value
]);
153 snprintf(buffer
, buf_len
, "%s", val
);
158 void option_talk_value(const struct settings_list
*setting
, int value
, bool enqueue
)
160 if ((setting
->flags
& F_BOOL_SETTING
) == F_BOOL_SETTING
)
162 bool val
= value
==1?true:false;
163 talk_id(val
? setting
->bool_setting
->lang_yes
:
164 setting
->bool_setting
->lang_no
, enqueue
);
166 #if 0 /* probably dont need this one */
167 else if ((setting
->flags
& F_FILENAME
) == F_FILENAME
)
171 else if (((setting
->flags
& F_INT_SETTING
) == F_INT_SETTING
) ||
172 ((setting
->flags
& F_TABLE_SETTING
) == F_TABLE_SETTING
))
174 const struct int_setting
*int_info
= setting
->int_setting
;
175 const struct table_setting
*tbl_info
= setting
->table_setting
;
177 int32_t (*get_talk_id
)(int, int);
178 if ((setting
->flags
& F_INT_SETTING
) == F_INT_SETTING
)
180 unit
= int_info
->unit
;
181 get_talk_id
= int_info
->get_talk_id
;
185 unit
= tbl_info
->unit
;
186 get_talk_id
= tbl_info
->get_talk_id
;
189 talk_id(get_talk_id(value
, unit
), enqueue
);
191 talk_value(value
, unit
, enqueue
);
193 else if ((setting
->flags
& F_T_SOUND
) == F_T_SOUND
)
195 int talkunit
= UNIT_INT
;
196 const char *unit
= sound_unit(setting
->sound_setting
->setting
);
197 if (!strcmp(unit
, "dB"))
199 else if (!strcmp(unit
, "%"))
200 talkunit
= UNIT_PERCENT
;
201 else if (!strcmp(unit
, "Hz"))
202 talkunit
= UNIT_HERTZ
;
203 talk_value(value
, talkunit
, false);
205 else if ((setting
->flags
& F_CHOICE_SETTING
) == F_CHOICE_SETTING
)
207 if (setting
->flags
& F_CHOICETALKS
)
209 talk_id(setting
->choice_setting
->talks
[value
], enqueue
);
213 talk_id(P2ID(setting
->choice_setting
->desc
[value
]), enqueue
);
218 static int option_talk(int selected_item
, void * data
)
220 struct settings_list
*setting
= (struct settings_list
*)data
;
221 int temp_var
= selection_to_val(setting
, selected_item
);
222 option_talk_value(setting
, temp_var
, false);
226 #if defined(HAVE_QUICKSCREEN) || defined(HAVE_RECORDING)
227 /* only the quickscreen and recording trigger needs this */
228 void option_select_next_val(const struct settings_list
*setting
,
229 bool previous
, bool apply
)
232 int *value
= setting
->setting
;
233 if ((setting
->flags
& F_BOOL_SETTING
) == F_BOOL_SETTING
)
235 *(bool*)value
= !*(bool*)value
;
236 if (apply
&& setting
->bool_setting
->option_callback
)
237 setting
->bool_setting
->option_callback(*(bool*)value
);
240 else if ((setting
->flags
& F_INT_SETTING
) == F_INT_SETTING
)
242 struct int_setting
*info
= (struct int_setting
*)setting
->int_setting
;
243 int step
= info
->step
;
258 if (apply
&& info
->option_callback
)
259 info
->option_callback(val
);
261 else if ((setting
->flags
& F_T_SOUND
) == F_T_SOUND
)
263 int setting_id
= setting
->sound_setting
->setting
;
264 int steps
= sound_steps(setting_id
);
265 int min
= sound_min(setting_id
);
266 int max
= sound_max(setting_id
);
269 val
= *value
+ steps
;
275 val
= *value
- steps
;
280 else if ((setting
->flags
& F_CHOICE_SETTING
) == F_CHOICE_SETTING
)
282 struct choice_setting
*info
= (struct choice_setting
*)setting
->choice_setting
;
287 if (val
>= info
->count
)
296 if (apply
&& info
->option_callback
)
297 info
->option_callback(val
);
299 else if ((setting
->flags
& F_TABLE_SETTING
) == F_TABLE_SETTING
)
301 const struct table_setting
*tbl_info
= setting
->table_setting
;
303 add
= previous
?tbl_info
->count
-1:1;
304 for (i
=0; i
<tbl_info
->count
;i
++)
306 if ((*value
== tbl_info
->values
[i
]) ||
307 (settings
->flags
&F_ALLOW_ARBITRARY_VALS
&&
308 *value
< tbl_info
->values
[i
]))
310 val
= tbl_info
->values
[(i
+add
)%tbl_info
->count
];
319 static int selection_to_val(const struct settings_list
*setting
, int selection
)
321 int min
= 0, max
= 0, step
= 1;
322 if (((setting
->flags
& F_BOOL_SETTING
) == F_BOOL_SETTING
) ||
323 ((setting
->flags
& F_CHOICE_SETTING
) == F_CHOICE_SETTING
))
325 else if ((setting
->flags
& F_TABLE_SETTING
) == F_TABLE_SETTING
)
327 const struct table_setting
*info
= setting
->table_setting
;
328 if (setting
->flags
&F_ALLOW_ARBITRARY_VALS
&&
329 table_setting_array_position
!= -1 &&
330 (selection
>= table_setting_array_position
))
332 if (selection
== table_setting_array_position
)
333 return table_setting_oldval
;
334 return info
->values
[selection
-1];
337 return info
->values
[selection
];
339 else if ((setting
->flags
& F_T_SOUND
) == F_T_SOUND
)
341 int setting_id
= setting
->sound_setting
->setting
;
342 #ifndef ASCENDING_INT_SETTINGS
343 step
= sound_steps(setting_id
);
344 max
= sound_max(setting_id
);
345 min
= sound_min(setting_id
);
347 step
= -sound_steps(setting_id
);
348 min
= sound_max(setting_id
);
349 max
= sound_min(setting_id
);
352 else if ((setting
->flags
& F_INT_SETTING
) == F_INT_SETTING
)
354 const struct int_setting
*info
= setting
->int_setting
;
355 #ifndef ASCENDING_INT_SETTINGS
365 return max
- (selection
* step
);
367 static char * value_setting_get_name_cb(int selected_item
,
372 selected_item
= selection_to_val(data
, selected_item
);
373 return option_get_valuestring(data
, buffer
, buffer_len
, selected_item
);
376 /* wrapper to convert from int param to bool param in option_screen */
377 static void (*boolfunction
)(bool);
378 static void bool_funcwrapper(int value
)
386 static void val_to_selection(const struct settings_list
*setting
, int oldvalue
,
387 int *nb_items
, int *selected
,
388 void (**function
)(int))
390 int var_type
= setting
->flags
&F_T_MASK
;
391 /* set the number of items and current selection */
392 if (var_type
== F_T_INT
|| var_type
== F_T_UINT
)
394 if (setting
->flags
&F_CHOICE_SETTING
)
396 *nb_items
= setting
->choice_setting
->count
;
397 *selected
= oldvalue
;
398 *function
= setting
->choice_setting
->option_callback
;
400 else if (setting
->flags
&F_TABLE_SETTING
)
402 const struct table_setting
*info
= setting
->table_setting
;
404 *nb_items
= info
->count
;
406 table_setting_array_position
= -1;
407 for (i
=0;*selected
==-1 && i
<*nb_items
;i
++)
409 if (setting
->flags
&F_ALLOW_ARBITRARY_VALS
&&
410 (oldvalue
< info
->values
[i
]))
412 table_setting_oldval
= oldvalue
;
413 table_setting_array_position
= i
;
417 else if (oldvalue
== info
->values
[i
])
420 *function
= info
->option_callback
;
422 else if (setting
->flags
&F_T_SOUND
)
424 int setting_id
= setting
->sound_setting
->setting
;
425 int steps
= sound_steps(setting_id
);
426 int min
= sound_min(setting_id
);
427 int max
= sound_max(setting_id
);
428 *nb_items
= (max
-min
)/steps
+ 1;
429 #ifndef ASCENDING_INT_SETTINGS
430 *selected
= (max
- oldvalue
) / steps
;
432 *selected
= (oldvalue
- min
) / steps
;
434 *function
= sound_get_fn(setting_id
);
438 const struct int_setting
*info
= setting
->int_setting
;
443 *nb_items
= (max
-min
)/step
+ 1;
444 #ifndef ASCENDING_INT_SETTINGS
445 *selected
= (max
- oldvalue
) / step
;
447 *selected
= (oldvalue
- min
) / step
;
449 *function
= info
->option_callback
;
452 else if (var_type
== F_T_BOOL
)
454 *selected
= oldvalue
;
456 boolfunction
= setting
->bool_setting
->option_callback
;
458 *function
= bool_funcwrapper
;
462 bool option_screen(const struct settings_list
*setting
,
463 struct viewport parent
[NB_SCREENS
],
464 bool use_temp_var
, unsigned char* option_title
)
468 struct gui_synclist lists
;
469 int oldvalue
, nb_items
= 0, selected
= 0, temp_var
;
471 bool allow_wrap
= setting
->flags
& F_NO_WRAP
? false : true;
472 int var_type
= setting
->flags
&F_T_MASK
;
473 void (*function
)(int) = NULL
;
475 if (var_type
== F_T_INT
|| var_type
== F_T_UINT
)
477 variable
= use_temp_var
? &temp_var
: (int*)setting
->setting
;
478 temp_var
= oldvalue
= *(int*)setting
->setting
;
480 else if (var_type
== F_T_BOOL
)
482 /* bools always use the temp variable...
483 if use_temp_var is false it will be copied to setting->setting every change */
484 variable
= &temp_var
;
485 temp_var
= oldvalue
= *(bool*)setting
->setting
?1:0;
487 else return false; /* only int/bools can go here */
488 gui_synclist_init(&lists
, value_setting_get_name_cb
,
489 (void*)setting
, false, 1, parent
);
490 if (setting
->lang_id
== -1)
491 title
= (char*)setting
->cfg_vals
;
493 title
= P2STR(option_title
);
495 gui_synclist_set_title(&lists
, title
, Icon_Questionmark
);
496 gui_synclist_set_icon_callback(&lists
, NULL
);
497 if(global_settings
.talk_menu
)
498 gui_synclist_set_voice_callback(&lists
, option_talk
);
500 val_to_selection(setting
, oldvalue
, &nb_items
, &selected
, &function
);
501 gui_synclist_set_nb_items(&lists
, nb_items
);
502 gui_synclist_select_item(&lists
, selected
);
504 gui_synclist_limit_scroll(&lists
, true);
505 gui_synclist_draw(&lists
);
507 gui_synclist_speak_item(&lists
);
508 gui_syncstatusbar_draw(&statusbars
, false);
511 if (list_do_action(CONTEXT_LIST
, TIMEOUT_BLOCK
,
513 allow_wrap
? LIST_WRAP_UNLESS_HELD
: LIST_WRAP_OFF
))
515 selected
= gui_synclist_get_sel_pos(&lists
);
516 *variable
= selection_to_val(setting
, selected
);
517 if (var_type
== F_T_BOOL
)
520 *(bool*)setting
->setting
= selected
==1?true:false;
523 else if (action
== ACTION_NONE
)
525 else if (action
== ACTION_STD_CANCEL
)
527 bool show_cancel
= false;
530 else if (var_type
== F_T_INT
|| var_type
== F_T_UINT
)
532 if (*variable
!= oldvalue
)
535 *variable
= oldvalue
;
540 if (*variable
!= oldvalue
)
544 *(bool*)setting
->setting
= oldvalue
==1?true:false;
545 *variable
= oldvalue
;
549 gui_syncsplash(HZ
/2, ID2P(LANG_CANCEL
));
552 else if (action
== ACTION_STD_CONTEXT
)
554 reset_setting(setting
, variable
);
555 if (var_type
== F_T_BOOL
&& !use_temp_var
)
556 *(bool*)setting
->setting
= temp_var
==1?true:false;
557 val_to_selection(setting
, *variable
, &nb_items
,
558 &selected
, &function
);
559 gui_synclist_select_item(&lists
, selected
);
560 gui_synclist_draw(&lists
);
561 gui_synclist_speak_item(&lists
);
563 else if (action
== ACTION_STD_OK
)
567 else if(default_event_handler(action
) == SYS_USB_CONNECTED
)
569 gui_syncstatusbar_draw(&statusbars
, false);
575 if (oldvalue
!= *variable
&& (action
!= ACTION_STD_CANCEL
))
579 if (var_type
== F_T_INT
|| var_type
== F_T_UINT
)
580 *(int*)setting
->setting
= *variable
;
582 *(bool*)setting
->setting
= *variable
?true:false;