summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/SOURCES3
-rw-r--r--apps/action.c466
-rw-r--r--apps/action.h102
-rw-r--r--apps/gui/mask_select.c287
-rw-r--r--apps/gui/mask_select.h41
-rw-r--r--apps/lang/english.lang168
-rw-r--r--apps/menus/display_menu.c123
-rw-r--r--apps/menus/settings_menu.c83
-rw-r--r--apps/settings.c40
-rw-r--r--apps/settings.h13
-rw-r--r--apps/settings_list.c69
-rw-r--r--apps/settings_list.h4
12 files changed, 1220 insertions, 179 deletions
diff --git a/apps/SOURCES b/apps/SOURCES
index faf7247fcc..521b920f69 100644
--- a/apps/SOURCES
+++ b/apps/SOURCES
@@ -95,6 +95,9 @@ gui/pitchscreen.c
95gui/quickscreen.c 95gui/quickscreen.c
96#endif 96#endif
97gui/folder_select.c 97gui/folder_select.c
98#if defined(HAVE_BACKLIGHT) || !defined(HAS_BUTTON_HOLD)
99gui/mask_select.c
100#endif
98 101
99gui/wps.c 102gui/wps.c
100gui/scrollbar.c 103gui/scrollbar.c
diff --git a/apps/action.c b/apps/action.c
index eae00f5d18..d153bc6140 100644
--- a/apps/action.c
+++ b/apps/action.c
@@ -42,6 +42,16 @@
42#include "statusbar-skinned.h" 42#include "statusbar-skinned.h"
43#endif 43#endif
44 44
45#ifdef HAVE_BACKLIGHT
46#include "backlight.h"
47#if CONFIG_CHARGING
48#include "power.h"
49#endif
50#endif /* HAVE_BACKLIGHT */
51
52#define LOGF_ENABLE
53#include "logf.h"
54
45static int last_button = BUTTON_NONE|BUTTON_REL; /* allow the ipod wheel to 55static int last_button = BUTTON_NONE|BUTTON_REL; /* allow the ipod wheel to
46 work on startup */ 56 work on startup */
47static intptr_t last_data = 0; 57static intptr_t last_data = 0;
@@ -56,19 +66,34 @@ static bool short_press = false;
56#define REPEAT_WINDOW_TICKS HZ/4 66#define REPEAT_WINDOW_TICKS HZ/4
57static int last_action_tick = 0; 67static int last_action_tick = 0;
58 68
69#if defined(HAVE_BACKLIGHT) || !defined(HAS_BUTTON_HOLD)
70static inline bool is_action_normal(int action);
71static inline bool mask_has_flag(unsigned int mask, unsigned int flag);
72static inline bool is_action_completed(int button);
73#define LAST_FILTER_TICKS HZ/2 /* timeout between filtered actions */
74#endif /* defined(HAVE_BACKLIGHT) || !defined(HAS_BUTTON_HOLD) */
75
76#ifdef HAVE_BACKLIGHT
77static unsigned int backlight_mask = SEL_ACTION_NONE;
78static int do_backlight(int action, int context, bool is_pre_btn);
79static void handle_backlight(bool backlight, bool ignore_next);
80#endif /* HAVE_BACKLIGHT */
81
59/* software keylock stuff */ 82/* software keylock stuff */
60#ifndef HAS_BUTTON_HOLD 83#ifndef HAS_BUTTON_HOLD
61static bool keys_locked = false; 84static bool keys_locked = false;
62static int unlock_combo = BUTTON_NONE;
63static bool screen_has_lock = false; 85static bool screen_has_lock = false;
86static unsigned int softlock_mask = SEL_ACTION_NONE;
87static inline int do_softlock_unlock_combo(int button, int context);
88static int do_softlock(int button, int action, int context, bool is_pre_btn);
64#endif /* HAVE_SOFTWARE_KEYLOCK */ 89#endif /* HAVE_SOFTWARE_KEYLOCK */
65
66/* 90/*
67 * do_button_check is the worker function for get_default_action. 91 * do_button_check is the worker function for get_default_action.
68 * returns ACTION_UNKNOWN or the requested return value from the list. 92 * returns ACTION_UNKNOWN or the requested return value from the list.
93 * BE AWARE is_pre_button can miss pre buttons if a match is found first.
69 */ 94 */
70static inline int do_button_check(const struct button_mapping *items, 95static inline int do_button_check(const struct button_mapping *items,int button,
71 int button, int last_button, int *start) 96 int last_button, int *start, bool *prebtn)
72{ 97{
73 int i = 0; 98 int i = 0;
74 int ret = ACTION_UNKNOWN; 99 int ret = ACTION_UNKNOWN;
@@ -88,6 +113,8 @@ static inline int do_button_check(const struct button_mapping *items,
88 break; 113 break;
89 } 114 }
90 } 115 }
116 else if (items[i].pre_button_code & button)
117 *prebtn = true; /* determine if this could be another action */
91 i++; 118 i++;
92 } 119 }
93 *start = i; 120 *start = i;
@@ -164,7 +191,7 @@ static inline int get_next_context(const struct button_mapping *items, int i)
164static void gui_boost(bool want_to_boost) 191static void gui_boost(bool want_to_boost)
165{ 192{
166 static bool boosted = false; 193 static bool boosted = false;
167 194
168 if (want_to_boost && !boosted) 195 if (want_to_boost && !boosted)
169 { 196 {
170 cpu_boost(true); 197 cpu_boost(true);
@@ -177,7 +204,7 @@ static void gui_boost(bool want_to_boost)
177 } 204 }
178} 205}
179 206
180/* gui_unboost_callback() is called GUI_BOOST_TIMEOUT seconds after the 207/* gui_unboost_callback() is called GUI_BOOST_TIMEOUT seconds after the
181 * last wheel scrolling event. */ 208 * last wheel scrolling event. */
182static int gui_unboost_callback(struct timeout *tmo) 209static int gui_unboost_callback(struct timeout *tmo)
183{ 210{
@@ -188,8 +215,8 @@ static int gui_unboost_callback(struct timeout *tmo)
188#endif 215#endif
189 216
190/* 217/*
191 * int get_action_worker(int context, struct button_mapping *user_mappings, 218 * int get_action_worker(int context, int timeout, bool *is_pre_button,
192 int timeout) 219 struct button_mapping *user_mappings)
193 This function searches the button list for the given context for the just 220 This function searches the button list for the given context for the just
194 pressed button. 221 pressed button.
195 If there is a match it returns the value from the list. 222 If there is a match it returns the value from the list.
@@ -197,12 +224,14 @@ static int gui_unboost_callback(struct timeout *tmo)
197 the last item in the list "points" to the next context in a chain 224 the last item in the list "points" to the next context in a chain
198 so the "chain" is followed until the button is found. 225 so the "chain" is followed until the button is found.
199 putting ACTION_NONE will get CONTEXT_STD which is always the last list checked. 226 putting ACTION_NONE will get CONTEXT_STD which is always the last list checked.
200 227 BE AWARE is_pre_button can miss pre buttons if a match is found first.
228 it is more for actions that are not yet completed in the desired context
229 but are defined in a lower 'chained' context.
201 Timeout can be TIMEOUT_NOBLOCK to return immediatly 230 Timeout can be TIMEOUT_NOBLOCK to return immediatly
202 TIMEOUT_BLOCK to wait for a button press 231 TIMEOUT_BLOCK to wait for a button press
203 Any number >0 to wait that many ticks for a press 232 Any number >0 to wait that many ticks for a press
204 */ 233 */
205static int get_action_worker(int context, int timeout, 234static int get_action_worker(int context, int timeout, bool *is_pre_button,
206 const struct button_mapping* (*get_context_map)(int) ) 235 const struct button_mapping* (*get_context_map)(int) )
207{ 236{
208 const struct button_mapping *items = NULL; 237 const struct button_mapping *items = NULL;
@@ -210,7 +239,7 @@ static int get_action_worker(int context, int timeout,
210 int i=0; 239 int i=0;
211 int ret = ACTION_UNKNOWN; 240 int ret = ACTION_UNKNOWN;
212 static int last_context = CONTEXT_STD; 241 static int last_context = CONTEXT_STD;
213 242
214 send_event(GUI_EVENT_ACTIONUPDATE, NULL); 243 send_event(GUI_EVENT_ACTIONUPDATE, NULL);
215 244
216 if (timeout == TIMEOUT_NOBLOCK) 245 if (timeout == TIMEOUT_NOBLOCK)
@@ -222,7 +251,7 @@ static int get_action_worker(int context, int timeout,
222 251
223#if defined(HAVE_GUI_BOOST) && defined(HAVE_ADJUSTABLE_CPU_FREQ) 252#if defined(HAVE_GUI_BOOST) && defined(HAVE_ADJUSTABLE_CPU_FREQ)
224 static struct timeout gui_unboost; 253 static struct timeout gui_unboost;
225 /* Boost the CPU in case of wheel scrolling activity in the defined contexts. 254 /* Boost the CPU in case of wheel scrolling activity in the defined contexts.
226 * Call unboost with a timeout of GUI_BOOST_TIMEOUT. */ 255 * Call unboost with a timeout of GUI_BOOST_TIMEOUT. */
227 if (button != BUTTON_NONE) 256 if (button != BUTTON_NONE)
228 { 257 {
@@ -270,7 +299,7 @@ static int get_action_worker(int context, int timeout,
270 } 299 }
271 return ACTION_NONE; 300 return ACTION_NONE;
272 } 301 }
273 302
274 if ((context != last_context) && ((last_button & BUTTON_REL) == 0) 303 if ((context != last_context) && ((last_button & BUTTON_REL) == 0)
275#ifdef HAVE_SCROLLWHEEL 304#ifdef HAVE_SCROLLWHEEL
276 /* Scrollwheel doesn't generate release events */ 305 /* Scrollwheel doesn't generate release events */
@@ -288,39 +317,24 @@ static int get_action_worker(int context, int timeout,
288 return ACTION_NONE; /* "safest" return value */ 317 return ACTION_NONE; /* "safest" return value */
289 } 318 }
290 last_context = context; 319 last_context = context;
320
291#ifndef HAS_BUTTON_HOLD 321#ifndef HAS_BUTTON_HOLD
292 screen_has_lock = ((context & ALLOW_SOFTLOCK) == ALLOW_SOFTLOCK); 322 screen_has_lock = ((context & ALLOW_SOFTLOCK) == ALLOW_SOFTLOCK);
323 context &= ~ALLOW_SOFTLOCK;
293 if (is_keys_locked()) 324 if (is_keys_locked())
294 { 325 {
295 if (button == unlock_combo) 326 ret = do_softlock_unlock_combo(button, context);
296 { 327 if (!is_keys_locked())
297 last_button = BUTTON_NONE; 328 return ret;
298 keys_locked = false;
299#if defined(HAVE_TOUCHPAD) || defined(HAVE_TOUCHSCREEN)
300 /* enable back touch device */
301 button_enable_touch(true);
302#endif
303 splash(HZ/2, str(LANG_KEYLOCK_OFF));
304 return ACTION_REDRAW;
305 }
306 else
307#if (BUTTON_REMOTE != 0)
308 if ((button & BUTTON_REMOTE) == 0)
309#endif
310 {
311 if ((button & BUTTON_REL))
312 splash(HZ/2, str(LANG_KEYLOCK_ON));
313 return ACTION_REDRAW;
314 }
315 } 329 }
316#if defined(HAVE_TOUCHPAD) || defined(HAVE_TOUCHSCREEN) 330#if defined(HAVE_TOUCHPAD) || defined(HAVE_TOUCHSCREEN)
317 else 331 else if (!mask_has_flag(softlock_mask, SEL_ACTION_NOTOUCH))
318 { 332 {
319 /* make sure touchpad get reactivated if we quit the screen */ 333 /* make sure touchpad get reactivated if we quit the screen */
320 button_enable_touch(true); 334 button_enable_touch(true);
321 } 335 }
322#endif 336#endif
323 context &= ~ALLOW_SOFTLOCK; 337
324#endif /* HAS_BUTTON_HOLD */ 338#endif /* HAS_BUTTON_HOLD */
325 339
326#ifdef HAVE_TOUCHSCREEN 340#ifdef HAVE_TOUCHSCREEN
@@ -348,6 +362,7 @@ static int get_action_worker(int context, int timeout,
348#endif 362#endif
349 363
350 /* logf("%x,%x",last_button,button); */ 364 /* logf("%x,%x",last_button,button); */
365 *is_pre_button = false; /* could the button be another actions pre_button */
351 while (1) 366 while (1)
352 { 367 {
353 /* logf("context = %x",context); */ 368 /* logf("context = %x",context); */
@@ -363,7 +378,7 @@ static int get_action_worker(int context, int timeout,
363 if (items == NULL) 378 if (items == NULL)
364 break; 379 break;
365 380
366 ret = do_button_check(items,button,last_button,&i); 381 ret = do_button_check(items, button, last_button, &i, is_pre_button);
367 382
368 if (ret == ACTION_UNKNOWN) 383 if (ret == ACTION_UNKNOWN)
369 { 384 {
@@ -375,24 +390,13 @@ static int get_action_worker(int context, int timeout,
375 continue; 390 continue;
376 } 391 }
377 } 392 }
378
379 /* Action was found or STOPSEARCHING was specified */ 393 /* Action was found or STOPSEARCHING was specified */
380 break; 394 break;
381 } 395 }
382 /* DEBUGF("ret = %x\n",ret); */ 396 /* DEBUGF("ret = %x\n",ret); */
383#ifndef HAS_BUTTON_HOLD 397#ifndef HAS_BUTTON_HOLD
384 if (screen_has_lock && (ret == ACTION_STD_KEYLOCK)) 398 if(screen_has_lock && is_action_normal(ret))
385 { 399 ret = do_softlock(button, ret, last_context & ~ALLOW_SOFTLOCK, is_pre_button);
386 unlock_combo = button;
387 keys_locked = true;
388 splash(HZ/2, str(LANG_KEYLOCK_ON));
389 #if defined(HAVE_TOUCHPAD) || defined(HAVE_TOUCHSCREEN)
390 /* disable touch device on keylock */
391 button_enable_touch(false);
392 #endif
393 button_clear_queue();
394 return ACTION_REDRAW;
395 }
396#endif 400#endif
397 if ((current_tick - last_action_tick < REPEAT_WINDOW_TICKS) 401 if ((current_tick - last_action_tick < REPEAT_WINDOW_TICKS)
398 && (ret == last_action)) 402 && (ret == last_action))
@@ -411,42 +415,46 @@ static int get_action_worker(int context, int timeout,
411#endif 415#endif
412 416
413 return ret; 417 return ret;
414} 418}/* get_action_worker */
415 419
416int get_action(int context, int timeout) 420int get_action(int context, int timeout)
417{ 421{
418 int button = get_action_worker(context,timeout,NULL); 422 bool is_pre_button = false;
423 int button = get_action_worker(context, timeout, &is_pre_button, NULL);
424
419#ifdef HAVE_TOUCHSCREEN 425#ifdef HAVE_TOUCHSCREEN
420 if (button == ACTION_TOUCHSCREEN) 426 if (button == ACTION_TOUCHSCREEN)
421 button = sb_touch_to_button(context); 427 button = sb_touch_to_button(context);
422#endif 428#endif
429
430#ifdef HAVE_BACKLIGHT
431 if (mask_has_flag(backlight_mask, SEL_ACTION_ENABLED) &&
432 is_action_normal(button))
433 button = do_backlight(button, context & ~ALLOW_SOFTLOCK, is_pre_button);
434#endif
435
423 return button; 436 return button;
424} 437}
425 438
426int get_custom_action(int context,int timeout, 439int get_custom_action(int context,int timeout,
427 const struct button_mapping* (*get_context_map)(int)) 440 const struct button_mapping* (*get_context_map)(int))
428{ 441{
429 return get_action_worker(context,timeout,get_context_map); 442 bool is_pre_button = false;
443 return get_action_worker(context,timeout, &is_pre_button, get_context_map);
430} 444}
431 445
432bool action_userabort(int timeout) 446bool action_userabort(int timeout)
433{ 447{
434 int action = get_action_worker(CONTEXT_STD,timeout,NULL); 448 bool is_pre_button = false;
449 int action = get_action_worker(CONTEXT_STD,timeout, &is_pre_button, NULL);
435 bool ret = (action == ACTION_STD_CANCEL); 450 bool ret = (action == ACTION_STD_CANCEL);
436 if(!ret) 451 if (!ret)
437 { 452 {
438 default_event_handler(action); 453 default_event_handler(action);
439 } 454 }
440 return ret; 455 return ret;
441} 456}
442 457
443#ifndef HAS_BUTTON_HOLD
444bool is_keys_locked(void)
445{
446 return (screen_has_lock && keys_locked);
447}
448#endif
449
450intptr_t get_action_data(void) 458intptr_t get_action_data(void)
451{ 459{
452 return last_data; 460 return last_data;
@@ -532,4 +540,338 @@ void action_wait_for_release(void)
532{ 540{
533 wait_for_release = true; 541 wait_for_release = true;
534} 542}
535 543
544#if defined(HAVE_BACKLIGHT) || !defined(HAS_BUTTON_HOLD)
545/* HELPER FUNCTIONS
546* Selective softlock and backlight use this lookup based on mask to decide
547* which actions are filtered, or could be filtered but not currently set.
548* returns false if the action isn't found, true if the action is found
549*/
550static bool is_action_filtered(int action, unsigned int mask, int context)
551{
552 bool match = false;
553
554 switch (action)
555 {
556 case ACTION_NONE:
557 break;
558/*Actions that are not mapped will not turn on the backlight option NOUNMAPPED*/
559 case ACTION_UNKNOWN:
560 match = mask_has_flag(mask, SEL_ACTION_NOUNMAPPED);
561 break;
562 case ACTION_WPS_PLAY:
563 case ACTION_FM_PLAY:
564 match = mask_has_flag(mask, SEL_ACTION_PLAY);
565 break;
566 case ACTION_STD_PREVREPEAT:
567 case ACTION_STD_NEXTREPEAT:
568 case ACTION_WPS_SEEKBACK:
569 case ACTION_WPS_SEEKFWD:
570 case ACTION_WPS_STOPSEEK:
571 match = mask_has_flag(mask, SEL_ACTION_SEEK);
572 break;
573 case ACTION_STD_PREV:
574 case ACTION_STD_NEXT:
575 case ACTION_WPS_SKIPNEXT:
576 case ACTION_WPS_SKIPPREV:
577 case ACTION_FM_NEXT_PRESET:
578 case ACTION_FM_PREV_PRESET:
579 match = mask_has_flag(mask, SEL_ACTION_SKIP);
580 break;
581 case ACTION_WPS_VOLUP:
582 case ACTION_WPS_VOLDOWN:
583 match = mask_has_flag(mask, SEL_ACTION_VOL);
584 break;
585 case ACTION_SETTINGS_INC:/*FMS*/
586 case ACTION_SETTINGS_INCREPEAT:/*FMS*/
587 case ACTION_SETTINGS_DEC:/*FMS*/
588 case ACTION_SETTINGS_DECREPEAT:/*FMS*/
589 match = (context == CONTEXT_FM) && mask_has_flag(mask, SEL_ACTION_VOL);
590 break;
591 default:
592 /* display action code of unfiltered actions */
593 logf ("unfiltered actions: context: %d action: %d, last btn: %d, \
594 mask: %d", context, action, last_button, mask);
595 break;
596 }/*switch*/
597
598 return match;
599}
600/* compares mask to a flag return true if set false otherwise*/
601static inline bool mask_has_flag(unsigned int mask, unsigned int flag)
602{
603 return ((mask & flag) != 0);
604}
605/* returns true if the supplied context is to be filtered by selective BL/SL*/
606static inline bool is_context_filtered(int context)
607{
608 return (context == CONTEXT_FM || context == CONTEXT_WPS);
609}
610/* returns true if action can be passed on to selective backlight/softlock */
611static inline bool is_action_normal(int action)
612{
613 return (action != ACTION_REDRAW && (action & SYS_EVENT) == 0);
614}
615/*returns true if Button & released, repeated; or won't generate those events*/
616static inline bool is_action_completed(int button)
617{
618 return ((button & (BUTTON_REPEAT | BUTTON_REL)) != 0
619#ifdef HAVE_SCROLLWHEEL
620 /* Scrollwheel doesn't generate release events */
621 || (button & (BUTTON_SCROLL_BACK | BUTTON_SCROLL_FWD)) != 0
622#endif
623 );
624}
625
626/* most every action takes two rounds through get_action_worker,
627 * once for the keypress and once for the key release,
628 * actions with pre_button codes take even more, some actions however, only
629 * take once; actions defined with only a button and no release/repeat event,
630 * these actions should be acted upon immediately except when we have
631 * selective backlighting/softlock enabled and in this case we only act upon
632 * them immediately if there is no chance they have another event tied to them
633 * determined using is_pre_button and is_action_completed()
634 *returns true if event was not filtered and false if it was
635*/
636static bool is_action_unfiltered(int action,int button, bool is_pre_button,
637 bool filtered, int *tick)
638{
639 bool ret = false;
640 /*directly after a match a key release event may trigger another*/
641 if (filtered && action != ACTION_UNKNOWN)
642 *tick = current_tick + LAST_FILTER_TICKS;
643 /* has button been rel/rep or is this the only action it could be */
644 if (is_action_completed(button) || !is_pre_button)
645 {
646 /* reset last action , if the action is not filtered and
647 this isn't just a key release event then return true */
648 if (!filtered && *tick < current_tick)
649 {
650 *tick = 0;
651 ret = true;
652 }
653 }/*is_action_completed() || !is_pre_button*/
654 return ret;
655}
656#endif /*defined(HAVE_BACKLIGHT) || !defined(HAS_BUTTON_HOLD) HELPER FUNCTIONS*/
657
658#ifdef HAVE_BACKLIGHT
659static void handle_backlight(bool backlight, bool ignore_next)
660{
661 if (backlight)
662 {
663 backlight_on_ignore(false, 0);
664 backlight_on();
665#ifdef HAVE_BUTTON_LIGHT
666 buttonlight_on_ignore(false, 0);
667 buttonlight_on();
668 }
669 buttonlight_on_ignore(ignore_next, 5*HZ);/* as a precautionary fallback */
670#else
671 }
672#endif
673 backlight_on_ignore(ignore_next, 5*HZ);/*must be set everytime we handle bl*/
674}
675
676 /* Need to look up actions before we can decide to turn on backlight, if
677 * selective backlighting is true filter first keypress events need to be
678 * taken into account as well
679 */
680static int do_backlight(int action, int context, bool is_pre_btn)
681{
682 static int last_filtered_tick = 0;
683
684 bool bl_is_active = is_backlight_on(false);
685 bool bl_activate = false;
686 bool filtered;
687
688#if CONFIG_CHARGING /* disable if on external power */
689 if (!bl_is_active && is_context_filtered(context) &&
690 !(mask_has_flag(backlight_mask, SEL_ACTION_NOEXT) && power_input_present()))
691#else /* skip if backlight is on or incorrect context */
692 if (!bl_is_active && is_context_filtered(context))
693#endif
694 {
695 filtered = is_action_filtered(action, backlight_mask, context);
696 bl_activate = is_action_unfiltered(action, last_button, is_pre_btn,
697 filtered, &last_filtered_tick);
698 }/*is_context_filtered(context)*/
699 else
700 bl_activate = true;
701
702 if (action != ACTION_NONE && bl_activate)
703 {
704 handle_backlight(true, true);
705
706 if (mask_has_flag(backlight_mask, SEL_ACTION_FFKEYPRESS) && !bl_is_active)
707 {
708 action = ACTION_NONE;
709 last_button = BUTTON_NONE;
710 }
711 }
712 else
713 handle_backlight(false, true);/* set ignore next true */
714
715 return action;
716}
717
718/* Enable selected actions to leave the backlight off */
719void set_selective_backlight_actions(bool selective, unsigned int mask,
720 bool filter_fkp)
721{
722 handle_backlight(true, selective);
723 if (selective) /* we will handle filter_first_keypress here so turn it off*/
724 {
725 set_backlight_filter_keypress(false);/* turnoff ffkp in button.c */
726 backlight_mask = mask | SEL_ACTION_ENABLED;
727 if(filter_fkp)
728 backlight_mask |= SEL_ACTION_FFKEYPRESS;
729 }
730 else
731 {
732 set_backlight_filter_keypress(filter_fkp);
733 backlight_mask = SEL_ACTION_NONE;
734 }
735}
736#endif /* HAVE_BACKLIGHT */
737
738#ifndef HAS_BUTTON_HOLD
739bool is_keys_locked(void)
740{
741 return (screen_has_lock && keys_locked);
742}
743
744static inline void do_key_lock(bool lock)
745{
746 keys_locked = lock;
747 last_button = BUTTON_NONE;
748 button_clear_queue();
749#if defined(HAVE_TOUCHPAD) || defined(HAVE_TOUCHSCREEN)
750 /* disable touch device on keylock if std behavior or selected disable touch */
751 if (!mask_has_flag(softlock_mask, SEL_ACTION_ENABLED) ||
752 mask_has_flag(softlock_mask, SEL_ACTION_NOTOUCH))
753 button_enable_touch(!lock);
754#endif
755}
756
757/* user selected autolock based on backlight timeout; toggles autolock on / off
758 by ACTION_STD_KEYLOCK presses, Activates autolock if set on backlight timeout
759*/
760#ifdef HAVE_BACKLIGHT
761static inline int do_auto_softlock(int button, int action, int *unlock_combo)
762{
763 if(mask_has_flag(softlock_mask, SEL_ACTION_ALOCK_OK) && !is_backlight_on(false))
764 do_key_lock(true);
765
766 else if (action == ACTION_STD_KEYLOCK)
767 {
768 *unlock_combo = button;/* set unlock combo to allow unlock */
769 softlock_mask ^= SEL_ACTION_ALOCK_OK;
770 handle_backlight(true, false);
771 /* If we don't wait for a moment for the backlight queue
772 * to process, the user will never see the message */
773 if (!is_backlight_on(false))
774 sleep(HZ/2);
775
776 if (mask_has_flag(softlock_mask, SEL_ACTION_ALOCK_OK))
777 {
778 splash(HZ/2, ID2P(LANG_ACTION_AUTOLOCK_ON));
779 action = ACTION_REDRAW;
780 }
781 else
782 splash(HZ/2, ID2P(LANG_ACTION_AUTOLOCK_OFF));
783 }
784 return action;
785}
786#endif
787
788/* Allows unlock softlock when action is not yet known but unlock_combo set*/
789static inline int do_softlock_unlock_combo(int button, int context)
790{
791return do_softlock(button, ACTION_NONE, context, false);
792}
793
794/* Handles softlock once action is known */
795static int do_softlock(int button, int action, int context, bool is_pre_btn)
796{
797 static int last_filtered_tick = 0;
798 static int unlock_combo = BUTTON_NONE; /*Moved from GLOBAL*/
799 bool filtered = true;
800 bool notify_user = false;
801 bool sl_activate = true; /* standard softlock behavior */
802
803#ifdef HAVE_BACKLIGHT
804 if (!keys_locked && mask_has_flag(softlock_mask, SEL_ACTION_AUTOLOCK))
805 action = do_auto_softlock(button, action, &unlock_combo);
806#endif
807 /* Lock/Unlock toggled by ACTION_STD_KEYLOCK presses*/
808 if ((action == ACTION_STD_KEYLOCK) || (keys_locked && unlock_combo == button))
809 {
810 unlock_combo = button;
811 do_key_lock(!keys_locked);
812 notify_user = true;
813 }
814#if (BUTTON_REMOTE != 0)/* Allow remote actions through */
815 else if (mask_has_flag(button, BUTTON_REMOTE))
816 notify_user = false;
817#endif
818 else if (keys_locked && action != ACTION_NONE && action != ACTION_REDRAW)
819 {
820 if (mask_has_flag(softlock_mask, SEL_ACTION_ENABLED))
821 {
822 filtered = is_action_filtered(action, softlock_mask, context);
823
824 sl_activate = is_action_unfiltered(action, button, is_pre_btn,
825 filtered, &last_filtered_tick);
826 }
827 /*All non-std softlock options are set to 0 if advanced sl is disabled*/
828 if (sl_activate)
829 {
830 if (!mask_has_flag(softlock_mask, SEL_ACTION_NONOTIFY))
831 { /* always true on standard softlock behavior*/
832 notify_user = mask_has_flag(button, BUTTON_REL);
833 action = ACTION_REDRAW;
834 }
835 else
836 action = ACTION_NONE;
837 }
838 else if (!filtered)/*catch blocked actions on fast repeated presses*/
839 action = ACTION_NONE;
840 } /* keys_locked */
841
842#ifdef BUTTON_POWER /*always notify if power button pressed while keys locked*/
843 notify_user |= (mask_has_flag(button, BUTTON_POWER) && keys_locked);
844#endif
845
846 if (notify_user)
847 {
848#ifdef HAVE_BACKLIGHT
849 handle_backlight(true, false);
850 /* If we don't wait for a moment for the backlight queue
851 * to process, the user will never see the message */
852 if (!is_backlight_on(false))
853 sleep(HZ/2);
854#endif
855 if (keys_locked)
856 splash(HZ/2, ID2P(LANG_KEYLOCK_ON));
857 else
858 splash(HZ/2, ID2P(LANG_KEYLOCK_OFF));
859
860 last_button = BUTTON_NONE;
861 action = ACTION_REDRAW;
862 button_clear_queue();
863 }
864
865 return action;
866}
867
868void set_selective_softlock_actions(bool selective, unsigned int mask)
869{
870 keys_locked = false;
871 if(selective)
872 softlock_mask = mask | SEL_ACTION_ENABLED;
873 else
874 softlock_mask = SEL_ACTION_NONE;
875}
876
877#endif /* HAS_BUTTON_HOLD */
diff --git a/apps/action.h b/apps/action.h
index e54d5deacf..3bc43c2190 100644
--- a/apps/action.h
+++ b/apps/action.h
@@ -41,37 +41,66 @@
41#else 41#else
42#define ALLOW_SOFTLOCK 0 42#define ALLOW_SOFTLOCK 0
43#endif 43#endif
44#if defined(HAVE_BACKLIGHT) || !defined(HAS_BUTTON_HOLD)
45/* Selective action selection flags */
46#define SEL_ACTION_NONE 0
47#define SEL_ACTION_VOL 0x001U
48#define SEL_ACTION_PLAY 0x002U
49#define SEL_ACTION_SEEK 0x004U
50#define SEL_ACTION_SKIP 0x008U
51#define SEL_ACTION_NOUNMAPPED 0x010U/* disable backlight on unmapped buttons */
52 /* Available 0x020U*/
53 /* Available 0x040U*/
54#define SEL_ACTION_NOTOUCH 0x080U/* disable touch screen/pad on screen lock */
55#define SEL_ACTION_AUTOLOCK 0x100U/* autolock on backlight off */
56#define SEL_ACTION_NOEXT 0x200U/* disable selective backlight while charge*/
57#define SEL_ACTION_NONOTIFY 0x200U/* don't notify user softlock is active */
58/* Flags below are internal to selective functions */
59#define SEL_ACTION_ALOCK_OK 0x400U/*autolock only active after key lock once*/
60#define SEL_ACTION_FFKEYPRESS 0x400U/* backlight Filter First Keypress active*/
61#define SEL_ACTION_ENABLED 0x800U
62/* Selective Actions flags */
44 63
64#ifndef HAS_BUTTON_HOLD
65bool is_keys_locked(void);
66void set_selective_softlock_actions(bool selective, unsigned int mask);
67#endif
68
69#ifdef HAVE_BACKLIGHT
70void set_selective_backlight_actions(bool selective, unsigned int mask,
71 bool filter_fkp);
72#endif
73#endif /* defined(HAVE_BACKLIGHT) || !defined(HAS_BUTTON_HOLD) */
45enum { 74enum {
46 CONTEXT_STD = 0, 75 CONTEXT_STD = 0,
47 /* These CONTEXT_ values were here before me, 76 /* These CONTEXT_ values were here before me,
48 there values may have significance, so dont touch! */ 77 there values may have significance, so dont touch! */
49 CONTEXT_WPS = 1, 78 CONTEXT_WPS = 1,
50 CONTEXT_TREE = 2, 79 CONTEXT_TREE = 2,
51 CONTEXT_RECORD = 3, 80 CONTEXT_RECORD = 3,
52 CONTEXT_MAINMENU = 4, /* uses CONTEXT_TREE and ACTION_TREE_* */ 81 CONTEXT_MAINMENU = 4, /* uses CONTEXT_TREE and ACTION_TREE_* */
53 CONTEXT_ID3DB = 5, 82 CONTEXT_ID3DB = 5,
54 /* Add new contexts here, no need to explicitly define a value for them */ 83 /* Add new contexts here, no need to explicitly define a value for them */
55 CONTEXT_LIST, 84 CONTEXT_LIST,
56 CONTEXT_SETTINGS, /* regular setting screens (and debug screens) */ 85 CONTEXT_SETTINGS, /* regular setting screens (and debug screens) */
57 /* bellow are setting screens which may need to redefine the standard 86 /* bellow are setting screens which may need to redefine the standard
58 setting screen keys, targets should return the CONTEXT_SETTINGS 87 setting screen keys, targets should return the CONTEXT_SETTINGS
59 keymap unless they are not adequate for the screen 88 keymap unless they are not adequate for the screen
60 NOTE: uses ACTION_STD_[NEXT|PREV] so make sure they are there also 89 NOTE: uses ACTION_STD_[NEXT|PREV] so make sure they are there also
61 and (possibly) ACTION_SETTINGS_[INC|DEC] */ 90 and (possibly) ACTION_SETTINGS_[INC|DEC] */
62 CONTEXT_SETTINGS_EQ, 91 CONTEXT_SETTINGS_EQ,
63 CONTEXT_SETTINGS_COLOURCHOOSER, 92 CONTEXT_SETTINGS_COLOURCHOOSER,
64 CONTEXT_SETTINGS_TIME, 93 CONTEXT_SETTINGS_TIME,
65 CONTEXT_SETTINGS_RECTRIGGER, 94 CONTEXT_SETTINGS_RECTRIGGER,
66 95
67 /* The following contexts should use ACTION_STD_[NEXT|PREV] 96 /* The following contexts should use ACTION_STD_[NEXT|PREV]
68 and (possibly) ACTION_SETTINGS_[INC|DEC] 97 and (possibly) ACTION_SETTINGS_[INC|DEC]
69 Also add any extra actions they need */ 98 Also add any extra actions they need */
70 CONTEXT_BOOKMARKSCREEN, /* uses ACTION_BMS_ defines */ 99 CONTEXT_BOOKMARKSCREEN, /* uses ACTION_BMS_ defines */
71 CONTEXT_ALARMSCREEN, /* uses ACTION_AS_ defines */ 100 CONTEXT_ALARMSCREEN, /* uses ACTION_AS_ defines */
72 CONTEXT_QUICKSCREEN, /* uses ACTION_QS_ defines below */ 101 CONTEXT_QUICKSCREEN, /* uses ACTION_QS_ defines below */
73 CONTEXT_PITCHSCREEN, /* uses ACTION_PS_ defines below */ 102 CONTEXT_PITCHSCREEN, /* uses ACTION_PS_ defines below */
74 103
75 CONTEXT_YESNOSCREEN, /*NOTE: make sure your target has this and ACTION_YESNO_ACCEPT */ 104 CONTEXT_YESNOSCREEN, /*NOTE: make sure your target has this and ACTION_YESNO_ACCEPT */
76 CONTEXT_RECSCREEN, 105 CONTEXT_RECSCREEN,
77 CONTEXT_KEYBOARD, 106 CONTEXT_KEYBOARD,
@@ -86,7 +115,7 @@ enum {
86 115
87 116
88enum { 117enum {
89 118
90 ACTION_NONE = BUTTON_NONE, 119 ACTION_NONE = BUTTON_NONE,
91 ACTION_UNKNOWN, 120 ACTION_UNKNOWN,
92 ACTION_REDRAW, /* returned if keys are locked and we splash()'ed */ 121 ACTION_REDRAW, /* returned if keys are locked and we splash()'ed */
@@ -95,11 +124,11 @@ enum {
95 ACTION_TOUCHSCREEN_IGNORE, /* used for the 'none' action in skins */ 124 ACTION_TOUCHSCREEN_IGNORE, /* used for the 'none' action in skins */
96 125
97 /* standard actions, use these first */ 126 /* standard actions, use these first */
98 ACTION_STD_PREV, 127 ACTION_STD_PREV,
99 ACTION_STD_PREVREPEAT, 128 ACTION_STD_PREVREPEAT,
100 ACTION_STD_NEXT, 129 ACTION_STD_NEXT,
101 ACTION_STD_NEXTREPEAT, 130 ACTION_STD_NEXTREPEAT,
102 131
103 ACTION_STD_OK, 132 ACTION_STD_OK,
104 ACTION_STD_CANCEL, 133 ACTION_STD_CANCEL,
105 ACTION_STD_CONTEXT, 134 ACTION_STD_CONTEXT,
@@ -108,10 +137,10 @@ enum {
108 ACTION_STD_KEYLOCK, 137 ACTION_STD_KEYLOCK,
109 ACTION_STD_REC, 138 ACTION_STD_REC,
110 ACTION_STD_HOTKEY, 139 ACTION_STD_HOTKEY,
111 140
112 ACTION_F3, /* just so everything works again, possibly change me */ 141 ACTION_F3, /* just so everything works again, possibly change me */
113 /* code context actions */ 142 /* code context actions */
114 143
115 /* WPS codes */ 144 /* WPS codes */
116 ACTION_WPS_BROWSE, 145 ACTION_WPS_BROWSE,
117 ACTION_WPS_PLAY, 146 ACTION_WPS_PLAY,
@@ -133,7 +162,7 @@ enum {
133 ACTION_WPS_CREATE_BOOKMARK,/* optional */ 162 ACTION_WPS_CREATE_BOOKMARK,/* optional */
134 ACTION_WPS_REC, 163 ACTION_WPS_REC,
135#if 0 164#if 0
136 ACTION_WPSAB_SINGLE, /* This needs to be #defined in 165 ACTION_WPSAB_SINGLE, /* This needs to be #defined in
137 the config-<target>.h to one of the ACTION_WPS_ actions 166 the config-<target>.h to one of the ACTION_WPS_ actions
138 so it can be used */ 167 so it can be used */
139#endif 168#endif
@@ -141,23 +170,23 @@ enum {
141 ACTION_WPS_ABSETB_NEXTDIR, /* you shouldnt want to change dir in ab-mode */ 170 ACTION_WPS_ABSETB_NEXTDIR, /* you shouldnt want to change dir in ab-mode */
142 ACTION_WPS_ABRESET, 171 ACTION_WPS_ABRESET,
143 ACTION_WPS_HOTKEY, 172 ACTION_WPS_HOTKEY,
144 173
145 /* list and tree page up/down */ 174 /* list and tree page up/down */
146 ACTION_LISTTREE_PGUP,/* optional */ 175 ACTION_LISTTREE_PGUP,/* optional */
147 ACTION_LISTTREE_PGDOWN,/* optional */ 176 ACTION_LISTTREE_PGDOWN,/* optional */
148#ifdef HAVE_VOLUME_IN_LIST 177#ifdef HAVE_VOLUME_IN_LIST
149 ACTION_LIST_VOLUP, 178 ACTION_LIST_VOLUP,
150 ACTION_LIST_VOLDOWN, 179 ACTION_LIST_VOLDOWN,
151#endif 180#endif
152 181
153 /* tree */ 182 /* tree */
154 ACTION_TREE_ROOT_INIT, 183 ACTION_TREE_ROOT_INIT,
155 ACTION_TREE_PGLEFT,/* optional */ 184 ACTION_TREE_PGLEFT,/* optional */
156 ACTION_TREE_PGRIGHT,/* optional */ 185 ACTION_TREE_PGRIGHT,/* optional */
157 ACTION_TREE_STOP, 186 ACTION_TREE_STOP,
158 ACTION_TREE_WPS, 187 ACTION_TREE_WPS,
159 ACTION_TREE_HOTKEY, 188 ACTION_TREE_HOTKEY,
160 189
161 /* radio */ 190 /* radio */
162 ACTION_FM_MENU, 191 ACTION_FM_MENU,
163 ACTION_FM_PRESET, 192 ACTION_FM_PRESET,
@@ -177,7 +206,7 @@ enum {
177 ACTION_REC_NEWFILE, 206 ACTION_REC_NEWFILE,
178 ACTION_REC_F2, 207 ACTION_REC_F2,
179 ACTION_REC_F3, 208 ACTION_REC_F3,
180 209
181 /* main menu */ 210 /* main menu */
182 /* These are not strictly actions, but must be here 211 /* These are not strictly actions, but must be here
183 so they dont conflict with real actions in the menu code */ 212 so they dont conflict with real actions in the menu code */
@@ -186,11 +215,11 @@ enum {
186 ACTION_EXIT_AFTER_THIS_MENUITEM, /* if a menu returns this the menu will exit 215 ACTION_EXIT_AFTER_THIS_MENUITEM, /* if a menu returns this the menu will exit
187 once the subitem returns */ 216 once the subitem returns */
188 ACTION_ENTER_MENUITEM, 217 ACTION_ENTER_MENUITEM,
189 218
190 /* id3db */ 219 /* id3db */
191 220
192 /* list */ 221 /* list */
193 222
194 /* settings */ 223 /* settings */
195 ACTION_SETTINGS_INC, 224 ACTION_SETTINGS_INC,
196 ACTION_SETTINGS_INCREPEAT, 225 ACTION_SETTINGS_INCREPEAT,
@@ -200,16 +229,16 @@ enum {
200 ACTION_SETTINGS_DECBIGSTEP, 229 ACTION_SETTINGS_DECBIGSTEP,
201 ACTION_SETTINGS_RESET, 230 ACTION_SETTINGS_RESET,
202 ACTION_SETTINGS_SET, /* Used by touchscreen targets */ 231 ACTION_SETTINGS_SET, /* Used by touchscreen targets */
203 232
204 /* bookmark screen */ 233 /* bookmark screen */
205 ACTION_BMS_DELETE, 234 ACTION_BMS_DELETE,
206 235
207 /* quickscreen */ 236 /* quickscreen */
208 ACTION_QS_LEFT, 237 ACTION_QS_LEFT,
209 ACTION_QS_RIGHT, 238 ACTION_QS_RIGHT,
210 ACTION_QS_DOWN, 239 ACTION_QS_DOWN,
211 ACTION_QS_TOP, 240 ACTION_QS_TOP,
212 241
213 /* pitchscreen */ 242 /* pitchscreen */
214 /* obviously ignore if you dont have thise screen */ 243 /* obviously ignore if you dont have thise screen */
215 ACTION_PS_INC_SMALL, 244 ACTION_PS_INC_SMALL,
@@ -225,10 +254,10 @@ enum {
225 ACTION_PS_EXIT, /* _STD_* isnt going to work here */ 254 ACTION_PS_EXIT, /* _STD_* isnt going to work here */
226 ACTION_PS_SLOWER, 255 ACTION_PS_SLOWER,
227 ACTION_PS_FASTER, 256 ACTION_PS_FASTER,
228 257
229 /* yesno screen */ 258 /* yesno screen */
230 ACTION_YESNO_ACCEPT, 259 ACTION_YESNO_ACCEPT,
231 260
232 /* keyboard screen */ 261 /* keyboard screen */
233 ACTION_KBD_LEFT, 262 ACTION_KBD_LEFT,
234 ACTION_KBD_RIGHT, 263 ACTION_KBD_RIGHT,
@@ -243,7 +272,7 @@ enum {
243 ACTION_KBD_DOWN, 272 ACTION_KBD_DOWN,
244 ACTION_KBD_MORSE_INPUT, 273 ACTION_KBD_MORSE_INPUT,
245 ACTION_KBD_MORSE_SELECT, 274 ACTION_KBD_MORSE_SELECT,
246 275
247#ifdef HAVE_TOUCHSCREEN 276#ifdef HAVE_TOUCHSCREEN
248 /* the following are helper actions for touchscreen targets, 277 /* the following are helper actions for touchscreen targets,
249 * These are for actions which are not doable or required if buttons are 278 * These are for actions which are not doable or required if buttons are
@@ -255,7 +284,7 @@ enum {
255 ACTION_TOUCH_VOLUME, 284 ACTION_TOUCH_VOLUME,
256 ACTION_TOUCH_SOFTLOCK, 285 ACTION_TOUCH_SOFTLOCK,
257 ACTION_TOUCH_SETTING, 286 ACTION_TOUCH_SETTING,
258#endif 287#endif
259 288
260 /* USB HID codes */ 289 /* USB HID codes */
261 ACTION_USB_HID_FIRST, /* Place holder */ 290 ACTION_USB_HID_FIRST, /* Place holder */
@@ -347,11 +376,8 @@ bool action_userabort(int timeout);
347 376
348/* no other code should need this apart from action.c */ 377/* no other code should need this apart from action.c */
349const struct button_mapping* get_context_mapping(int context); 378const struct button_mapping* get_context_mapping(int context);
350#ifndef HAS_BUTTON_HOLD
351bool is_keys_locked(void);
352#endif
353 379
354/* returns the status code variable from action.c for the button just pressed 380/* returns the status code variable from action.c for the button just pressed
355 If button != NULL it will be set to the actual button code */ 381 If button != NULL it will be set to the actual button code */
356#define ACTION_REMOTE 0x1 /* remote was pressed */ 382#define ACTION_REMOTE 0x1 /* remote was pressed */
357#define ACTION_REPEAT 0x2 /* action was repeated (NOT button) */ 383#define ACTION_REPEAT 0x2 /* action was repeated (NOT button) */
@@ -378,7 +404,7 @@ int action_get_touchscreen_press(short *x, short *y);
378 * the press was within the viewport, 404 * the press was within the viewport,
379 * ACTION_UNKNOWN (and x1, y1 untouched) if the press was outside 405 * ACTION_UNKNOWN (and x1, y1 untouched) if the press was outside
380 * BUTTON_NONE else 406 * BUTTON_NONE else
381 * 407 *
382 **/ 408 **/
383int action_get_touchscreen_press_in_vp(short *x1, short *y1, struct viewport *vp); 409int action_get_touchscreen_press_in_vp(short *x1, short *y1, struct viewport *vp);
384#endif 410#endif
diff --git a/apps/gui/mask_select.c b/apps/gui/mask_select.c
new file mode 100644
index 0000000000..e22ba7dd03
--- /dev/null
+++ b/apps/gui/mask_select.c
@@ -0,0 +1,287 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * Copyright (C) 2016 William Wilgus
9 * Derivative of folder_select.c by:
10 * Copyright (C) 2012 Jonathan Gordon
11 * Copyright (C) 2012 Thomas Martitz
12 *
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.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22/* TODO add language defines */
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include "lang.h"
28#include "language.h"
29#include "list.h"
30#include "plugin.h"
31#include "mask_select.h"
32#include "talk.h"
33
34/*
35 * Order for changing child states:
36 * 1) expand folder
37 * 2) collapse and select
38 * 3) deselect (skip to 1)
39 */
40
41enum child_state {
42 EXPANDED,
43 SELECTED,
44 COLLAPSED,
45 DESELECTED,
46};
47
48/* Children of main categories */
49struct child {
50 const char* name;
51 struct category *category;
52 enum child_state state;
53 int key_value;
54};
55
56/* Main Categories in root */
57struct category {
58 const char *name;
59 struct child *children;
60 int children_count;
61 int depth;
62 struct category* previous;
63 int key_value; /*values of all children OR|D*/
64};
65
66/* empty category for children of root only one level needed */
67static struct category empty = {
68 .name = "",
69 .children = NULL,
70 .children_count = 0,
71 .depth = 1,
72 .previous = NULL,
73};
74
75/* Or | all keyvalues that user selected */
76static int calculate_mask_r(struct category *root, int mask)
77{
78 int i = 0;
79 while (i < root->children_count)
80 {
81 struct child *this = &root->children[i];
82 if (this->state == SELECTED)
83 mask |= this->key_value;
84
85 else if (this->state == EXPANDED)
86 mask = calculate_mask_r(this->category, mask);
87 i++;
88 }
89return mask;
90}
91
92static int count_items(struct category *start)
93{
94 int count = 0;
95 int i;
96
97 for (i=0; i<start->children_count; i++)
98 {
99 struct child *foo = &start->children[i];
100 if (foo->state == EXPANDED)
101 count += count_items(foo->category);
102 count++;
103 }
104 return count;
105}
106
107static struct child* find_index(struct category *start,
108 int index,struct category **parent)
109{
110 int i = 0;
111
112 *parent = NULL;
113
114 while (i < start->children_count)
115 {
116 struct child *foo = &start->children[i];
117 if (i == index)
118 {
119 *parent = start;
120 return foo;
121 }
122 i++;
123 if (foo->state == EXPANDED)
124 {
125 struct child *bar = find_index(foo->category, index - i, parent);
126 if (bar)
127 {
128 return bar;
129 }
130 index -= count_items(foo->category);
131 }
132 }
133 return NULL;
134}
135
136/* simplelist uses this callback to change
137 the states of the categories/children */
138static int item_action_callback(int action, struct gui_synclist *list)
139{
140 struct category *root = (struct category*)list->data;
141 struct category *parent;
142 struct child *this = find_index(root, list->selected_item, &parent);
143
144 if (action == ACTION_STD_OK)
145 {
146 switch (this->state)
147 {
148 case EXPANDED:
149 this->state = SELECTED;
150 if (global_settings.talk_menu)
151 talk_id(LANG_ON, false);
152 break;
153 case SELECTED:
154 this->state = this->category->children_count == 0 ?
155 DESELECTED : COLLAPSED;
156 if (global_settings.talk_menu && this->category->children_count == 0)
157 talk_id(LANG_OFF, false);
158 break;
159 case COLLAPSED:
160 if (this->category == NULL)
161 this->category = root;
162 this->state = this->category->children_count == 0 ?
163 SELECTED : EXPANDED;
164 if (global_settings.talk_menu && this->category->children_count == 0)
165 talk_id(LANG_ON, false);
166 break;
167 case DESELECTED:
168 this->state = SELECTED;
169 if (global_settings.talk_menu)
170 talk_id(LANG_ON, false);
171 break;
172
173 default:
174 /* do nothing */
175 return action;
176 }
177 list->nb_items = count_items(root);
178 return ACTION_REDRAW;
179 }
180
181 return action;
182}
183
184static const char * item_get_name(int selected_item, void * data,
185 char * buffer, size_t buffer_len)
186{
187 struct category *root = (struct category*)data;
188 struct category *parent;
189 struct child *this = find_index(root, selected_item , &parent);
190
191 buffer[0] = '\0';
192
193 if (parent->depth >= 0)
194 for(int i = 0; i <= parent->depth; i++)
195 strcat(buffer, "\t\0");
196
197 /* state of selection needs icons so if icons are disabled use text*/
198 if (!global_settings.show_icons)
199 {
200 if (this->state == SELECTED)
201 strcat(buffer, "+\0");
202 else
203 strcat(buffer," \0");
204 }
205 strlcat(buffer, P2STR((const unsigned char *)this->name), buffer_len);
206
207 return buffer;
208}
209
210static int item_get_talk(int selected_item, void *data)
211{
212 struct category *root = (struct category*)data;
213 struct category *parent;
214 struct child *this = find_index(root, selected_item , &parent);
215 if (global_settings.talk_menu)
216 {
217 long id = P2ID((const unsigned char *)(this->name));
218 if(id>=0)
219 talk_id(id, true);
220 else
221 talk_spell(this->name, true);
222 talk_id(VOICE_PAUSE,true);
223 if (this->state == SELECTED)
224 talk_id(LANG_ON, true);
225 else if (this->state == DESELECTED)
226 talk_id(LANG_OFF, true);
227 }
228 return 0;
229}
230
231static enum themable_icons item_get_icon(int selected_item, void * data)
232{
233 struct category *root = (struct category*)data;
234 struct category *parent;
235 struct child *this = find_index(root, selected_item, &parent);
236
237 switch (this->state)
238 {
239 case SELECTED:
240 return Icon_Submenu;
241 case COLLAPSED:
242 return Icon_NOICON;
243 case EXPANDED:
244 return Icon_Submenu_Entered;
245 default:
246 return Icon_NOICON;
247 }
248 return Icon_NOICON;
249}
250
251/* supply your original mask,the page header (ie. User do this..), mask items
252 and count, they will be selected automatically if the mask includes
253 them. If user selects new items and chooses to save settings
254 new mask returned otherwise, original is returned
255*/
256int mask_select(int mask, const unsigned char* headermsg,
257 struct s_mask_items *mask_items, size_t items)
258{
259 struct simplelist_info info;
260
261 struct child action_child[items];
262 for (unsigned i = 0; i < items; i++)
263 {
264 action_child[i].name = mask_items[i].name;
265 action_child[i].category = &empty;
266 action_child[i].key_value = mask_items[i].bit_value;
267 action_child[i].state = mask_items[i].bit_value & mask ?
268 SELECTED : DESELECTED;
269 }
270
271 struct category root = {
272 .name = "",
273 .children = (struct child*) &action_child,
274 .children_count = items,
275 .depth = -1,
276 .previous = NULL,
277 };
278
279 simplelist_info_init(&info, P2STR(headermsg), count_items(&root), &root);
280 info.get_name = item_get_name;
281 info.action_callback = item_action_callback;
282 info.get_icon = item_get_icon;
283 info.get_talk = item_get_talk;
284 simplelist_show_list(&info);
285
286 return calculate_mask_r(&root,0);
287}
diff --git a/apps/gui/mask_select.h b/apps/gui/mask_select.h
new file mode 100644
index 0000000000..8578133b9c
--- /dev/null
+++ b/apps/gui/mask_select.h
@@ -0,0 +1,41 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2016 William Wilgus
10 * Derivative of folder_select.h by:
11 * Copyright (C) 2011 Jonathan Gordon
12 *
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.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22
23#ifndef __MASK_SELECT_H__
24#define __MASK_SELECT_H__
25
26/**
27 * A GUI browser to select masks on a target
28 *
29 * It reads an original mask supplied to function
30 * and pre-selects the corresponding actions in the UI. If the user is done it
31 * returns the new mask, assuming the user confirms the yesno dialog.
32 *
33 * Returns new mask if the selected options have changed, otherwise
34 * returns the mask originally supplied */
35struct s_mask_items {
36 const char* name;
37 const int bit_value;
38};
39int mask_select(int mask, const unsigned char* headermsg,
40 struct s_mask_items *mask_items, size_t items);
41#endif /* __MASK_SELECT_H__ */
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 8d2b579f3b..676516ec3d 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -13479,3 +13479,171 @@
13479 ibassodx90: "Android Debug Bridge" 13479 ibassodx90: "Android Debug Bridge"
13480 </voice> 13480 </voice>
13481</phrase> 13481</phrase>
13482<phrase>
13483 id: LANG_ACTION_ENABLED
13484 desc: Selective Actions
13485 user: core
13486 <source>
13487 *: "Enabled"
13488 </source>
13489 <dest>
13490 *: "Enabled"
13491 </dest>
13492 <voice>
13493 *: "Enabled"
13494 </voice>
13495</phrase>
13496<phrase>
13497 id: LANG_ACTION_PLAY
13498 desc: Selective Actions
13499 user: core
13500 <source>
13501 *: "Play"
13502 </source>
13503 <dest>
13504 *: "Play"
13505 </dest>
13506 <voice>
13507 *: "Play"
13508 </voice>
13509</phrase>
13510<phrase>
13511 id: LANG_ACTION_SEEK
13512 desc: Selective Actions
13513 user: core
13514 <source>
13515 *: "Seek"
13516 </source>
13517 <dest>
13518 *: "Seek"
13519 </dest>
13520 <voice>
13521 *: "Seek"
13522 </voice>
13523</phrase>
13524<phrase>
13525 id: LANG_ACTION_SKIP
13526 desc: Selective Actions
13527 user: core
13528 <source>
13529 *: "Skip"
13530 </source>
13531 <dest>
13532 *: "Skip"
13533 </dest>
13534 <voice>
13535 *: "Skip"
13536 </voice>
13537</phrase>
13538<phrase>
13539 id: LANG_BACKLIGHT_SELECTIVE
13540 desc: Backlight behaviour setting
13541 user: core
13542 <source>
13543 *: "Selective Backlight"
13544 </source>
13545 <dest>
13546 *: "Selective Backlight"
13547 </dest>
13548 <voice>
13549 *: "Selective Backlight"
13550 </voice>
13551</phrase>
13552<phrase>
13553 id: LANG_ACTION_DISABLE_EXT_POWER
13554 desc: Backlight behaviour setting
13555 user: core
13556 <source>
13557 *: "Disable on External Power"
13558 </source>
13559 <dest>
13560 *: "Disable on External Power"
13561 </dest>
13562 <voice>
13563 *: "Disable on External Power"
13564 </voice>
13565</phrase>
13566<phrase>
13567 id: LANG_ACTION_DISABLE_UNMAPPED
13568 desc: Backlight behaviour setting
13569 user: core
13570 <source>
13571 *: "Disable Unmapped Keys"
13572 </source>
13573 <dest>
13574 *: "Disable Unmapped Keys"
13575 </dest>
13576 <voice>
13577 *: "Disable Unmapped Keys"
13578 </voice>
13579</phrase>
13580<phrase>
13581 id: LANG_SOFTLOCK_SELECTIVE
13582 desc: Softlock behaviour setting
13583 user: core
13584 <source>
13585 *: "Advanced Key Lock"
13586 </source>
13587 <dest>
13588 *: "Advanced Key Lock"
13589 </dest>
13590 <voice>
13591 *: "Advanced Key Lock"
13592 </voice>
13593</phrase>
13594<phrase>
13595 id: LANG_ACTION_AUTOLOCK_ON
13596 desc: Softlock behaviour setting
13597 user: core
13598 <source>
13599 *: "Autolock On"
13600 </source>
13601 <dest>
13602 *: "Autolock On"
13603 </dest>
13604 <voice>
13605 *: "Autolock On"
13606 </voice>
13607</phrase>
13608<phrase>
13609 id: LANG_ACTION_AUTOLOCK_OFF
13610 desc: Softlock behaviour setting
13611 user: core
13612 <source>
13613 *: "Autolock Off"
13614 </source>
13615 <dest>
13616 *: "Autolock Off"
13617 </dest>
13618 <voice>
13619 *: "Autolock Off"
13620 </voice>
13621</phrase>
13622<phrase>
13623 id: LANG_ACTION_DISABLE_NOTIFY
13624 desc: Softlock behaviour setting
13625 user: core
13626 <source>
13627 *: "Disable Notify"
13628 </source>
13629 <dest>
13630 *: "Disable Notify"
13631 </dest>
13632 <voice>
13633 *: "Disable Notify"
13634 </voice>
13635</phrase>
13636<phrase>
13637 id: LANG_ACTION_DISABLE_TOUCH
13638 desc: Softlock behaviour setting
13639 user: core
13640 <source>
13641 *: "Disable Touch"
13642 </source>
13643 <dest>
13644 *: "Disable Touch"
13645 </dest>
13646 <voice>
13647 *: "Disable Touch"
13648 </voice>
13649</phrase>
diff --git a/apps/menus/display_menu.c b/apps/menus/display_menu.c
index 948dcede00..5d53cbfe16 100644
--- a/apps/menus/display_menu.c
+++ b/apps/menus/display_menu.c
@@ -38,6 +38,10 @@
38#ifdef HAVE_REMOTE_LCD 38#ifdef HAVE_REMOTE_LCD
39#include "lcd-remote.h" 39#include "lcd-remote.h"
40#endif 40#endif
41#ifdef HAVE_BACKLIGHT
42#include "mask_select.h"
43#include "splash.h"
44#endif
41#ifdef HAVE_TOUCHSCREEN 45#ifdef HAVE_TOUCHSCREEN
42#include "screens.h" 46#include "screens.h"
43#endif 47#endif
@@ -46,9 +50,29 @@
46#include "rbunicode.h" 50#include "rbunicode.h"
47 51
48#ifdef HAVE_BACKLIGHT 52#ifdef HAVE_BACKLIGHT
49static int filterfirstkeypress_callback(int action,const struct menu_item_ex *this_item) 53static int selectivebacklight_callback(int action,const struct menu_item_ex *this_item)
50{ 54{
51 (void)this_item; 55 (void)this_item;
56
57 switch (action)
58 {
59 case ACTION_EXIT_MENUITEM:
60 case ACTION_STD_MENU:
61 case ACTION_STD_CANCEL:
62 set_selective_backlight_actions(
63 global_settings.bl_selective_actions,
64 global_settings.bl_selective_actions_mask,
65 global_settings.bl_filter_first_keypress);
66 break;
67 }
68
69 return action;
70}
71
72static int filterfirstkeypress_callback(int action,const struct menu_item_ex *this_item)
73{
74 /*(void)this_item;REMOVED*/
75
52 switch (action) 76 switch (action)
53 { 77 {
54 case ACTION_EXIT_MENUITEM: 78 case ACTION_EXIT_MENUITEM:
@@ -56,13 +80,43 @@ static int filterfirstkeypress_callback(int action,const struct menu_item_ex *th
56#ifdef HAVE_REMOTE_LCD 80#ifdef HAVE_REMOTE_LCD
57 set_remote_backlight_filter_keypress( 81 set_remote_backlight_filter_keypress(
58 global_settings.remote_bl_filter_first_keypress); 82 global_settings.remote_bl_filter_first_keypress);
59#endif 83#endif /* HAVE_REMOTE_LCD */
60 84 selectivebacklight_callback(action,this_item);/*uses Filter First KP*/
61 break; 85 break;
62 } 86 }
87
63 return action; 88 return action;
64} 89}
90
91static int selectivebacklight_set_mask(void* param)
92{
93 (void)param;
94 int mask = global_settings.bl_selective_actions_mask;
95 struct s_mask_items maskitems[]={
96 {ID2P(LANG_VOLUME) , SEL_ACTION_VOL},
97 {ID2P(LANG_ACTION_PLAY), SEL_ACTION_PLAY},
98 {ID2P(LANG_ACTION_SEEK), SEL_ACTION_SEEK},
99 {ID2P(LANG_ACTION_SKIP), SEL_ACTION_SKIP},
100 {ID2P(LANG_ACTION_DISABLE_UNMAPPED), SEL_ACTION_NOUNMAPPED}
101#if CONFIG_CHARGING
102 ,{ID2P(LANG_ACTION_DISABLE_EXT_POWER), SEL_ACTION_NOEXT}
65#endif 103#endif
104 };
105
106 mask = mask_select(mask, ID2P(LANG_BACKLIGHT_SELECTIVE)
107 , maskitems, ARRAYLEN(maskitems));
108
109 if (mask == SEL_ACTION_NONE || mask == SEL_ACTION_NOEXT)
110 global_settings.bl_selective_actions = false;
111 else if (global_settings.bl_selective_actions_mask != mask)
112 global_settings.bl_selective_actions = true;
113
114 global_settings.bl_selective_actions_mask = mask;
115
116 return true;
117}
118
119#endif /* HAVE_BACKLIGHT */
66#ifdef HAVE_LCD_FLIP 120#ifdef HAVE_LCD_FLIP
67static int flipdisplay_callback(int action,const struct menu_item_ex *this_item) 121static int flipdisplay_callback(int action,const struct menu_item_ex *this_item)
68{ 122{
@@ -88,11 +142,11 @@ static int flipdisplay_callback(int action,const struct menu_item_ex *this_item)
88#ifdef HAVE_BACKLIGHT 142#ifdef HAVE_BACKLIGHT
89MENUITEM_SETTING(backlight_timeout, &global_settings.backlight_timeout, NULL); 143MENUITEM_SETTING(backlight_timeout, &global_settings.backlight_timeout, NULL);
90#if CONFIG_CHARGING 144#if CONFIG_CHARGING
91MENUITEM_SETTING(backlight_timeout_plugged, 145MENUITEM_SETTING(backlight_timeout_plugged,
92 &global_settings.backlight_timeout_plugged, NULL); 146 &global_settings.backlight_timeout_plugged, NULL);
93#endif 147#endif
94#ifdef HAS_BUTTON_HOLD 148#ifdef HAS_BUTTON_HOLD
95MENUITEM_SETTING(backlight_on_button_hold, 149MENUITEM_SETTING(backlight_on_button_hold,
96 &global_settings.backlight_on_button_hold, NULL); 150 &global_settings.backlight_on_button_hold, NULL);
97#endif 151#endif
98MENUITEM_SETTING(caption_backlight, &global_settings.caption_backlight, NULL); 152MENUITEM_SETTING(caption_backlight, &global_settings.caption_backlight, NULL);
@@ -101,9 +155,21 @@ MENUITEM_SETTING(caption_backlight, &global_settings.caption_backlight, NULL);
101MENUITEM_SETTING(backlight_fade_in, &global_settings.backlight_fade_in, NULL); 155MENUITEM_SETTING(backlight_fade_in, &global_settings.backlight_fade_in, NULL);
102MENUITEM_SETTING(backlight_fade_out, &global_settings.backlight_fade_out, NULL); 156MENUITEM_SETTING(backlight_fade_out, &global_settings.backlight_fade_out, NULL);
103#endif 157#endif
104MENUITEM_SETTING(bl_filter_first_keypress, 158MENUITEM_SETTING(bl_filter_first_keypress,
105 &global_settings.bl_filter_first_keypress, 159 &global_settings.bl_filter_first_keypress,
106 filterfirstkeypress_callback); 160 filterfirstkeypress_callback);
161
162MENUITEM_SETTING(bl_selective_actions,
163 &global_settings.bl_selective_actions,
164 selectivebacklight_callback);
165
166MENUITEM_FUNCTION(sel_backlight_mask, 0, ID2P(LANG_SETTINGS),
167 selectivebacklight_set_mask, NULL,
168 selectivebacklight_callback, Icon_Menu_setting);
169
170MAKE_MENU(sel_backlight, ID2P(LANG_BACKLIGHT_SELECTIVE),
171 NULL, Icon_Menu_setting, &bl_selective_actions, &sel_backlight_mask);
172
107#ifdef HAVE_LCD_SLEEP_SETTING 173#ifdef HAVE_LCD_SLEEP_SETTING
108MENUITEM_SETTING(lcd_sleep_after_backlight_off, 174MENUITEM_SETTING(lcd_sleep_after_backlight_off,
109 &global_settings.lcd_sleep_after_backlight_off, NULL); 175 &global_settings.lcd_sleep_after_backlight_off, NULL);
@@ -124,6 +190,8 @@ MENUITEM_SETTING(flip_display, &global_settings.flip_display, flipdisplay_callba
124#endif 190#endif
125#endif /* HAVE_LCD_BITMAP */ 191#endif /* HAVE_LCD_BITMAP */
126 192
193
194
127/* now the actual menu */ 195/* now the actual menu */
128MAKE_MENU(lcd_settings,ID2P(LANG_LCD_MENU), 196MAKE_MENU(lcd_settings,ID2P(LANG_LCD_MENU),
129 NULL, Icon_Display_menu 197 NULL, Icon_Display_menu
@@ -141,6 +209,7 @@ MAKE_MENU(lcd_settings,ID2P(LANG_LCD_MENU),
141 ,&backlight_fade_in, &backlight_fade_out 209 ,&backlight_fade_in, &backlight_fade_out
142#endif 210#endif
143 ,&bl_filter_first_keypress 211 ,&bl_filter_first_keypress
212 ,&sel_backlight
144# ifdef HAVE_LCD_SLEEP_SETTING 213# ifdef HAVE_LCD_SLEEP_SETTING
145 ,&lcd_sleep_after_backlight_off 214 ,&lcd_sleep_after_backlight_off
146# endif 215# endif
@@ -167,31 +236,31 @@ MAKE_MENU(lcd_settings,ID2P(LANG_LCD_MENU),
167/********************************/ 236/********************************/
168/* Remote LCD settings menu */ 237/* Remote LCD settings menu */
169#ifdef HAVE_REMOTE_LCD 238#ifdef HAVE_REMOTE_LCD
170MENUITEM_SETTING(remote_backlight_timeout, 239MENUITEM_SETTING(remote_backlight_timeout,
171 &global_settings.remote_backlight_timeout, NULL); 240 &global_settings.remote_backlight_timeout, NULL);
172 241
173#if CONFIG_CHARGING 242#if CONFIG_CHARGING
174MENUITEM_SETTING(remote_backlight_timeout_plugged, 243MENUITEM_SETTING(remote_backlight_timeout_plugged,
175 &global_settings.remote_backlight_timeout_plugged, NULL); 244 &global_settings.remote_backlight_timeout_plugged, NULL);
176#endif 245#endif
177 246
178#ifdef HAS_REMOTE_BUTTON_HOLD 247#ifdef HAS_REMOTE_BUTTON_HOLD
179MENUITEM_SETTING(remote_backlight_on_button_hold, 248MENUITEM_SETTING(remote_backlight_on_button_hold,
180 &global_settings.remote_backlight_on_button_hold, NULL); 249 &global_settings.remote_backlight_on_button_hold, NULL);
181#endif 250#endif
182 251
183MENUITEM_SETTING(remote_caption_backlight, 252MENUITEM_SETTING(remote_caption_backlight,
184 &global_settings.remote_caption_backlight, NULL); 253 &global_settings.remote_caption_backlight, NULL);
185MENUITEM_SETTING(remote_bl_filter_first_keypress, 254MENUITEM_SETTING(remote_bl_filter_first_keypress,
186 &global_settings.remote_bl_filter_first_keypress, 255 &global_settings.remote_bl_filter_first_keypress,
187 filterfirstkeypress_callback); 256 filterfirstkeypress_callback);
188MENUITEM_SETTING(remote_contrast, 257MENUITEM_SETTING(remote_contrast,
189 &global_settings.remote_contrast, NULL); 258 &global_settings.remote_contrast, NULL);
190MENUITEM_SETTING(remote_invert, 259MENUITEM_SETTING(remote_invert,
191 &global_settings.remote_invert, NULL); 260 &global_settings.remote_invert, NULL);
192 261
193#ifdef HAVE_LCD_FLIP 262#ifdef HAVE_LCD_FLIP
194MENUITEM_SETTING(remote_flip_display, 263MENUITEM_SETTING(remote_flip_display,
195 &global_settings.remote_flip_display, flipdisplay_callback); 264 &global_settings.remote_flip_display, flipdisplay_callback);
196#endif 265#endif
197 266
@@ -207,7 +276,7 @@ static int ticking_callback(int action,const struct menu_item_ex *this_item)
207 } 276 }
208 return action; 277 return action;
209} 278}
210MENUITEM_SETTING(remote_reduce_ticking, 279MENUITEM_SETTING(remote_reduce_ticking,
211 &global_settings.remote_reduce_ticking, ticking_callback); 280 &global_settings.remote_reduce_ticking, ticking_callback);
212#endif 281#endif
213 282
@@ -222,7 +291,7 @@ MAKE_MENU(lcd_remote_settings, ID2P(LANG_LCD_REMOTE_MENU),
222#endif 291#endif
223 &remote_caption_backlight, &remote_bl_filter_first_keypress, 292 &remote_caption_backlight, &remote_bl_filter_first_keypress,
224 &remote_contrast, &remote_invert 293 &remote_contrast, &remote_invert
225 294
226#ifdef HAVE_LCD_FLIP 295#ifdef HAVE_LCD_FLIP
227 ,&remote_flip_display 296 ,&remote_flip_display
228#endif 297#endif
@@ -319,15 +388,15 @@ static int peakmeter_callback(int action,const struct menu_item_ex *this_item)
319 } 388 }
320 return action; 389 return action;
321} 390}
322MENUITEM_SETTING(peak_meter_hold, 391MENUITEM_SETTING(peak_meter_hold,
323 &global_settings.peak_meter_hold, peakmeter_callback); 392 &global_settings.peak_meter_hold, peakmeter_callback);
324MENUITEM_SETTING(peak_meter_clip_hold, 393MENUITEM_SETTING(peak_meter_clip_hold,
325 &global_settings.peak_meter_clip_hold, peakmeter_callback); 394 &global_settings.peak_meter_clip_hold, peakmeter_callback);
326#ifdef HAVE_RECORDING 395#ifdef HAVE_RECORDING
327MENUITEM_SETTING(peak_meter_clipcounter, 396MENUITEM_SETTING(peak_meter_clipcounter,
328 &global_settings.peak_meter_clipcounter, NULL); 397 &global_settings.peak_meter_clipcounter, NULL);
329#endif 398#endif
330MENUITEM_SETTING(peak_meter_release, 399MENUITEM_SETTING(peak_meter_release,
331 &global_settings.peak_meter_release, peakmeter_callback); 400 &global_settings.peak_meter_release, peakmeter_callback);
332/** 401/**
333 * Menu to select wether the scale of the meter 402 * Menu to select wether the scale of the meter
@@ -356,7 +425,7 @@ static int peak_meter_scale(void) {
356 /* we only store -dBfs */ 425 /* we only store -dBfs */
357 global_settings.peak_meter_min = -peak_meter_get_min() / 100; 426 global_settings.peak_meter_min = -peak_meter_get_min() / 100;
358 global_settings.peak_meter_max = -peak_meter_get_max() / 100; 427 global_settings.peak_meter_max = -peak_meter_get_max() / 100;
359 428
360 /* limit the returned value to the allowed range */ 429 /* limit the returned value to the allowed range */
361 if(global_settings.peak_meter_min > 89) 430 if(global_settings.peak_meter_min > 89)
362 global_settings.peak_meter_min = 89; 431 global_settings.peak_meter_min = 89;
@@ -472,12 +541,12 @@ MENUITEM_FUNCTION(histogram, 0,
472 541
473MENUITEM_FUNCTION(peak_meter_scale_item, 0, ID2P(LANG_PM_SCALE), 542MENUITEM_FUNCTION(peak_meter_scale_item, 0, ID2P(LANG_PM_SCALE),
474 peak_meter_scale, NULL, NULL, Icon_NOICON); 543 peak_meter_scale, NULL, NULL, Icon_NOICON);
475MENUITEM_FUNCTION(peak_meter_min_item, 0, ID2P(LANG_PM_MIN), 544MENUITEM_FUNCTION(peak_meter_min_item, 0, ID2P(LANG_PM_MIN),
476 peak_meter_min, NULL, NULL, Icon_NOICON); 545 peak_meter_min, NULL, NULL, Icon_NOICON);
477MENUITEM_FUNCTION(peak_meter_max_item, 0, ID2P(LANG_PM_MAX), 546MENUITEM_FUNCTION(peak_meter_max_item, 0, ID2P(LANG_PM_MAX),
478 peak_meter_max, NULL, NULL, Icon_NOICON); 547 peak_meter_max, NULL, NULL, Icon_NOICON);
479MAKE_MENU(peak_meter_menu, ID2P(LANG_PM_MENU), NULL, Icon_NOICON, 548MAKE_MENU(peak_meter_menu, ID2P(LANG_PM_MENU), NULL, Icon_NOICON,
480 &peak_meter_release, &peak_meter_hold, 549 &peak_meter_release, &peak_meter_hold,
481 &peak_meter_clip_hold, 550 &peak_meter_clip_hold,
482#ifdef HAVE_RECORDING 551#ifdef HAVE_RECORDING
483 &peak_meter_clipcounter, 552 &peak_meter_clipcounter,
diff --git a/apps/menus/settings_menu.c b/apps/menus/settings_menu.c
index f42550cc6a..5c99cb4cd4 100644
--- a/apps/menus/settings_menu.c
+++ b/apps/menus/settings_menu.c
@@ -49,12 +49,67 @@
49#include "dircache.h" 49#include "dircache.h"
50#endif 50#endif
51#include "folder_select.h" 51#include "folder_select.h"
52 52#ifndef HAS_BUTTON_HOLD
53#include "mask_select.h"
54#endif
53#if defined(DX50) || defined(DX90) 55#if defined(DX50) || defined(DX90)
54#include "governor-ibasso.h" 56#include "governor-ibasso.h"
55#include "usb-ibasso.h" 57#include "usb-ibasso.h"
56#endif 58#endif
57 59
60#ifndef HAS_BUTTON_HOLD
61static int selectivesoftlock_callback(int action,
62 const struct menu_item_ex *this_item)
63{
64 (void)this_item;
65
66 switch (action)
67 {
68 case ACTION_STD_MENU:
69 case ACTION_STD_CANCEL:
70 case ACTION_EXIT_MENUITEM:
71 set_selective_softlock_actions(
72 global_settings.bt_selective_softlock_actions,
73 global_settings.bt_selective_softlock_actions_mask);
74 break;
75 }
76
77 return action;
78}
79
80static int selectivesoftlock_set_mask(void* param)
81{
82 (void)param;
83int mask = global_settings.bt_selective_softlock_actions_mask;
84 struct s_mask_items maskitems[]={
85 {ID2P(LANG_VOLUME) , SEL_ACTION_VOL},
86 {ID2P(LANG_ACTION_PLAY), SEL_ACTION_PLAY},
87 {ID2P(LANG_ACTION_SEEK), SEL_ACTION_SEEK},
88 {ID2P(LANG_ACTION_SKIP), SEL_ACTION_SKIP},
89 #ifdef HAVE_BACKLIGHT
90 {ID2P(LANG_ACTION_AUTOLOCK_ON), SEL_ACTION_AUTOLOCK},
91 #endif
92 #if defined(HAVE_TOUCHPAD) || defined(HAVE_TOUCHSCREEN)
93 {ID2P(LANG_ACTION_DISABLE_TOUCH) , SEL_ACTION_NOTOUCH},
94 #endif
95 {ID2P(LANG_ACTION_DISABLE_NOTIFY), SEL_ACTION_NONOTIFY}
96 };
97
98 mask = mask_select(mask, ID2P(LANG_SOFTLOCK_SELECTIVE)
99 , maskitems,ARRAYLEN(maskitems));
100
101 if (mask == SEL_ACTION_NONE)
102 global_settings.bt_selective_softlock_actions = false;
103 else if (global_settings.bt_selective_softlock_actions_mask != mask)
104 global_settings.bt_selective_softlock_actions = true;
105
106 global_settings.bt_selective_softlock_actions_mask = mask;
107
108 return true;
109}
110
111#endif /* !HAS_BUTTON_HOLD */
112
58/***********************************/ 113/***********************************/
59/* TAGCACHE MENU */ 114/* TAGCACHE MENU */
60#ifdef HAVE_TAGCACHE 115#ifdef HAVE_TAGCACHE
@@ -137,7 +192,7 @@ static int clear_start_directory(void)
137 splash(HZ, ID2P(LANG_RESET_DONE_CLEAR)); 192 splash(HZ, ID2P(LANG_RESET_DONE_CLEAR));
138 return false; 193 return false;
139} 194}
140MENUITEM_FUNCTION(clear_start_directory_item, 0, ID2P(LANG_RESET_START_DIR), 195MENUITEM_FUNCTION(clear_start_directory_item, 0, ID2P(LANG_RESET_START_DIR),
141 clear_start_directory, NULL, NULL, Icon_file_view_menu); 196 clear_start_directory, NULL, NULL, Icon_file_view_menu);
142static int fileview_callback(int action,const struct menu_item_ex *this_item) 197static int fileview_callback(int action,const struct menu_item_ex *this_item)
143{ 198{
@@ -330,6 +385,19 @@ MENUITEM_SETTING(touchpad_deadzone, &global_settings.touchpad_deadzone, NULL);
330MENUITEM_SETTING(shortcuts_replaces_quickscreen, &global_settings.shortcuts_replaces_qs, NULL); 385MENUITEM_SETTING(shortcuts_replaces_quickscreen, &global_settings.shortcuts_replaces_qs, NULL);
331#endif 386#endif
332 387
388#ifndef HAS_BUTTON_HOLD
389
390MENUITEM_SETTING(bt_selective_actions,
391 &global_settings.bt_selective_softlock_actions,
392 selectivesoftlock_callback);
393MENUITEM_FUNCTION(sel_softlock_mask, 0, ID2P(LANG_SETTINGS),
394 selectivesoftlock_set_mask, NULL,
395 selectivesoftlock_callback, Icon_Menu_setting);
396
397MAKE_MENU(sel_softlock, ID2P(LANG_SOFTLOCK_SELECTIVE),
398 NULL, Icon_Menu_setting, &bt_selective_actions, &sel_softlock_mask);
399#endif /* !HAS_BUTTON_HOLD */
400
333#if defined(DX50) || defined(DX90) 401#if defined(DX50) || defined(DX90)
334MENUITEM_SETTING(governor, &global_settings.governor, NULL); 402MENUITEM_SETTING(governor, &global_settings.governor, NULL);
335MENUITEM_SETTING(usb_mode, &global_settings.usb_mode, NULL); 403MENUITEM_SETTING(usb_mode, &global_settings.usb_mode, NULL);
@@ -380,6 +448,9 @@ MAKE_MENU(system_menu, ID2P(LANG_SYSTEM),
380#ifdef HAVE_TOUCHPAD_DEADZONE 448#ifdef HAVE_TOUCHPAD_DEADZONE
381 &touchpad_deadzone, 449 &touchpad_deadzone,
382#endif 450#endif
451#ifndef HAS_BUTTON_HOLD
452 &sel_softlock,
453#endif
383#ifdef USB_ENABLE_HID 454#ifdef USB_ENABLE_HID
384 &usb_hid, 455 &usb_hid,
385 &usb_keypad_mode, 456 &usb_keypad_mode,
@@ -544,7 +615,7 @@ MAKE_MENU(bookmark_settings_menu, ID2P(LANG_BOOKMARK_SETTINGS), 0,
544/***********************************/ 615/***********************************/
545/* AUTORESUME MENU */ 616/* AUTORESUME MENU */
546#ifdef HAVE_TAGCACHE 617#ifdef HAVE_TAGCACHE
547#if CONFIG_CODEC == SWCODEC 618#if CONFIG_CODEC == SWCODEC
548 619
549static int autoresume_callback(int action, const struct menu_item_ex *this_item) 620static int autoresume_callback(int action, const struct menu_item_ex *this_item)
550{ 621{
@@ -557,7 +628,7 @@ static int autoresume_callback(int action, const struct menu_item_ex *this_item)
557 static const char *lines[] = {ID2P(LANG_TAGCACHE_BUSY), 628 static const char *lines[] = {ID2P(LANG_TAGCACHE_BUSY),
558 ID2P(LANG_TAGCACHE_FORCE_UPDATE)}; 629 ID2P(LANG_TAGCACHE_FORCE_UPDATE)};
559 static const struct text_message message = {lines, 2}; 630 static const struct text_message message = {lines, 2};
560 631
561 if (gui_syncyesno_run(&message, NULL, NULL) == YESNO_YES) 632 if (gui_syncyesno_run(&message, NULL, NULL) == YESNO_YES)
562 tagcache_rebuild_with_splash(); 633 tagcache_rebuild_with_splash();
563 } 634 }
@@ -672,9 +743,9 @@ MAKE_MENU(settings_menu_item, ID2P(LANG_GENERAL_SETTINGS), 0,
672 &startup_shutdown_menu, 743 &startup_shutdown_menu,
673 &bookmark_settings_menu, 744 &bookmark_settings_menu,
674#ifdef HAVE_TAGCACHE 745#ifdef HAVE_TAGCACHE
675#if CONFIG_CODEC == SWCODEC 746#if CONFIG_CODEC == SWCODEC
676 &autoresume_menu, 747 &autoresume_menu,
677#endif 748#endif
678#endif 749#endif
679 &browse_langs, &voice_settings_menu, 750 &browse_langs, &voice_settings_menu,
680#ifdef HAVE_HOTKEY 751#ifdef HAVE_HOTKEY
diff --git a/apps/settings.c b/apps/settings.c
index eed2b3a692..992cc1f391 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -146,7 +146,7 @@ static bool read_nvram_data(char* buf, int max_len)
146 buf[i] = rtc_read(0x14+i); 146 buf[i] = rtc_read(0x14+i);
147#endif 147#endif
148 /* check magic, version */ 148 /* check magic, version */
149 if ((buf[0] != 'R') || (buf[1] != 'b') 149 if ((buf[0] != 'R') || (buf[1] != 'b')
150 || (buf[2] != NVRAM_CONFIG_VERSION)) 150 || (buf[2] != NVRAM_CONFIG_VERSION))
151 return false; 151 return false;
152 /* check crc32 */ 152 /* check crc32 */
@@ -221,7 +221,7 @@ static bool write_nvram_data(char* buf, int max_len)
221 supports that, but this will have to do for now 8-) */ 221 supports that, but this will have to do for now 8-) */
222 for (i=0; i < NVRAM_BLOCK_SIZE; i++ ) { 222 for (i=0; i < NVRAM_BLOCK_SIZE; i++ ) {
223 int r = rtc_write(0x14+i, buf[i]); 223 int r = rtc_write(0x14+i, buf[i]);
224 if (r) 224 if (r)
225 return false; 225 return false;
226 } 226 }
227#endif 227#endif
@@ -307,8 +307,8 @@ bool settings_load_config(const char* file, bool apply)
307#ifdef HAVE_LCD_COLOR 307#ifdef HAVE_LCD_COLOR
308 if (settings[i].flags&F_RGB) 308 if (settings[i].flags&F_RGB)
309 hex_to_rgb(value, (int*)settings[i].setting); 309 hex_to_rgb(value, (int*)settings[i].setting);
310 else 310 else
311#endif 311#endif
312 if (settings[i].cfg_vals == NULL) 312 if (settings[i].cfg_vals == NULL)
313 { 313 {
314 *(int*)settings[i].setting = atoi(value); 314 *(int*)settings[i].setting = atoi(value);
@@ -392,7 +392,7 @@ bool cfg_int_to_string(int setting_id, int val, char* buf, int buf_len)
392 const char* start = settings[setting_id].cfg_vals; 392 const char* start = settings[setting_id].cfg_vals;
393 char* end = NULL; 393 char* end = NULL;
394 int count = 0; 394 int count = 0;
395 395
396 if ((flags&F_T_MASK)==F_T_INT && 396 if ((flags&F_T_MASK)==F_T_INT &&
397 flags&F_TABLE_SETTING) 397 flags&F_TABLE_SETTING)
398 { 398 {
@@ -404,7 +404,7 @@ bool cfg_int_to_string(int setting_id, int val, char* buf, int buf_len)
404 { 404 {
405 if (end == NULL) 405 if (end == NULL)
406 strlcpy(buf, start, buf_len); 406 strlcpy(buf, start, buf_len);
407 else 407 else
408 { 408 {
409 int len = (buf_len > (end-start))? end-start: buf_len; 409 int len = (buf_len > (end-start))? end-start: buf_len;
410 strlcpy(buf, start, len+1); 410 strlcpy(buf, start, len+1);
@@ -412,7 +412,7 @@ bool cfg_int_to_string(int setting_id, int val, char* buf, int buf_len)
412 return true; 412 return true;
413 } 413 }
414 count++; 414 count++;
415 415
416 if (end) 416 if (end)
417 start = end+1; 417 start = end+1;
418 else 418 else
@@ -420,7 +420,7 @@ bool cfg_int_to_string(int setting_id, int val, char* buf, int buf_len)
420 } 420 }
421 return false; 421 return false;
422 } 422 }
423 423
424 while (count < val) 424 while (count < val)
425 { 425 {
426 start = strchr(start,','); 426 start = strchr(start,',');
@@ -432,7 +432,7 @@ bool cfg_int_to_string(int setting_id, int val, char* buf, int buf_len)
432 end = strchr(start,','); 432 end = strchr(start,',');
433 if (end == NULL) 433 if (end == NULL)
434 strlcpy(buf, start, buf_len); 434 strlcpy(buf, start, buf_len);
435 else 435 else
436 { 436 {
437 int len = (buf_len > (end-start))? end-start: buf_len; 437 int len = (buf_len > (end-start))? end-start: buf_len;
438 strlcpy(buf, start, len+1); 438 strlcpy(buf, start, len+1);
@@ -561,7 +561,7 @@ static bool settings_write_config(const char* filename, int options)
561 value[0] = '\0'; 561 value[0] = '\0';
562 if (settings[i].flags & F_DEPRECATED) 562 if (settings[i].flags & F_DEPRECATED)
563 continue; 563 continue;
564 564
565 switch (options) 565 switch (options)
566 { 566 {
567 case SETTINGS_SAVE_CHANGED: 567 case SETTINGS_SAVE_CHANGED:
@@ -939,7 +939,7 @@ void settings_apply(bool read_disk)
939 && global_settings.font_file[0] != '-') { 939 && global_settings.font_file[0] != '-') {
940 int font_ui = screens[SCREEN_MAIN].getuifont(); 940 int font_ui = screens[SCREEN_MAIN].getuifont();
941 const char* loaded_font = font_filename(font_ui); 941 const char* loaded_font = font_filename(font_ui);
942 942
943 snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", 943 snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt",
944 global_settings.font_file); 944 global_settings.font_file);
945 if (!loaded_font || strcmp(loaded_font, buf)) 945 if (!loaded_font || strcmp(loaded_font, buf))
@@ -953,7 +953,7 @@ void settings_apply(bool read_disk)
953 screens[SCREEN_MAIN].setfont(rc); 953 screens[SCREEN_MAIN].setfont(rc);
954 } 954 }
955 } 955 }
956#ifdef HAVE_REMOTE_LCD 956#ifdef HAVE_REMOTE_LCD
957 if ( global_settings.remote_font_file[0] 957 if ( global_settings.remote_font_file[0]
958 && global_settings.remote_font_file[0] != '-') { 958 && global_settings.remote_font_file[0] != '-') {
959 int font_ui = screens[SCREEN_REMOTE].getuifont(); 959 int font_ui = screens[SCREEN_REMOTE].getuifont();
@@ -1064,17 +1064,27 @@ void settings_apply(bool read_disk)
1064 1064
1065#ifdef HAVE_BACKLIGHT 1065#ifdef HAVE_BACKLIGHT
1066 set_backlight_filter_keypress(global_settings.bl_filter_first_keypress); 1066 set_backlight_filter_keypress(global_settings.bl_filter_first_keypress);
1067 set_selective_backlight_actions(global_settings.bl_selective_actions,
1068 global_settings.bl_selective_actions_mask,
1069 global_settings.bl_filter_first_keypress);
1067#ifdef HAVE_REMOTE_LCD 1070#ifdef HAVE_REMOTE_LCD
1068 set_remote_backlight_filter_keypress(global_settings.remote_bl_filter_first_keypress); 1071 set_remote_backlight_filter_keypress(global_settings.remote_bl_filter_first_keypress);
1069#endif 1072#endif
1070#ifdef HAS_BUTTON_HOLD 1073#ifdef HAS_BUTTON_HOLD
1071 backlight_set_on_button_hold(global_settings.backlight_on_button_hold); 1074 backlight_set_on_button_hold(global_settings.backlight_on_button_hold);
1072#endif 1075#endif
1076
1073#ifdef HAVE_LCD_SLEEP_SETTING 1077#ifdef HAVE_LCD_SLEEP_SETTING
1074 lcd_set_sleep_after_backlight_off(global_settings.lcd_sleep_after_backlight_off); 1078 lcd_set_sleep_after_backlight_off(global_settings.lcd_sleep_after_backlight_off);
1075#endif 1079#endif
1076#endif /* HAVE_BACKLIGHT */ 1080#endif /* HAVE_BACKLIGHT */
1077 1081
1082#ifndef HAS_BUTTON_HOLD
1083 set_selective_softlock_actions(
1084 global_settings.bt_selective_softlock_actions,
1085 global_settings.bt_selective_softlock_actions_mask);
1086#endif
1087
1078#ifdef HAVE_TOUCHPAD_SENSITIVITY_SETTING 1088#ifdef HAVE_TOUCHPAD_SENSITIVITY_SETTING
1079 touchpad_set_sensitivity(global_settings.touchpad_sensitivity); 1089 touchpad_set_sensitivity(global_settings.touchpad_sensitivity);
1080#endif 1090#endif
@@ -1243,7 +1253,7 @@ bool set_int_ex(const unsigned char* string,
1243 (void)unit; 1253 (void)unit;
1244 struct settings_list item; 1254 struct settings_list item;
1245 struct int_setting data = { 1255 struct int_setting data = {
1246 function, voice_unit, min, max, step, 1256 function, voice_unit, min, max, step,
1247 formatter, get_talk_id 1257 formatter, get_talk_id
1248 }; 1258 };
1249 item.int_setting = &data; 1259 item.int_setting = &data;
@@ -1269,7 +1279,7 @@ static int32_t set_option_get_talk_id(int value, int unit)
1269} 1279}
1270 1280
1271bool set_option(const char* string, const void* variable, enum optiontype type, 1281bool set_option(const char* string, const void* variable, enum optiontype type,
1272 const struct opt_items* options, 1282 const struct opt_items* options,
1273 int numoptions, void (*function)(int)) 1283 int numoptions, void (*function)(int))
1274{ 1284{
1275 int temp; 1285 int temp;
@@ -1287,7 +1297,7 @@ bool set_option(const char* string, const void* variable, enum optiontype type,
1287 item.setting = &temp; 1297 item.setting = &temp;
1288 if (type == BOOL) 1298 if (type == BOOL)
1289 temp = *(bool*)variable? 1: 0; 1299 temp = *(bool*)variable? 1: 0;
1290 else 1300 else
1291 temp = *(int*)variable; 1301 temp = *(int*)variable;
1292 if (!option_screen(&item, NULL, false, NULL)) 1302 if (!option_screen(&item, NULL, false, NULL))
1293 { 1303 {
diff --git a/apps/settings.h b/apps/settings.h
index e7388b4586..c79aeb37f4 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -529,7 +529,7 @@ struct user_settings
529 int statusbar; /* STATUSBAR_* enum values */ 529 int statusbar; /* STATUSBAR_* enum values */
530#ifdef HAVE_REMOTE_LCD 530#ifdef HAVE_REMOTE_LCD
531 int remote_statusbar; 531 int remote_statusbar;
532#endif 532#endif
533 533
534#if CONFIG_KEYPAD == RECORDER_PAD 534#if CONFIG_KEYPAD == RECORDER_PAD
535 bool buttonbar; /* 0=hide, 1=show */ 535 bool buttonbar; /* 0=hide, 1=show */
@@ -670,7 +670,13 @@ struct user_settings
670#if CONFIG_CHARGING 670#if CONFIG_CHARGING
671 int backlight_timeout_plugged; 671 int backlight_timeout_plugged;
672#endif 672#endif
673#ifndef HAS_BUTTON_HOLD
674 bool bt_selective_softlock_actions;
675 int bt_selective_softlock_actions_mask;
676#endif
673#ifdef HAVE_BACKLIGHT 677#ifdef HAVE_BACKLIGHT
678 bool bl_selective_actions; /* backlight disable on some actions */
679 int bl_selective_actions_mask;/* mask of actions that will not enable backlight */
674#ifdef HAS_BUTTON_HOLD 680#ifdef HAS_BUTTON_HOLD
675 int backlight_on_button_hold; /* what to do with backlight when hold 681 int backlight_on_button_hold; /* what to do with backlight when hold
676 switch is on */ 682 switch is on */
@@ -679,7 +685,8 @@ struct user_settings
679 int lcd_sleep_after_backlight_off; /* when to put lcd to sleep after backlight 685 int lcd_sleep_after_backlight_off; /* when to put lcd to sleep after backlight
680 has turned off */ 686 has turned off */
681#endif 687#endif
682#endif 688#endif /* HAVE_BACKLIGHT */
689
683#if defined(HAVE_BACKLIGHT_FADING_INT_SETTING) 690#if defined(HAVE_BACKLIGHT_FADING_INT_SETTING)
684 int backlight_fade_in; /* backlight fade in timing: 0..3 */ 691 int backlight_fade_in; /* backlight fade in timing: 0..3 */
685 int backlight_fade_out; /* backlight fade in timing: 0..7 */ 692 int backlight_fade_out; /* backlight fade in timing: 0..7 */
@@ -687,7 +694,7 @@ struct user_settings
687 bool backlight_fade_in; 694 bool backlight_fade_in;
688 bool backlight_fade_out; 695 bool backlight_fade_out;
689#endif 696#endif
690#ifdef HAVE_BACKLIGHT_BRIGHTNESS 697#ifdef HAVE_BACKLIGHT_BRIGHTNESS
691 int brightness; 698 int brightness;
692#endif 699#endif
693 700
diff --git a/apps/settings_list.c b/apps/settings_list.c
index 62f232610c..58be3d2575 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -159,7 +159,7 @@
159/* for settings which use the set_int() setting screen. 159/* for settings which use the set_int() setting screen.
160 unit is the UNIT_ define to display/talk. 160 unit is the UNIT_ define to display/talk.
161 the first one saves a string to the config file, 161 the first one saves a string to the config file,
162 the second one saves the variable value to the config file */ 162 the second one saves the variable value to the config file */
163#define INT_SETTING_W_CFGVALS(flags, var, lang_id, default, name, cfg_vals, \ 163#define INT_SETTING_W_CFGVALS(flags, var, lang_id, default, name, cfg_vals, \
164 unit, min, max, step, formatter, get_talk_id, cb) \ 164 unit, min, max, step, formatter, get_talk_id, cb) \
165 {flags|F_INT_SETTING|F_T_INT, &global_settings.var, \ 165 {flags|F_INT_SETTING|F_T_INT, &global_settings.var, \
@@ -864,7 +864,7 @@ const struct settings_list settings[] = {
864 MAX_CONTRAST_SETTING, 1, NULL, NULL }}}}, 864 MAX_CONTRAST_SETTING, 1, NULL, NULL }}}},
865#endif 865#endif
866#ifdef HAVE_BACKLIGHT 866#ifdef HAVE_BACKLIGHT
867 TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, backlight_timeout, LANG_BACKLIGHT, 867 TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, backlight_timeout, LANG_BACKLIGHT,
868 DEFAULT_BACKLIGHT_TIMEOUT, 868 DEFAULT_BACKLIGHT_TIMEOUT,
869 "backlight timeout", off_on, UNIT_SEC, backlight_formatter, 869 "backlight timeout", off_on, UNIT_SEC, backlight_formatter,
870 backlight_getlang, backlight_set_timeout, 20, 870 backlight_getlang, backlight_set_timeout, 20,
@@ -957,7 +957,7 @@ const struct settings_list settings[] = {
957 0,1,2,3,4,5,6,7,8,9,10,15,30,45,60), 957 0,1,2,3,4,5,6,7,8,9,10,15,30,45,60),
958 SYSTEM_SETTING(NVRAM(4), runtime, 0), 958 SYSTEM_SETTING(NVRAM(4), runtime, 0),
959 SYSTEM_SETTING(NVRAM(4), topruntime, 0), 959 SYSTEM_SETTING(NVRAM(4), topruntime, 0),
960 INT_SETTING(F_BANFROMQS, max_files_in_playlist, 960 INT_SETTING(F_BANFROMQS, max_files_in_playlist,
961 LANG_MAX_FILES_IN_PLAYLIST, 961 LANG_MAX_FILES_IN_PLAYLIST,
962#if MEMORYSIZE > 1 962#if MEMORYSIZE > 1
963 10000, 963 10000,
@@ -1071,9 +1071,26 @@ const struct settings_list settings[] = {
1071 1071
1072/** End of old RTC config block **/ 1072/** End of old RTC config block **/
1073 1073
1074#ifndef HAS_BUTTON_HOLD
1075 OFFON_SETTING(0, bt_selective_softlock_actions,
1076 LANG_ACTION_ENABLED, false,
1077 "No Screen Lock For Selected Actions", NULL),
1078 INT_SETTING(0, bt_selective_softlock_actions_mask, LANG_SOFTLOCK_SELECTIVE,
1079 0, "Selective Screen Lock Actions", UNIT_INT,
1080 0, 2048,2, NULL, NULL, NULL),
1081#endif /* !HAS_BUTTON_HOLD */
1082
1074#ifdef HAVE_BACKLIGHT 1083#ifdef HAVE_BACKLIGHT
1075 OFFON_SETTING(0, caption_backlight, LANG_CAPTION_BACKLIGHT, 1084 OFFON_SETTING(0, caption_backlight, LANG_CAPTION_BACKLIGHT,
1076 false, "caption backlight", NULL), 1085 false, "caption backlight", NULL),
1086
1087 OFFON_SETTING(0, bl_selective_actions,
1088 LANG_ACTION_ENABLED, false,
1089 "No Backlight On Selected Actions", NULL),
1090
1091 INT_SETTING(0, bl_selective_actions_mask, LANG_BACKLIGHT_SELECTIVE,
1092 0, "Selective Backlight Actions", UNIT_INT,
1093 0, 2048,2, NULL, NULL, NULL),
1077#ifdef HAVE_REMOTE_LCD 1094#ifdef HAVE_REMOTE_LCD
1078 OFFON_SETTING(0, remote_caption_backlight, LANG_CAPTION_BACKLIGHT, 1095 OFFON_SETTING(0, remote_caption_backlight, LANG_CAPTION_BACKLIGHT,
1079 false, "remote caption backlight", NULL), 1096 false, "remote caption backlight", NULL),
@@ -1351,7 +1368,7 @@ const struct settings_list settings[] = {
1351 ID2P(LANG_TIME), ID2P(LANG_FILESIZE)), 1368 ID2P(LANG_TIME), ID2P(LANG_FILESIZE)),
1352 {F_T_INT|F_RECSETTING, &global_settings.rec_source, LANG_RECORDING_SOURCE, 1369 {F_T_INT|F_RECSETTING, &global_settings.rec_source, LANG_RECORDING_SOURCE,
1353 INT(0), "rec source", 1370 INT(0), "rec source",
1354 &HAVE_MIC_REC_(",mic") 1371 &HAVE_MIC_REC_(",mic")
1355 HAVE_LINE_REC_(",line") 1372 HAVE_LINE_REC_(",line")
1356 HAVE_SPDIF_REC_(",spdif") 1373 HAVE_SPDIF_REC_(",spdif")
1357 HAVE_FMRADIO_REC_(",fmradio")[1], 1374 HAVE_FMRADIO_REC_(",fmradio")[1],
@@ -1427,17 +1444,17 @@ const struct settings_list settings[] = {
1427 INT_SETTING(F_RECSETTING, rec_stop_thres_linear, LANG_RECORD_STOP_THRESHOLD, 10, 1444 INT_SETTING(F_RECSETTING, rec_stop_thres_linear, LANG_RECORD_STOP_THRESHOLD, 10,
1428 "trigger stop threshold linear", UNIT_PERCENT, 0, 100, 1, NULL, NULL, NULL), 1445 "trigger stop threshold linear", UNIT_PERCENT, 0, 100, 1, NULL, NULL, NULL),
1429 TABLE_SETTING(F_RECSETTING, rec_start_duration, LANG_MIN_DURATION, 0, 1446 TABLE_SETTING(F_RECSETTING, rec_start_duration, LANG_MIN_DURATION, 0,
1430 "trigger start duration", 1447 "trigger start duration",
1431 "0s,1s,2s,5s,10s,15s,20s,25s,30s,1min,2min,5min,10min", 1448 "0s,1s,2s,5s,10s,15s,20s,25s,30s,1min,2min,5min,10min",
1432 UNIT_SEC, NULL, NULL, NULL, 13, 1449 UNIT_SEC, NULL, NULL, NULL, 13,
1433 0,1,2,5,10,15,20,25,30,60,120,300,600), 1450 0,1,2,5,10,15,20,25,30,60,120,300,600),
1434 TABLE_SETTING(F_RECSETTING, rec_stop_postrec, LANG_MIN_DURATION, 0, 1451 TABLE_SETTING(F_RECSETTING, rec_stop_postrec, LANG_MIN_DURATION, 0,
1435 "trigger stop duration", 1452 "trigger stop duration",
1436 "0s,1s,2s,5s,10s,15s,20s,25s,30s,1min,2min,5min,10min", 1453 "0s,1s,2s,5s,10s,15s,20s,25s,30s,1min,2min,5min,10min",
1437 UNIT_SEC, NULL, NULL, NULL, 13, 1454 UNIT_SEC, NULL, NULL, NULL, 13,
1438 0,1,2,5,10,15,20,25,30,60,120,300,600), 1455 0,1,2,5,10,15,20,25,30,60,120,300,600),
1439 TABLE_SETTING(F_RECSETTING, rec_stop_gap, LANG_RECORD_STOP_GAP, 1, 1456 TABLE_SETTING(F_RECSETTING, rec_stop_gap, LANG_RECORD_STOP_GAP, 1,
1440 "trigger min gap", 1457 "trigger min gap",
1441 "0s,1s,2s,5s,10s,15s,20s,25s,30s,1min,2min,5min,10min", 1458 "0s,1s,2s,5s,10s,15s,20s,25s,30s,1min,2min,5min,10min",
1442 UNIT_SEC, NULL, NULL, NULL, 13, 1459 UNIT_SEC, NULL, NULL, NULL, 13,
1443 0,1,2,5,10,15,20,25,30,60,120,300,600), 1460 0,1,2,5,10,15,20,25,30,60,120,300,600),
@@ -1469,7 +1486,7 @@ const struct settings_list settings[] = {
1469 LANG_SET_BOOL_YES, LANG_SET_BOOL_NO, NULL), 1486 LANG_SET_BOOL_YES, LANG_SET_BOOL_NO, NULL),
1470 1487
1471#ifdef HAVE_TAGCACHE 1488#ifdef HAVE_TAGCACHE
1472#if CONFIG_CODEC == SWCODEC 1489#if CONFIG_CODEC == SWCODEC
1473 BOOL_SETTING(0, autoresume_enable, LANG_AUTORESUME, false, 1490 BOOL_SETTING(0, autoresume_enable, LANG_AUTORESUME, false,
1474 "autoresume enable", off_on, 1491 "autoresume enable", off_on,
1475 LANG_SET_BOOL_YES, LANG_SET_BOOL_NO, NULL), 1492 LANG_SET_BOOL_YES, LANG_SET_BOOL_NO, NULL),
@@ -1482,7 +1499,7 @@ const struct settings_list settings[] = {
1482 ID2P(LANG_AUTORESUME_CUSTOM)), 1499 ID2P(LANG_AUTORESUME_CUSTOM)),
1483 TEXT_SETTING(0, autoresume_paths, "autoresume next track paths", 1500 TEXT_SETTING(0, autoresume_paths, "autoresume next track paths",
1484 "/podcast:/podcasts", NULL, NULL), 1501 "/podcast:/podcasts", NULL, NULL),
1485#endif 1502#endif
1486 1503
1487 OFFON_SETTING(0, runtimedb, LANG_RUNTIMEDB_ACTIVE, false, 1504 OFFON_SETTING(0, runtimedb, LANG_RUNTIMEDB_ACTIVE, false,
1488 "gather runtime data", NULL), 1505 "gather runtime data", NULL),
@@ -1741,11 +1758,11 @@ const struct settings_list settings[] = {
1741 CHOICE_SETTING(F_SOUNDSETTING|F_NO_WRAP, compressor_settings.knee, 1758 CHOICE_SETTING(F_SOUNDSETTING|F_NO_WRAP, compressor_settings.knee,
1742 LANG_COMPRESSOR_KNEE, 1, "compressor knee", 1759 LANG_COMPRESSOR_KNEE, 1, "compressor knee",
1743 "hard knee,soft knee", compressor_set, 2, 1760 "hard knee,soft knee", compressor_set, 2,
1744 ID2P(LANG_COMPRESSOR_HARD_KNEE), ID2P(LANG_COMPRESSOR_SOFT_KNEE)), 1761 ID2P(LANG_COMPRESSOR_HARD_KNEE), ID2P(LANG_COMPRESSOR_SOFT_KNEE)),
1745 INT_SETTING_NOWRAP(F_SOUNDSETTING, compressor_settings.attack_time, 1762 INT_SETTING_NOWRAP(F_SOUNDSETTING, compressor_settings.attack_time,
1746 LANG_COMPRESSOR_ATTACK, 5, 1763 LANG_COMPRESSOR_ATTACK, 5,
1747 "compressor attack time", UNIT_MS, 0, 30, 1764 "compressor attack time", UNIT_MS, 0, 30,
1748 5, NULL, NULL, compressor_set), 1765 5, NULL, NULL, compressor_set),
1749 INT_SETTING_NOWRAP(F_SOUNDSETTING, compressor_settings.release_time, 1766 INT_SETTING_NOWRAP(F_SOUNDSETTING, compressor_settings.release_time,
1750 LANG_COMPRESSOR_RELEASE, 500, 1767 LANG_COMPRESSOR_RELEASE, 500,
1751 "compressor release time", UNIT_MS, 100, 1000, 1768 "compressor release time", UNIT_MS, 100, 1000,
@@ -1933,38 +1950,38 @@ const struct settings_list settings[] = {
1933 UNIT_SEC, formatter_unit_0_is_skip_track, 1950 UNIT_SEC, formatter_unit_0_is_skip_track,
1934 getlang_unit_0_is_skip_track, NULL, 1951 getlang_unit_0_is_skip_track, NULL,
1935 19, -1,0,1,2,3,5,7,10,15,20,30,45,60,90,120,180,300,600,900), 1952 19, -1,0,1,2,3,5,7,10,15,20,30,45,60,90,120,180,300,600,900),
1936 CHOICE_SETTING(0, start_in_screen, LANG_START_SCREEN, 1, 1953 CHOICE_SETTING(0, start_in_screen, LANG_START_SCREEN, 1,
1937 "start in screen", "previous,root,files," 1954 "start in screen", "previous,root,files,"
1938#ifdef HAVE_TAGCACHE 1955#ifdef HAVE_TAGCACHE
1939#define START_DB_COUNT 1 1956#define START_DB_COUNT 1
1940 "db," 1957 "db,"
1941#else 1958#else
1942#define START_DB_COUNT 0 1959#define START_DB_COUNT 0
1943#endif 1960#endif
1944 "wps,menu," 1961 "wps,menu,"
1945#ifdef HAVE_RECORDING 1962#ifdef HAVE_RECORDING
1946#define START_REC_COUNT 1 1963#define START_REC_COUNT 1
1947 "recording," 1964 "recording,"
1948#else 1965#else
1949#define START_REC_COUNT 0 1966#define START_REC_COUNT 0
1950#endif 1967#endif
1951#if CONFIG_TUNER 1968#if CONFIG_TUNER
1952#define START_TUNER_COUNT 1 1969#define START_TUNER_COUNT 1
1953 "radio," 1970 "radio,"
1954#else 1971#else
1955#define START_TUNER_COUNT 0 1972#define START_TUNER_COUNT 0
1956#endif 1973#endif
1957 "bookmarks" 1974 "bookmarks"
1958#ifdef HAVE_PICTUREFLOW_INTEGRATION 1975#ifdef HAVE_PICTUREFLOW_INTEGRATION
1959#define START_PF_COUNT 1 1976#define START_PF_COUNT 1
1960 ",pictureflow" 1977 ",pictureflow"
1961#else 1978#else
1962#define START_PF_COUNT 0 1979#define START_PF_COUNT 0
1963#endif 1980#endif
1964 , NULL, 1981 , NULL,
1965 (6 + START_DB_COUNT + START_REC_COUNT + START_TUNER_COUNT + START_PF_COUNT), 1982 (6 + START_DB_COUNT + START_REC_COUNT + START_TUNER_COUNT + START_PF_COUNT),
1966 ID2P(LANG_PREVIOUS_SCREEN), ID2P(LANG_MAIN_MENU), 1983 ID2P(LANG_PREVIOUS_SCREEN), ID2P(LANG_MAIN_MENU),
1967 ID2P(LANG_DIR_BROWSER), 1984 ID2P(LANG_DIR_BROWSER),
1968#ifdef HAVE_TAGCACHE 1985#ifdef HAVE_TAGCACHE
1969 ID2P(LANG_TAGCACHE), 1986 ID2P(LANG_TAGCACHE),
1970#endif 1987#endif
@@ -2025,7 +2042,7 @@ const struct settings_list settings[] = {
2025 2, "list_accel_start_delay", UNIT_SEC, 0, 10, 1, 2042 2, "list_accel_start_delay", UNIT_SEC, 0, 10, 1,
2026 formatter_unit_0_is_off, getlang_unit_0_is_off, NULL), 2043 formatter_unit_0_is_off, getlang_unit_0_is_off, NULL),
2027 INT_SETTING(0, list_accel_wait, LANG_LISTACCEL_ACCEL_SPEED, 2044 INT_SETTING(0, list_accel_wait, LANG_LISTACCEL_ACCEL_SPEED,
2028 3, "list_accel_wait", UNIT_SEC, 1, 10, 1, 2045 3, "list_accel_wait", UNIT_SEC, 1, 10, 1,
2029 scanaccel_formatter, getlang_unit_0_is_off, NULL), 2046 scanaccel_formatter, getlang_unit_0_is_off, NULL),
2030#endif /* HAVE_WHEEL_ACCELERATION */ 2047#endif /* HAVE_WHEEL_ACCELERATION */
2031#if CONFIG_CODEC == SWCODEC 2048#if CONFIG_CODEC == SWCODEC
@@ -2108,7 +2125,7 @@ const struct settings_list settings[] = {
2108 CHOICE_SETTING(0, touch_mode, LANG_TOUCHSCREEN_MODE, DEFAULT_TOUCHSCREEN_MODE, 2125 CHOICE_SETTING(0, touch_mode, LANG_TOUCHSCREEN_MODE, DEFAULT_TOUCHSCREEN_MODE,
2109 "touchscreen mode", "point,grid", NULL, 2, 2126 "touchscreen mode", "point,grid", NULL, 2,
2110 ID2P(LANG_TOUCHSCREEN_POINT), ID2P(LANG_TOUCHSCREEN_GRID)), 2127 ID2P(LANG_TOUCHSCREEN_POINT), ID2P(LANG_TOUCHSCREEN_GRID)),
2111 CUSTOM_SETTING(0, ts_calibration_data, -1, 2128 CUSTOM_SETTING(0, ts_calibration_data, -1,
2112 &default_calibration_parameters, "touchscreen calibration", 2129 &default_calibration_parameters, "touchscreen calibration",
2113 tsc_load_from_cfg, tsc_write_to_cfg, 2130 tsc_load_from_cfg, tsc_write_to_cfg,
2114 tsc_is_changed, tsc_set_default), 2131 tsc_is_changed, tsc_set_default),
@@ -2165,21 +2182,21 @@ const struct settings_list settings[] = {
2165 TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, hotkey_wps, 2182 TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, hotkey_wps,
2166 LANG_HOTKEY_WPS, HOTKEY_VIEW_PLAYLIST, "hotkey wps", 2183 LANG_HOTKEY_WPS, HOTKEY_VIEW_PLAYLIST, "hotkey wps",
2167 "off,view playlist,show track info,pitchscreen,open with,delete" 2184 "off,view playlist,show track info,pitchscreen,open with,delete"
2168#ifdef HAVE_PICTUREFLOW_INTEGRATION 2185#ifdef HAVE_PICTUREFLOW_INTEGRATION
2169 ",pictureflow" 2186 ",pictureflow"
2170#endif 2187#endif
2171 ,UNIT_INT, hotkey_formatter, hotkey_getlang, NULL, 2188 ,UNIT_INT, hotkey_formatter, hotkey_getlang, NULL,
2172#ifdef HAVE_PICTUREFLOW_INTEGRATION 2189#ifdef HAVE_PICTUREFLOW_INTEGRATION
2173 7, 2190 7,
2174#else 2191#else
2175 6, 2192 6,
2176#endif 2193#endif
2177 HOTKEY_OFF, 2194 HOTKEY_OFF,
2178 HOTKEY_VIEW_PLAYLIST, HOTKEY_SHOW_TRACK_INFO, HOTKEY_PITCHSCREEN, 2195 HOTKEY_VIEW_PLAYLIST, HOTKEY_SHOW_TRACK_INFO, HOTKEY_PITCHSCREEN,
2179 HOTKEY_OPEN_WITH, HOTKEY_DELETE 2196 HOTKEY_OPEN_WITH, HOTKEY_DELETE
2180#ifdef HAVE_PICTUREFLOW_INTEGRATION 2197#ifdef HAVE_PICTUREFLOW_INTEGRATION
2181 , HOTKEY_PICTUREFLOW 2198 , HOTKEY_PICTUREFLOW
2182#endif 2199#endif
2183 ), 2200 ),
2184 TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, hotkey_tree, 2201 TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, hotkey_tree,
2185 LANG_HOTKEY_FILE_BROWSER, HOTKEY_OFF, "hotkey tree", 2202 LANG_HOTKEY_FILE_BROWSER, HOTKEY_OFF, "hotkey tree",
diff --git a/apps/settings_list.h b/apps/settings_list.h
index 2e63220da1..967d581c06 100644
--- a/apps/settings_list.h
+++ b/apps/settings_list.h
@@ -89,7 +89,7 @@ struct choice_setting {
89#define F_CHOICE_SETTING 0x100 89#define F_CHOICE_SETTING 0x100
90#define F_CHOICETALKS 0x200 /* uses .talks in the above struct for the talks */ 90#define F_CHOICETALKS 0x200 /* uses .talks in the above struct for the talks */
91 /* and cfg_vals for the strings to display */ 91 /* and cfg_vals for the strings to display */
92 92
93struct table_setting { 93struct table_setting {
94 void (*option_callback)(int); 94 void (*option_callback)(int);
95 const char* (*formatter)(char*, size_t, int, const char*); 95 const char* (*formatter)(char*, size_t, int, const char*);
@@ -113,7 +113,7 @@ struct table_setting {
113struct custom_setting { 113struct custom_setting {
114 /* load the saved value from the .cfg 114 /* load the saved value from the .cfg
115 setting: pointer into global_settings 115 setting: pointer into global_settings
116 value: the text from the .cfg 116 value: the text from the .cfg
117 */ 117 */
118 void (*load_from_cfg)(void* setting, char*value); 118 void (*load_from_cfg)(void* setting, char*value);
119 /* store the value into a .cfg 119 /* store the value into a .cfg