Fix redraw issues when the statusbar setting was changed with an UI viewport. Now...
[kugel-rb.git] / apps / menus / display_menu.c
blob0b2769831ec58e59ec6167844ab5975b041e9c28
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 Jonathan Gordon
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include <stdbool.h>
23 #include <stddef.h>
24 #include <limits.h>
25 #include "config.h"
26 #include "appevents.h"
27 #include "lang.h"
28 #include "action.h"
29 #include "settings.h"
30 #include "menu.h"
31 #include "tree.h"
32 #include "list.h"
33 #ifdef HAVE_LCD_BITMAP
34 #include "peakmeter.h"
35 #endif
36 #include "talk.h"
37 #include "lcd.h"
38 #include "lcd-remote.h"
39 #ifdef HAVE_TOUCHSCREEN
40 #include "screens.h"
41 #endif
42 #include "viewport.h"
43 #include "statusbar.h" /* statusbar_vals enum*/
45 #ifdef HAVE_BACKLIGHT
46 static int filterfirstkeypress_callback(int action,const struct menu_item_ex *this_item)
48 (void)this_item;
49 switch (action)
51 case ACTION_EXIT_MENUITEM:
52 set_backlight_filter_keypress(global_settings.bl_filter_first_keypress);
53 #ifdef HAVE_REMOTE_LCD
54 set_remote_backlight_filter_keypress(
55 global_settings.remote_bl_filter_first_keypress);
56 #endif
58 break;
60 return action;
62 #endif
63 #ifdef HAVE_LCD_FLIP
64 static int flipdisplay_callback(int action,const struct menu_item_ex *this_item)
66 (void)this_item;
67 switch (action)
69 case ACTION_EXIT_MENUITEM:
70 button_set_flip(global_settings.flip_display);
71 lcd_set_flip(global_settings.flip_display);
72 lcd_update();
73 #ifdef HAVE_REMOTE_LCD
74 lcd_remote_set_flip(global_settings.remote_flip_display);
75 lcd_remote_update();
76 #endif
77 break;
79 return action;
81 #endif
83 /***********************************/
84 /* LCD MENU */
85 #ifdef HAVE_BACKLIGHT
86 MENUITEM_SETTING(backlight_timeout, &global_settings.backlight_timeout, NULL);
87 #if CONFIG_CHARGING
88 MENUITEM_SETTING(backlight_timeout_plugged,
89 &global_settings.backlight_timeout_plugged, NULL);
90 #endif
91 #ifdef HAS_BUTTON_HOLD
92 MENUITEM_SETTING(backlight_on_button_hold,
93 &global_settings.backlight_on_button_hold, NULL);
94 #endif
95 MENUITEM_SETTING(caption_backlight, &global_settings.caption_backlight, NULL);
96 #if defined(HAVE_BACKLIGHT_FADING_INT_SETTING) \
97 || defined(HAVE_BACKLIGHT_FADING_BOOL_SETTING)
98 MENUITEM_SETTING(backlight_fade_in, &global_settings.backlight_fade_in, NULL);
99 MENUITEM_SETTING(backlight_fade_out, &global_settings.backlight_fade_out, NULL);
100 #endif
101 MENUITEM_SETTING(bl_filter_first_keypress,
102 &global_settings.bl_filter_first_keypress,
103 filterfirstkeypress_callback);
104 #ifdef HAVE_LCD_SLEEP_SETTING
105 MENUITEM_SETTING(lcd_sleep_after_backlight_off,
106 &global_settings.lcd_sleep_after_backlight_off, NULL);
107 #endif
108 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
109 MENUITEM_SETTING(brightness_item, &global_settings.brightness, NULL);
110 #endif
111 #endif /* HAVE_BACKLIGHT */
112 #ifdef HAVE_LCD_CONTRAST
113 MENUITEM_SETTING(contrast, &global_settings.contrast, NULL);
114 #endif
115 #ifdef HAVE_LCD_BITMAP
116 #ifdef HAVE_LCD_INVERT
117 MENUITEM_SETTING(invert, &global_settings.invert, NULL);
118 #endif
119 #ifdef HAVE_LCD_FLIP
120 MENUITEM_SETTING(flip_display, &global_settings.flip_display, flipdisplay_callback);
121 #endif
122 #endif /* HAVE_LCD_BITMAP */
124 /* now the actual menu */
125 MAKE_MENU(lcd_settings,ID2P(LANG_LCD_MENU),
126 NULL, Icon_Display_menu
127 #ifdef HAVE_BACKLIGHT
128 ,&backlight_timeout
129 # if CONFIG_CHARGING
130 ,&backlight_timeout_plugged
131 # endif
132 # ifdef HAS_BUTTON_HOLD
133 ,&backlight_on_button_hold
134 # endif
135 ,&caption_backlight
136 #if defined(HAVE_BACKLIGHT_FADING_INT_SETTING) \
137 || defined(HAVE_BACKLIGHT_FADING_BOOL_SETTING)
138 ,&backlight_fade_in, &backlight_fade_out
139 #endif
140 ,&bl_filter_first_keypress
141 # ifdef HAVE_LCD_SLEEP_SETTING
142 ,&lcd_sleep_after_backlight_off
143 # endif
144 # ifdef HAVE_BACKLIGHT_BRIGHTNESS
145 ,&brightness_item
146 # endif
147 #endif /* HAVE_BACKLIGHT */
148 #ifdef HAVE_LCD_CONTRAST
149 ,&contrast
150 #endif
151 #ifdef HAVE_LCD_BITMAP
152 # ifdef HAVE_LCD_INVERT
153 ,&invert
154 # endif
155 # ifdef HAVE_LCD_FLIP
156 ,&flip_display
157 # endif
158 #endif /* HAVE_LCD_BITMAP */
160 /* LCD MENU */
161 /***********************************/
164 /********************************/
165 /* Remote LCD settings menu */
166 #ifdef HAVE_REMOTE_LCD
167 MENUITEM_SETTING(remote_backlight_timeout,
168 &global_settings.remote_backlight_timeout, NULL);
170 #if CONFIG_CHARGING
171 MENUITEM_SETTING(remote_backlight_timeout_plugged,
172 &global_settings.remote_backlight_timeout_plugged, NULL);
173 #endif
175 #ifdef HAS_REMOTE_BUTTON_HOLD
176 MENUITEM_SETTING(remote_backlight_on_button_hold,
177 &global_settings.remote_backlight_on_button_hold, NULL);
178 #endif
180 MENUITEM_SETTING(remote_caption_backlight,
181 &global_settings.remote_caption_backlight, NULL);
182 MENUITEM_SETTING(remote_bl_filter_first_keypress,
183 &global_settings.remote_bl_filter_first_keypress,
184 filterfirstkeypress_callback);
185 MENUITEM_SETTING(remote_contrast,
186 &global_settings.remote_contrast, NULL);
187 MENUITEM_SETTING(remote_invert,
188 &global_settings.remote_invert, NULL);
190 #ifdef HAVE_LCD_FLIP
191 MENUITEM_SETTING(remote_flip_display,
192 &global_settings.remote_flip_display, flipdisplay_callback);
193 #endif
195 #ifdef HAVE_REMOTE_LCD_TICKING
196 static int ticking_callback(int action,const struct menu_item_ex *this_item)
198 (void)this_item;
199 switch (action)
201 case ACTION_EXIT_MENUITEM:
202 lcd_remote_emireduce(global_settings.remote_reduce_ticking);
203 break;
205 return action;
207 MENUITEM_SETTING(remote_reduce_ticking,
208 &global_settings.remote_reduce_ticking, ticking_callback);
209 #endif
211 MAKE_MENU(lcd_remote_settings, ID2P(LANG_LCD_REMOTE_MENU),
212 NULL, Icon_Remote_Display_menu,
213 &remote_backlight_timeout,
214 #if CONFIG_CHARGING
215 &remote_backlight_timeout_plugged,
216 #endif
217 #ifdef HAS_REMOTE_BUTTON_HOLD
218 &remote_backlight_on_button_hold,
219 #endif
220 &remote_caption_backlight, &remote_bl_filter_first_keypress,
221 &remote_contrast, &remote_invert
223 #ifdef HAVE_LCD_FLIP
224 ,&remote_flip_display
225 #endif
226 #ifdef HAVE_REMOTE_LCD_TICKING
227 ,&remote_reduce_ticking
228 #endif
231 #endif /* HAVE_REMOTE_LCD */
232 /* Remote LCD settings menu */
233 /********************************/
235 /***********************************/
236 /* SCROLL MENU */
237 MENUITEM_SETTING_W_TEXT(scroll_speed, &global_settings.scroll_speed,
238 ID2P(LANG_SCROLL), NULL);
239 MENUITEM_SETTING(scroll_delay, &global_settings.scroll_delay, NULL);
240 #ifdef HAVE_LCD_BITMAP
241 MENUITEM_SETTING_W_TEXT(scroll_step, &global_settings.scroll_step,
242 ID2P(LANG_SCROLL_STEP_EXAMPLE), NULL);
243 #endif
244 MENUITEM_SETTING(bidir_limit, &global_settings.bidir_limit, NULL);
245 #ifdef HAVE_REMOTE_LCD
246 MENUITEM_SETTING_W_TEXT(remote_scroll_speed, &global_settings.remote_scroll_speed,
247 ID2P(LANG_SCROLL), NULL);
248 MENUITEM_SETTING(remote_scroll_delay, &global_settings.remote_scroll_delay, NULL);
249 MENUITEM_SETTING_W_TEXT(remote_scroll_step, &global_settings.remote_scroll_step,
250 ID2P(LANG_SCROLL_STEP_EXAMPLE), NULL);
251 MENUITEM_SETTING(remote_bidir_limit, &global_settings.remote_bidir_limit, NULL);
253 MAKE_MENU(remote_scroll_sets, ID2P(LANG_REMOTE_SCROLL_SETS), 0, Icon_NOICON,
254 &remote_scroll_speed, &remote_scroll_delay,
255 &remote_scroll_step, &remote_bidir_limit);
256 #endif /* HAVE_REMOTE_LCD */
257 #ifdef HAVE_LCD_CHARCELLS
258 MENUITEM_SETTING(jump_scroll, &global_settings.jump_scroll, NULL);
259 MENUITEM_SETTING(jump_scroll_delay, &global_settings.jump_scroll_delay, NULL);
260 #endif
261 /* list acceleration */
262 #ifndef HAVE_WHEEL_ACCELERATION
263 MENUITEM_SETTING(list_accel_start_delay,
264 &global_settings.list_accel_start_delay, NULL);
265 MENUITEM_SETTING(list_accel_wait, &global_settings.list_accel_wait, NULL);
266 #endif /* HAVE_WHEEL_ACCELERATION */
267 #ifdef HAVE_LCD_BITMAP
268 static int screenscroll_callback(int action,const struct menu_item_ex *this_item)
270 (void)this_item;
271 switch (action)
273 case ACTION_EXIT_MENUITEM:
274 gui_list_screen_scroll_out_of_view(global_settings.offset_out_of_view);
275 break;
277 return action;
279 MENUITEM_SETTING(offset_out_of_view, &global_settings.offset_out_of_view,
280 screenscroll_callback);
281 MENUITEM_SETTING(screen_scroll_step, &global_settings.screen_scroll_step, NULL);
282 #endif
283 MENUITEM_SETTING(scroll_paginated, &global_settings.scroll_paginated, NULL);
285 MAKE_MENU(scroll_settings_menu, ID2P(LANG_SCROLL_MENU), 0, Icon_NOICON,
286 &scroll_speed, &scroll_delay,
287 #ifdef HAVE_LCD_BITMAP
288 &scroll_step,
289 #endif
290 &bidir_limit,
291 #ifdef HAVE_REMOTE_LCD
292 &remote_scroll_sets,
293 #endif
294 #ifdef HAVE_LCD_CHARCELLS
295 &jump_scroll, &jump_scroll_delay,
296 #endif
297 #ifdef HAVE_LCD_BITMAP
298 &offset_out_of_view, &screen_scroll_step,
299 #endif
300 &scroll_paginated,
301 #ifndef HAVE_WHEEL_ACCELERATION
302 &list_accel_start_delay, &list_accel_wait
303 #endif
305 /* SCROLL MENU */
306 /***********************************/
308 /***********************************/
309 /* BARS MENU */
310 #ifdef HAVE_LCD_BITMAP
311 static int statusbar_callback_ex(int action,const struct menu_item_ex *this_item,
312 enum screen_type screen)
314 (void)this_item;
315 /* we save the old statusbar value here, so the old statusbars can get
316 * removed and cleared from the display properly on exiting
317 * (in gui_statusbar_changed() ) */
318 static enum statusbar_values old_bar[NB_SCREENS];
319 switch (action)
321 case ACTION_ENTER_MENUITEM:
322 #ifdef HAVE_REMOTE_LCD
323 if (screen == SCREEN_REMOTE)
324 old_bar[screen] = global_settings.remote_statusbar;
325 else
326 #endif
327 old_bar[screen] = global_settings.statusbar;
328 break;
329 case ACTION_EXIT_MENUITEM:
330 gui_statusbar_changed(screen, old_bar[screen]);
331 send_event(GUI_EVENT_STATUSBAR_TOGGLE, NULL);
332 send_event(GUI_EVENT_ACTIONUPDATE, (void*)true);
333 break;
335 return action;
338 #ifdef HAVE_REMOTE_LCD
339 static int statusbar_callback_remote(int action,const struct menu_item_ex *this_item)
341 return statusbar_callback_ex(action, this_item, SCREEN_REMOTE);
343 #endif
344 static int statusbar_callback(int action,const struct menu_item_ex *this_item)
346 return statusbar_callback_ex(action, this_item, SCREEN_MAIN);
348 MENUITEM_SETTING(scrollbar_item, &global_settings.scrollbar, NULL);
349 MENUITEM_SETTING(scrollbar_width, &global_settings.scrollbar_width, NULL);
350 MENUITEM_SETTING(statusbar, &global_settings.statusbar,
351 statusbar_callback);
352 #ifdef HAVE_REMOTE_LCD
353 MENUITEM_SETTING(remote_statusbar, &global_settings.remote_statusbar,
354 statusbar_callback_remote);
355 #endif
356 #if CONFIG_KEYPAD == RECORDER_PAD
357 MENUITEM_SETTING(buttonbar, &global_settings.buttonbar, NULL);
358 #endif
359 MENUITEM_SETTING(volume_type, &global_settings.volume_type, NULL);
360 MENUITEM_SETTING(battery_display, &global_settings.battery_display, NULL);
361 MAKE_MENU(bars_menu, ID2P(LANG_BARS_MENU), 0, Icon_NOICON,
362 &scrollbar_item, &scrollbar_width, &statusbar,
363 #ifdef HAVE_REMOTE_LCD
364 &remote_statusbar,
365 #endif
366 #if CONFIG_KEYPAD == RECORDER_PAD
367 &buttonbar,
368 #endif
369 &volume_type, &battery_display);
370 #endif /* HAVE_LCD_BITMAP */
371 /* BARS MENU */
372 /***********************************/
375 /***********************************/
376 /* PEAK METER MENU */
378 #ifdef HAVE_LCD_BITMAP
379 static int peakmeter_callback(int action,const struct menu_item_ex *this_item)
381 (void)this_item;
382 switch (action)
384 case ACTION_EXIT_MENUITEM:
385 peak_meter_init_times(global_settings.peak_meter_release,
386 global_settings.peak_meter_hold,
387 global_settings.peak_meter_clip_hold);
388 break;
390 return action;
392 MENUITEM_SETTING(peak_meter_hold,
393 &global_settings.peak_meter_hold, peakmeter_callback);
394 MENUITEM_SETTING(peak_meter_clip_hold,
395 &global_settings.peak_meter_clip_hold, peakmeter_callback);
396 #ifdef HAVE_RECORDING
397 MENUITEM_SETTING(peak_meter_clipcounter,
398 &global_settings.peak_meter_clipcounter, NULL);
399 #endif
400 MENUITEM_SETTING(peak_meter_release,
401 &global_settings.peak_meter_release, peakmeter_callback);
403 * Menu to select wether the scale of the meter
404 * displays dBfs of linear values.
406 static int peak_meter_scale(void) {
407 bool retval = false;
408 bool use_dbfs = global_settings.peak_meter_dbfs;
409 retval = set_bool_options(str(LANG_PM_SCALE),
410 &use_dbfs,
411 STR(LANG_PM_DBFS), STR(LANG_PM_LINEAR),
412 NULL);
414 /* has the user really changed the scale? */
415 if (use_dbfs != global_settings.peak_meter_dbfs) {
417 /* store the change */
418 global_settings.peak_meter_dbfs = use_dbfs;
419 peak_meter_set_use_dbfs(use_dbfs);
421 /* If the user changed the scale mode the meaning of
422 peak_meter_min (peak_meter_max) has changed. Thus we have
423 to convert the values stored in global_settings. */
424 if (use_dbfs) {
426 /* we only store -dBfs */
427 global_settings.peak_meter_min = -peak_meter_get_min() / 100;
428 global_settings.peak_meter_max = -peak_meter_get_max() / 100;
430 /* limit the returned value to the allowed range */
431 if(global_settings.peak_meter_min > 89)
432 global_settings.peak_meter_min = 89;
433 } else {
434 int max;
436 /* linear percent */
437 global_settings.peak_meter_min = peak_meter_get_min();
439 /* converting dBfs -> percent results in a precision loss.
440 I assume that the user doesn't bother that conversion
441 dBfs <-> percent isn't symmetrical for odd values but that
442 he wants 0 dBfs == 100%. Thus I 'correct' the percent value
443 resulting from dBfs -> percent manually here */
444 max = peak_meter_get_max();
445 global_settings.peak_meter_max = max < 99 ? max : 100;
447 settings_apply_pm_range();
449 return retval;
453 * Adjust the min value of the value range that
454 * the peak meter shall visualize.
456 static int peak_meter_min(void) {
457 bool retval = false;
458 if (global_settings.peak_meter_dbfs) {
460 /* for dBfs scale */
461 int range_max = -global_settings.peak_meter_max;
462 int min = -global_settings.peak_meter_min;
464 retval = set_int(str(LANG_PM_MIN), str(LANG_PM_DBFS), UNIT_DB,
465 &min, NULL, 1, -89, range_max, NULL);
467 global_settings.peak_meter_min = - min;
470 /* for linear scale */
471 else {
472 int min = global_settings.peak_meter_min;
474 retval = set_int(str(LANG_PM_MIN), "%", UNIT_PERCENT,
475 &min, NULL,
476 1, 0, global_settings.peak_meter_max - 1, NULL);
478 global_settings.peak_meter_min = (unsigned char)min;
481 settings_apply_pm_range();
482 return retval;
487 * Adjust the max value of the value range that
488 * the peak meter shall visualize.
490 static int peak_meter_max(void) {
491 bool retval = false;
492 if (global_settings.peak_meter_dbfs) {
494 /* for dBfs scale */
495 int range_min = -global_settings.peak_meter_min;
496 int max = -global_settings.peak_meter_max;
498 retval = set_int(str(LANG_PM_MAX), str(LANG_PM_DBFS), UNIT_DB,
499 &max, NULL, 1, range_min, 0, NULL);
501 global_settings.peak_meter_max = - max;
505 /* for linear scale */
506 else {
507 int max = global_settings.peak_meter_max;
509 retval = set_int(str(LANG_PM_MAX), "%", UNIT_PERCENT,
510 &max, NULL,
511 1, global_settings.peak_meter_min + 1, 100, NULL);
513 global_settings.peak_meter_max = (unsigned char)max;
516 settings_apply_pm_range();
517 return retval;
519 MENUITEM_FUNCTION(peak_meter_scale_item, 0, ID2P(LANG_PM_SCALE),
520 peak_meter_scale, NULL, NULL, Icon_NOICON);
521 MENUITEM_FUNCTION(peak_meter_min_item, 0, ID2P(LANG_PM_MIN),
522 peak_meter_min, NULL, NULL, Icon_NOICON);
523 MENUITEM_FUNCTION(peak_meter_max_item, 0, ID2P(LANG_PM_MAX),
524 peak_meter_max, NULL, NULL, Icon_NOICON);
525 MAKE_MENU(peak_meter_menu, ID2P(LANG_PM_MENU), NULL, Icon_NOICON,
526 &peak_meter_release, &peak_meter_hold,
527 &peak_meter_clip_hold,
528 #ifdef HAVE_RECORDING
529 &peak_meter_clipcounter,
530 #endif
531 &peak_meter_scale_item, &peak_meter_min_item, &peak_meter_max_item);
532 #endif /* HAVE_LCD_BITMAP */
533 /* PEAK METER MENU */
534 /***********************************/
537 #ifdef HAVE_TOUCHSCREEN
538 static int touch_mode_callback(int action,const struct menu_item_ex *this_item)
540 (void)this_item;
541 switch (action)
543 case ACTION_EXIT_MENUITEM: /* on exit */
544 touchscreen_set_mode(global_settings.touch_mode);
545 break;
547 return action;
549 MENUITEM_SETTING(touch_mode, &global_settings.touch_mode, touch_mode_callback);
551 MENUITEM_FUNCTION(touchscreen_menu_calibrate, 0, ID2P(LANG_TOUCHSCREEN_CALIBRATE), calibrate,
552 NULL, NULL, Icon_NOICON);
553 MENUITEM_FUNCTION(touchscreen_menu_reset_calibration, 0, ID2P(LANG_TOUCHSCREEN_RESET_CALIBRATION), reset_mapping,
554 NULL, NULL, Icon_NOICON);
556 MAKE_MENU(touchscreen_menu, ID2P(LANG_TOUCHSCREEN_SETTINGS), NULL, Icon_NOICON, &touch_mode,
557 &touchscreen_menu_calibrate, &touchscreen_menu_reset_calibration);
558 #endif
561 MENUITEM_SETTING(codepage_setting, &global_settings.default_codepage, NULL);
564 MAKE_MENU(display_menu, ID2P(LANG_DISPLAY),
565 NULL, Icon_Display_menu,
566 &lcd_settings,
567 #ifdef HAVE_REMOTE_LCD
568 &lcd_remote_settings,
569 #endif
570 &scroll_settings_menu,
571 #ifdef HAVE_LCD_BITMAP
572 &bars_menu, &peak_meter_menu,
573 #endif
574 &codepage_setting,
575 #ifdef HAVE_TOUCHSCREEN
576 &touchscreen_menu,
577 #endif