Index: apps/lang/francais.lang =================================================================== --- apps/lang/francais.lang (revision 23543) +++ apps/lang/francais.lang (working copy) @@ -11850,6 +11850,20 @@ + id: LANG_SKIP_BINARY + desc: binary search to the desired point in the track + user: core + + *: "Binary Skip" + + + *: "Binaire de recherche" + + + *: "Binaire de recherche" + + + id: VOICE_CHAR_SLASH desc: spoken only, for spelling user: core Index: apps/lang/english.lang =================================================================== --- apps/lang/english.lang (revision 23543) +++ apps/lang/english.lang (working copy) @@ -11996,6 +11996,20 @@ + id: LANG_SKIP_BINARY + desc: binary search to the desired point in the track + user: core + + *: "Binary Skip" + + + *: "Binary Skip" + + + *: "Binary Skip" + + + id: VOICE_CHAR_SLASH desc: spoken only, for spelling user: core Index: apps/gui/wps.c =================================================================== --- apps/gui/wps.c (revision 23543) +++ apps/gui/wps.c (working copy) @@ -84,6 +84,14 @@ static struct wps_data wps_datas[NB_SCREENS] = {{ .wps_loaded = 0 }}; static struct wps_sync_data wps_sync_data = { .do_full_update = false }; +/* Binary Search Mode vars */ +#define BINARY_SEARCH_TIMEOUT 5 +#define BINARY_SEARCH_SKIP_LENGTH -2 + +static unsigned long search_lower_bound = 0; +static unsigned long search_upper_bound = 0; +static long search_timeout = 0; + /* initial setup of wps_data */ static void wps_state_init(void); static void track_changed_callback(void *param); @@ -931,9 +939,37 @@ else /* ...otherwise, do it normally */ #endif - play_hop(-1); + /* + We have NN seconds to continue our binary search + from the last time it was attempted. + If the NN seconds have expired, we consider that + a new search has begun. + This affects the initial upper and lower bounds for the search + as does the direction of the initial skip. + */ + if (global_settings.skip_length == BINARY_SEARCH_SKIP_LENGTH) + { + if (TIME_AFTER(current_tick, search_timeout)) + { + /* + We're skipping backwards from the current elapsed time + so our initial window is from the current position + to the start of the track + */ + search_lower_bound = 0; + } + + /* Adjust based on the search bounds and direction */ + search_upper_bound = wps_state.id3->elapsed; + + audio_ff_rewind((search_lower_bound + search_upper_bound) / 2); + + search_timeout = current_tick + BINARY_SEARCH_TIMEOUT * HZ; + } else { + play_hop(-1); + } + break; - /* next OR if skip length set, hop by predetermined amount. */ case ACTION_WPS_SKIPNEXT: @@ -958,8 +994,30 @@ else /* ...otherwise, do it normally */ #endif - play_hop(1); + if (global_settings.skip_length == BINARY_SEARCH_SKIP_LENGTH) + { + if (TIME_AFTER(current_tick, search_timeout)) + { + /* + We're skipping forwards from the current elapsed time + so our initial window is from the current position + to the end of the track + */ + search_upper_bound = wps_state.id3->length; + } + + /* Adjust based on the search bounds and direction */ + search_lower_bound = wps_state.id3->elapsed; + + audio_ff_rewind((search_lower_bound + search_upper_bound) / 2); + + search_timeout = current_tick + BINARY_SEARCH_TIMEOUT * HZ; + } else { + play_hop(1); + } + break; + /* next / prev directories */ /* and set A-B markers if in a-b mode */ case ACTION_WPS_ABSETB_NEXTDIR: Index: apps/settings_list.c =================================================================== --- apps/settings_list.c (revision 23543) +++ apps/settings_list.c (working copy) @@ -293,7 +293,9 @@ int val, const char *unit) { (void)unit; - if (val == -1) + if (val == -2) + return str(LANG_SKIP_BINARY); + else if (val == -1) return str(LANG_SKIP_OUTRO); else if (val == 0) return str(LANG_SKIP_TRACK); @@ -1453,10 +1455,10 @@ NULL), TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, skip_length, LANG_SKIP_LENGTH, 0, "skip length", - "outro,track,1s,2s,3s,5s,7s,10s,15s,20s,30s,45s,1min,90s,2min,3min,5min,10min,15min", + "outro,track,binary,1s,2s,3s,5s,7s,10s,15s,20s,30s,45s,1min,90s,2min,3min,5min,10min,15min", UNIT_SEC, formatter_unit_0_is_skip_track, getlang_unit_0_is_skip_track, NULL, - 19, -1,0,1,2,3,5,7,10,15,20,30,45,60,90,120,180,300,600,900), + 20, -1,0,-2,1,2,3,5,7,10,15,20,30,45,60,90,120,180,300,600,900), CHOICE_SETTING(0, start_in_screen, LANG_START_SCREEN, 1, "start in screen", "previous,root,files," #ifdef HAVE_TAGCACHE Index: manual/configure_rockbox/playback_options.tex =================================================================== --- manual/configure_rockbox/playback_options.tex (revision 23543) +++ manual/configure_rockbox/playback_options.tex (working copy) @@ -273,6 +273,11 @@ The \setting{Skip to Outro} option changes the behaviour so that the buttons skip to just before the end of the track, so that the last few seconds are played before the next track. + The \setting{Binary Skip} option changes the behaviour so that the buttons + allow a binary search within the track allowing a specific point to be + selected. If the \ActionWpsSkipPrev{} and \ActionWpsSkipNext{} buttons + are not pressed for a period of 5 seconds, the current binary search is reset + and a new search can be started. \section{Prevent Track Skipping}\index{Prevent Track Skipping} If this option is enabled, the ability to manually skip tracks is disabled