Manual: The c200v2 also needs to be set to MSC mode for installation.
[maemo-rb.git] / apps / gui / option_select.c
blobd42d08188a0627de35a85cf2bf0a4cfe91d96f1c
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
22 #include <stdlib.h>
23 #include "string-extra.h"
24 #include "config.h"
25 #include "system.h"
26 #include "option_select.h"
27 #include "kernel.h"
28 #include "lang.h"
29 #include "talk.h"
30 #include "settings_list.h"
31 #include "sound.h"
32 #include "list.h"
33 #include "action.h"
34 #include "misc.h"
35 #include "splash.h"
36 #include "menu.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);
44 int temp = 0;
45 if (type == F_T_BOOL)
46 temp = *(bool*)setting->setting?1:0;
47 else if (type == F_T_UINT || type == F_T_INT)
48 temp = *(int*)setting->setting;
49 return temp;
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",
59 [UNIT_HERTZ] = "Hz",
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,
68 intptr_t temp_var)
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);
84 #endif
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;
90 const char *unit;
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];
97 else
99 formatter = tbl_info->formatter;
100 unit = unit_strings[tbl_info->unit];
102 if (formatter)
103 str = formatter(buffer, buf_len, (int)temp_var, unit);
104 else
105 snprintf(buffer, buf_len, "%d %s", (int)temp_var, unit?unit:"");
107 else if ((setting->flags & F_T_SOUND) == F_T_SOUND)
109 char sign = ' ';
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))
114 int integer, dec;
115 if(val < 0)
117 sign = '-';
118 val = abs(val);
120 integer = val / 10;
121 dec = val % 10;
122 snprintf(buffer, buf_len, "%c%d.%d %s", sign, integer, dec, unit);
124 else
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)
131 int setting_id;
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);
137 else
139 find_setting(setting->setting, &setting_id);
140 cfg_int_to_string(setting_id, (int)temp_var, buffer, buf_len);
143 else
145 int value = (int)temp_var;
146 char *val = P2STR(setting->choice_setting->desc[value]);
147 strlcpy(buffer, val, buf_len);
150 return str;
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)
164 #endif
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;
170 int unit;
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;
177 else
179 unit = tbl_info->unit;
180 get_talk_id = tbl_info->get_talk_id;
182 if (get_talk_id)
183 talk_id(get_talk_id(value, unit), enqueue);
184 else
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"))
195 talkunit = 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);
208 else
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);
220 return 0;
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)
228 int val = 0;
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);
235 return;
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);
241 if (!previous)
243 val = *value + info->step;
244 if (neg_step ? (val < info->max) : (val > info->max))
245 val = info->min;
247 else
249 val = *value - info->step;
250 if (neg_step ? (val > info->min) : (val < info->min))
251 val = info->max;
253 *value = val;
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);
263 if (!previous)
265 val = *value + steps;
266 if (val >= max)
267 val = min;
269 else
271 val = *value - steps;
272 if (val < min)
273 val = max;
275 *value = val;
276 if (apply)
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;
282 if (!previous)
284 val = *value + 1;
285 if (val >= info->count)
286 val = 0;
288 else
290 val = *value - 1;
291 if (val < 0)
292 val = info->count-1;
294 *value = val;
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;
301 int i, add;
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];
310 break;
313 *value = val;
314 if (apply && tbl_info->option_callback)
315 tbl_info->option_callback(val);
318 #endif
320 static int selection_to_val(const struct settings_list *setting, int selection)
322 /* rockbox: comment 'set but unused' variables
323 int min = 0;
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))
328 return selection;
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];
340 else
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); */
350 #else
351 step = -sound_steps(setting_id);
352 /* min = sound_max(setting_id); */
353 max = sound_min(setting_id);
354 #endif
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; */
361 max = info->max;
362 step = info->step;
363 #else
364 max = info->min;
365 /* min = info->max; */
366 step = -info->step;
367 #endif
369 return max- (selection * step);
372 static const char * value_setting_get_name_cb(int selected_item,
373 void * data,
374 char *buffer,
375 size_t buffer_len)
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)
385 if (value)
386 boolfunction(true);
387 else
388 boolfunction(false);
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;
408 int i;
409 *nb_items = info->count;
410 *selected = -1;
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;
419 *selected = i;
420 (*nb_items)++;
422 else if (oldvalue == info->values[i])
423 *selected = 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;
436 #else
437 *selected = (oldvalue - min) / steps;
438 #endif
439 *function = sound_get_fn(setting_id);
441 else
443 const struct int_setting *info = setting->int_setting;
444 int min, max, step;
445 max = info->max;
446 min = info->min;
447 step = info->step;
448 *nb_items = (max-min)/step + 1;
449 #ifndef ASCENDING_INT_SETTINGS
450 *selected = (max - oldvalue) / step;
451 #else
452 *selected = (oldvalue - min) / step;
453 #endif
454 *function = info->option_callback;
457 else if (var_type == F_T_BOOL)
459 *selected = oldvalue;
460 *nb_items = 2;
461 boolfunction = setting->bool_setting->option_callback;
462 if (boolfunction)
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)
471 int action;
472 bool done = false;
473 struct gui_synclist lists;
474 int oldvalue, nb_items = 0, selected = 0, temp_var;
475 int *variable;
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;
479 char *title;
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;
498 else
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);
512 /* talk the item */
513 gui_synclist_speak_item(&lists);
514 while (!done)
516 if (list_do_action(CONTEXT_LIST, HZ, /* HZ so the status bar redraws */
517 &lists, &action,
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)
527 continue;
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));
538 done = true;
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 */
555 if (use_temp_var)
557 if (var_type == F_T_INT || var_type == F_T_UINT)
558 *(int*)setting->setting = *variable;
559 else
560 *(bool*)setting->setting = (*variable==1);
562 settings_save();
563 done = true;
565 else if(default_event_handler(action) == SYS_USB_CONNECTED)
566 return true;
567 /* callback */
568 if ( function )
569 function(*variable);
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();
575 return false;
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;
583 int oldvalue;
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;
593 else
595 *val = 0;
596 *count = 1;
597 return false; /* only int/bools can go here */
600 val_to_selection(setting, oldvalue, count, val, &function);
601 return true;
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;
620 #endif