Index: apps/lang/english.lang
===================================================================
--- apps/lang/english.lang (revision 27817)
+++ apps/lang/english.lang (working copy)
@@ -12619,3 +12619,31 @@
*: "Update on Stop"
+
+ id: LANG_SKIP_BINARY
+ desc: binary search to the desired point in the track
+ user: core
+
+ *: "Binary Skip"
+
+
+ *: "Binary Skip"
+
+
+ *: "Binary Skip"
+
+
+
+ id: LANG_TALK_TRACK_POSITION
+ desc: announce track position on binary skip
+ user: core
+
+ *: "Announce Track Position"
+
+
+ *: "Announce Track Position"
+
+
+ *: "Announce Track Position"
+
+
Index: apps/gui/wps.c
===================================================================
--- apps/gui/wps.c (revision 27817)
+++ apps/gui/wps.c (working copy)
@@ -66,6 +66,7 @@
#include "playlist_viewer.h"
#include "wps.h"
#include "statusbar-skinned.h"
+#include "talk.h"
#define RESTORE_WPS_INSTANTLY 0l
#define RESTORE_WPS_NEXT_SECOND ((long)(HZ+current_tick))
@@ -80,6 +81,17 @@
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
+#define TRACK_SKIP_TIMEOUT 0.5
+
+static unsigned long search_lower_bound = 0;
+static unsigned long search_upper_bound = 0;
+static long search_timeout = 0;
+static long track_skip_timeout=0;
+
/* initial setup of wps_data */
static void wps_state_init(void);
static void track_changed_callback(void *param);
@@ -299,6 +311,8 @@
case ACTION_WPS_SEEKFWD:
direction = 1;
case ACTION_WPS_SEEKBACK:
+
+
if (wps_state.ff_rewind)
{
if (direction == 1)
@@ -489,6 +503,8 @@
static void prev_track(unsigned long skip_thresh)
{
+ search_timeout = 0;
+
if (wps_state.id3->elapsed < skip_thresh)
{
audio_prev();
@@ -520,6 +536,8 @@
static void next_track(void)
{
+ search_timeout = 0;
+
/* take care of if we're playing a cuesheet */
if (wps_state.id3->cuesheet)
{
@@ -702,7 +720,9 @@
bool vol_changed = false;
int i;
long last_left = 0, last_right = 0;
-
+ int announce_seconds = 0;
+
+
#ifdef HAVE_LCD_CHARCELLS
status_set_audio(true);
status_set_param(false);
@@ -842,6 +862,7 @@
case ACTION_WPS_SEEKFWD:
if (global_settings.party_mode)
break;
+ search_timeout = 0;
if (current_tick -last_right < HZ)
{
if (wps_state.id3->cuesheet)
@@ -862,6 +883,7 @@
case ACTION_WPS_SEEKBACK:
if (global_settings.party_mode)
break;
+ search_timeout = 0;
if (current_tick -last_left < HZ)
{
if (wps_state.id3->cuesheet)
@@ -903,7 +925,55 @@
else
/* ...otherwise, do it normally */
#endif
+
+ /*
+ 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, track_skip_timeout))
+ {
+ 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;
+
+ track_skip_timeout = current_tick + TRACK_SKIP_TIMEOUT * HZ;
+
+ if (global_settings.talk_track_position == true)
+ {
+ announce_seconds = ((search_lower_bound + search_upper_bound) / 2) / 1000;
+
+ talk_value_decimal(announce_seconds, UNIT_TIME, 0, false);
+ }
+ } else {
+ if (global_settings.talk_track_position == true)
+ {
+ talk_shutup();
+ }
+ play_hop(-1);
+ }
+ } else {
play_hop(-1);
+ }
+
break;
/* next
@@ -926,7 +996,47 @@
else
/* ...otherwise, do it normally */
#endif
+ if (global_settings.skip_length == BINARY_SEARCH_SKIP_LENGTH)
+ {
+ if (TIME_AFTER(current_tick, track_skip_timeout))
+ {
+ 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;
+
+ track_skip_timeout = current_tick + TRACK_SKIP_TIMEOUT * HZ;
+
+ if (global_settings.talk_track_position == true)
+ {
+ announce_seconds = ((search_lower_bound + search_upper_bound) / 2) / 1000;
+
+ talk_value_decimal(announce_seconds, UNIT_TIME, 0, false);
+ }
+ } else {
+
+ if (global_settings.talk_track_position == true)
+ {
+ talk_shutup();
+ }
+ play_hop(1);
+ }
+ } else {
play_hop(1);
+ }
+
break;
/* next / prev directories */
/* and set A-B markers if in a-b mode */
Index: apps/settings.h
===================================================================
--- apps/settings.h (revision 27817)
+++ apps/settings.h (working copy)
@@ -610,6 +610,7 @@
bool talk_file_clip; /* use file .talk clips */
bool talk_filetype; /* say file type */
bool talk_battery_level;
+ bool talk_track_position; /* announce track position */
/* file browser sorting */
bool sort_case; /* dir sort order: 0=case insensitive, 1=sensitive */
Index: apps/settings_list.c
===================================================================
--- apps/settings_list.c (revision 27817)
+++ apps/settings_list.c (working copy)
@@ -308,7 +308,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);
@@ -322,7 +324,9 @@
static int32_t getlang_unit_0_is_skip_track(int value, int unit)
{
(void)unit;
- if (value == -1)
+ if (value == -2)
+ return LANG_SKIP_BINARY;
+ else if (value == -1)
return LANG_SKIP_OUTRO;
else if (value == 0)
return LANG_SKIP_TRACK;
@@ -1078,7 +1082,10 @@
"talk filetype", NULL),
OFFON_SETTING(F_TEMPVAR, talk_battery_level, LANG_TALK_BATTERY_LEVEL, false,
"Announce Battery Level", NULL),
+ OFFON_SETTING(F_TEMPVAR, talk_track_position, LANG_TALK_TRACK_POSITION, false,
+ "Announce Track Position", NULL),
+
#ifdef HAVE_RECORDING
/* recording */
STRINGCHOICE_SETTING(F_RECSETTING, rec_timesplit, LANG_SPLIT_TIME, 0,
@@ -1562,10 +1569,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