Index: apps/action.h
===================================================================
--- apps/action.h (revision 15044)
+++ apps/action.h (working copy)
@@ -111,6 +111,9 @@
ACTION_WPS_ID3SCREEN,/* optional */
ACTION_WPS_CONTEXT,
ACTION_WPS_QUICKSCREEN,/* optional */
+#ifdef ACCEPT_DOUBLE_CLICK
+ ACTION_WPS_SCRUBSEEK,/* optional */
+#endif
ACTION_WPS_MENU, /*this should be the same as ACTION_STD_MENU */
ACTION_WPS_REC,
#if 0
Index: apps/lang/english.lang
===================================================================
--- apps/lang/english.lang (revision 15044)
+++ apps/lang/english.lang (working copy)
@@ -11342,6 +11356,20 @@
+ id: LANG_SCRUB_MODE_TIMEOUT
+ desc: Menu item to select timeout for Scrub mode (scrollwheel devices)
+ user:
+
+ *: "Scrub Mode Timeout"
+
+
+ *: "Scrub Mode Timeout"
+
+
+ *: ""
+
+
+
id: LANG_THEME_MENU
desc: in the settings menu
user:
Index: apps/gui/gwps-common.c
===================================================================
--- apps/gui/gwps-common.c (revision 15044)
+++ apps/gui/gwps-common.c (working copy)
@@ -142,6 +142,228 @@
return false;
}
+bool scrub_ffwd_rew(int button)
+{
+ static const uint16_t ff_rew_steps[] = {
+ 1000, 2000, 3000, 4000,
+ 5000, 6000, 8000, 10000,
+ 15000, 20000, 25000, 30000,
+ 45000, 60000
+ };
+
+ unsigned int step = 0; /* current ff/rewind step */
+ unsigned int max_step = 0; /* maximum ff/rewind step */
+ int ff_rewind_count = 0; /* current ff/rewind count (in ticks) */
+ int direction = -1; /* forward=1 or backward=-1 */
+ long accel_tick = 0; /* next time at which to bump the step size */
+ bool exit = false;
+ bool usb = false;
+ bool update=false; /* update audio */
+ bool timeout=false; /* time out scrub mode after preset seconds */
+ long cur_pos=0; /* used to get round unsigned/signed comparison */
+ long old_pos=0; /* used to calculate timeout */
+ int wait_time=0; /* wait time before updating audio - makes for smooth scrubbing */
+ int i = 0;
+
+ if (button == ACTION_WPS_BROWSE) /* exit - should never happen */
+ {
+ status_set_ffmode(0);
+ return usb;
+ }
+
+if ( (audio_status() & AUDIO_STATUS_PLAY) &&
+ wps_state.id3 && wps_state.id3->length )
+ {
+ if ((!wps_state.paused) && (global_settings.scrub_mode_timeout==0)) /* pause audio if timeout is 0 */
+#if (CONFIG_CODEC == SWCODEC)
+ audio_pre_ff_rewind();
+#else
+ audio_pause();
+#endif
+#if CONFIG_KEYPAD == PLAYER_PAD
+if (global_settings.scrub_mode_timeout==0)
+ FOR_NB_SCREENS(i)
+ gui_wps[i].display->stop_scroll();
+#endif
+
+ wps_state.ff_rewind = true; /* set scrub mode for progress bar */
+
+ step = ff_rew_steps[global_settings.ff_rewind_min_step];
+
+ accel_tick = current_tick +
+ global_settings.ff_rewind_accel*HZ;
+ }
+ old_pos=wps_state.id3->elapsed; /* get old position for time out (should be redundant actually) */
+
+ while (!exit) /* main loop - read button, take action*/
+ {
+ switch ( button )
+ {
+ case ACTION_WPS_VOLUP:
+ direction = 1;
+ case ACTION_WPS_VOLDOWN:
+ wps_state.ff_rewind=true; /* re-enable scrub mode for progress bar if disabled elsewhere */
+ if (wps_state.ff_rewind) /* enabled above so kind of redundant */
+ {
+ if (direction == 1)
+ {
+ /* fast forwarding, calc max step relative to end */
+ max_step = (wps_state.id3->length -
+ (wps_state.id3->elapsed +
+ ff_rewind_count)) *
+ FF_REWIND_MAX_PERCENT / 100;
+ status_set_ffmode(STATUS_FASTFORWARD);
+ }
+ else
+ {
+ /* rewinding, calc max step relative to start */
+ max_step = (wps_state.id3->elapsed + ff_rewind_count) *
+ FF_REWIND_MAX_PERCENT / 100;
+ status_set_ffmode(STATUS_FASTBACKWARD);
+ }
+
+ max_step = MAX(max_step, MIN_FF_REWIND_STEP);
+
+ if (step > max_step)
+ step = max_step;
+
+ ff_rewind_count += step * direction;
+
+ if (global_settings.ff_rewind_accel != 0 &&
+ current_tick >= accel_tick)
+ {
+ step *= 2;
+ accel_tick = current_tick +
+ global_settings.ff_rewind_accel*HZ;
+ }
+ }
+ if (direction > 0) {
+ if ((wps_state.id3->elapsed + ff_rewind_count) >
+ wps_state.id3->length)
+ ff_rewind_count = wps_state.id3->length -
+ wps_state.id3->elapsed;
+ }
+ else {
+ if ((int)(wps_state.id3->elapsed + ff_rewind_count) < 0)
+ ff_rewind_count = -wps_state.id3->elapsed;
+
+ }
+
+ FOR_NB_SCREENS(i)
+ gui_wps_refresh(&gui_wps[i],
+ (wps_state.wps_time_countup == false)?
+ ff_rewind_count:-ff_rewind_count,
+ WPS_REFRESH_PLAYER_PROGRESS |
+ WPS_REFRESH_DYNAMIC);
+ direction = -1;
+ update = true;
+ wait_time=0;
+ if ((wps_state.id3->length - wps_state.id3->elapsed) < 2000) /* few seconds to go before we run out of current song */
+#if (CONFIG_CODEC == SWCODEC)
+ audio_pre_ff_rewind(); /* so pause playback while we are still scrubbing*/
+#else
+ audio_pause();
+#endif
+ break;
+
+ case ACTION_WPS_BROWSE: /* Exit on Select */
+ case ACTION_WPS_PLAY: /* Exit on Play */
+ if ((global_settings.scrub_mode_timeout==0) || (update))
+ /* update playback if we are scrubbing while paused, or update required */
+ {
+ wps_state.id3->elapsed = wps_state.id3->elapsed+ff_rewind_count;
+ audio_ff_rewind(wps_state.id3->elapsed);
+ }
+ ff_rewind_count = 0;
+ wps_state.ff_rewind = false;
+ status_set_ffmode(0);
+#if (CONFIG_CODEC != SWCODEC)
+ if (!wps_state.paused)
+ audio_resume();
+#endif
+#ifdef HAVE_LCD_CHARCELLS
+ //gui_wps_display();
+#endif
+ exit = true;
+ break;
+
+ case ACTION_NONE: /* No Button Pressed */
+ if (global_settings.scrub_mode_timeout==0)
+ {
+ status_set_ffmode(STATUS_PAUSE); /* display paused when not ff or rew */
+ FOR_NB_SCREENS(i)
+ gui_wps_refresh(&gui_wps[i], (wps_state.wps_time_countup == false)?
+ ff_rewind_count:-ff_rewind_count,
+ WPS_REFRESH_PLAYER_PROGRESS | WPS_REFRESH_DYNAMIC);
+ }
+ else
+ {
+ if ((update) && (wait_time > 3)) /* wait time of 3 works OK, should this be a variable? */
+ {
+ wait_time =0;
+#if (CONFIG_CODEC == SWCODEC)
+ audio_pre_ff_rewind(); /* pause audio so that we can update cleanly */
+#else
+ audio_pause();
+#endif
+ if (wps_state.id3->elapsed+ff_rewind_count < wps_state.id3->length)
+ wps_state.id3->elapsed = wps_state.id3->elapsed+ff_rewind_count; /* update position if not beyond end of file */
+ else
+ {
+ wps_state.id3->elapsed = wps_state.id3->length;
+ timeout=true; /* scrubbed to end of song */
+ }
+ audio_ff_rewind(wps_state.id3->elapsed); /* update file with new position */
+ old_pos=wps_state.id3->elapsed; /*update old_pos for time out calculation */
+ ff_rewind_count = 0; /*reset scrub position now that we have updated */
+ wps_state.ff_rewind=false; /* out of scub mode for progress bar */
+#if (CONFIG_CODEC != SWCODEC)
+ if (!wps_state.paused)
+ audio_resume();
+#endif
+ update=false; /* only update once */
+ }
+ else
+ {
+ if (!update) /* we havent scrubbed yet, so just show progress as normal */
+ {
+ wps_state.ff_rewind=false; /* not scrubbing, normal mode for progress bar */
+ FOR_NB_SCREENS(i)
+ gui_wps_refresh(&gui_wps[i],
+ 0,
+ WPS_REFRESH_PLAYER_PROGRESS |
+ WPS_REFRESH_DYNAMIC);
+ }
+ else /* we have scrubbed so increment wait_time */
+ {
+ wait_time++;
+ DEBUGF("wait time is %d\n", wait_time);
+ old_pos=wps_state.id3->elapsed; /*update old_pos for time out calculation */
+ }
+ if ((wps_state.id3->length - wps_state.id3->elapsed) < 2250) /* .25 seconds to go before we run out of current song */
+ timeout=true;
+ cur_pos=wps_state.id3->elapsed;
+ if ((short)(cur_pos - old_pos)/1000 > global_settings.scrub_mode_timeout) /* time out calculation */
+ timeout=true;
+ }
+ }
+ break;
+
+ default: /* loop unless USB is connected */
+ if(default_event_handler(button) == SYS_USB_CONNECTED) {
+ status_set_ffmode(0);
+ usb = true;
+ exit = true;
+ }
+ }
+ if ((!exit) && (timeout==false)) /* if we are not exiting and timeout has not elapsed, read button */
+ button = get_action(CONTEXT_WPS|ALLOW_SOFTLOCK,HZ/5);
+ else
+ button = ACTION_WPS_PLAY; /* otherwise we are exiting, so go back to play as normal */
+ }
+ return usb;
+}
+
bool ffwd_rew(int button)
{
static const uint16_t ff_rew_steps[] = {
@@ -1073,6 +1295,8 @@
mode = 4;
if (status_get_ffmode() == STATUS_FASTBACKWARD)
mode = 5;
+ if (status_get_ffmode() == STATUS_PAUSE)
+ mode = 3;
if (intval) {
*intval = mode;
Index: apps/gui/gwps-common.h
===================================================================
--- apps/gui/gwps-common.h (revision 15044)
+++ apps/gui/gwps-common.h (working copy)
@@ -27,6 +27,7 @@
bool gui_wps_display(void);
bool update_onvol_change(struct gui_wps * gwps);
bool update(struct gui_wps *gwps);
+bool scrub_ffwd_rew(int button);
bool ffwd_rew(int button);
void display_keylock_text(bool locked);
Index: apps/gui/gwps.c
===================================================================
--- apps/gui/gwps.c (revision 15044)
+++ apps/gui/gwps.c (working copy)
@@ -502,7 +502,15 @@
return GO_TO_ROOT;
break;
+#ifdef ACCEPT_DOUBLE_CLICK
+ case ACTION_WPS_SCRUBSEEK:
+ if (global_settings.party_mode) /* don't do anything in party mode */
+ break;
+ scrub_ffwd_rew(ACTION_NONE); /* go into scrub mode, but don't seek unless vol up or down */
+ break;
+#endif
+
#ifdef HAVE_QUICKSCREEN
case ACTION_WPS_QUICKSCREEN:
#if LCD_DEPTH > 1
Index: apps/settings.h
===================================================================
--- apps/settings.h (revision 15044)
+++ apps/settings.h (working copy)
@@ -748,6 +748,15 @@
int list_accel_start_delay; /* ms before we start increaseing step size */
int list_accel_wait; /* ms between increases */
#endif
+
+ int scrub_mode_timeout; /* time to wait before exiting scrub mode
+ 0 = never
+ number = time to wait in seconds */
+
#ifdef ACCEPT_DOUBLE_CLICK
int btn_double_click_delay;
#endif
#ifdef HAVE_USBSTACK
int usb_stack_mode; /* device or host */
unsigned char usb_stack_device_driver[32]; /* usb device driver to load */
Index: apps/menus/playback_menu.c
===================================================================
--- apps/menus/playback_menu.c (revision 15044)
+++ apps/menus/playback_menu.c (working copy)
@@ -60,8 +60,9 @@
MENUITEM_SETTING(ff_rewind_accel, &global_settings.ff_rewind_accel, NULL);
MENUITEM_SETTING(ff_rewind_min_step, &global_settings.ff_rewind_min_step, NULL);
+MENUITEM_SETTING(scrub_mode_timeout, &global_settings.scrub_mode_timeout, NULL);
MAKE_MENU(ff_rewind_settings_menu, ID2P(LANG_WIND_MENU), 0, Icon_NOICON,
- &ff_rewind_min_step, &ff_rewind_accel);
+ &ff_rewind_min_step, &ff_rewind_accel, &scrub_mode_timeout);
#ifndef HAVE_FLASH_STORAGE
#if CONFIG_CODEC == SWCODEC
int buffermargin_callback(int action,const struct menu_item_ex *this_item)
Index: apps/settings_list.c
===================================================================
--- apps/settings_list.c (revision 15044)
+++ apps/settings_list.c (working copy)
@@ -258,6 +258,24 @@
snprintf(buffer, buffer_size, "2x/%ds", val);
}
+static const int scrub_mode_timeout_vals[] = {0,4,5,6,7,8,9,10,15,20,30};
+static long scrub_mode_timeout_getlang(int value)
+{
+ if (value == 0)
+ return LANG_OFF;
+ return TALK_ID(scrub_mode_timeout_vals[value], UNIT_SEC);
+}
+static void scrub_mode_timeout_formatter(char *buffer, size_t buffer_size,
+ int val, const char *unit)
+{
+ (void)unit;
+ if (val == 0)
+ strcpy(buffer, str(LANG_OFF));
+ else
+ snprintf(buffer, buffer_size, "%ds", scrub_mode_timeout_vals[val]);
+}
+
+
static const unsigned char poweroff_idle_timer_times[] = {0,1,2,3,4,5,6,7,8,9,10,15,30,45,60};
static long poweroff_idle_timer_getlang(int value)
{
@@ -650,6 +668,10 @@
ff_rewind_min_step_getlang, NULL),
INT_SETTING(0, ff_rewind_accel, LANG_FFRW_ACCEL, 3, "scan accel",
UNIT_SEC, 16, 0, -1, scanaccel_formatter, scanaccel_getlang, NULL),
+ INT_SETTING(0, scrub_mode_timeout, LANG_SCRUB_MODE_TIMEOUT,
+ 0, "scrub mode timeout", UNIT_SEC, 0, 10, 1,
+ scrub_mode_timeout_formatter, scrub_mode_timeout_getlang, NULL),
+
#if (CONFIG_CODEC == SWCODEC) && !defined(HAVE_FLASH_STORAGE)
STRINGCHOICE_SETTING(0, buffer_margin, LANG_MP3BUFFER_MARGIN, 0,"antiskip",
"5s,15s,30s,1min,2min,3min,5min,10min",NULL, 8,
Index: apps/keymaps/keymap-ipod.c
===================================================================
--- apps/keymaps/keymap-ipod.c (revision 15044)
+++ apps/keymaps/keymap-ipod.c (working copy)
@@ -75,6 +75,9 @@
};
static const struct button_mapping button_context_wps[] = {
+#ifdef ACCEPT_DOUBLE_CLICK
+ { ACTION_WPS_SCRUBSEEK, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT|BUTTON_DBL },
+#endif
{ ACTION_WPS_PLAY, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY },
{ ACTION_WPS_STOP, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_PLAY },
{ ACTION_WPS_SKIPPREV, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT },
Index: firmware/export/config-ipodvideo.h
===================================================================
--- firmware/export/config-ipodvideo.h (revision 15044)
+++ firmware/export/config-ipodvideo.h (working copy)
@@ -159,4 +159,7 @@
#define ICODE_ATTR_TREMOR_NOT_MDCT
+/* define this to turn on double click captures */
+#define ACCEPT_DOUBLE_CLICK
+
#endif
Index: firmware/export/config-ipod3g.h
===================================================================
--- firmware/export/config-ipod3g.h (revision 15044)
+++ firmware/export/config-ipod3g.h (working copy)
@@ -133,4 +133,7 @@
#define ICODE_ATTR_TREMOR_NOT_MDCT
+/* define this to turn on double click captures */
+#define ACCEPT_DOUBLE_CLICK
+
#endif /* SIMULATOR */
Index: firmware/export/config-ipodcolor.h
===================================================================
--- firmware/export/config-ipodcolor.h (revision 15044)
+++ firmware/export/config-ipodcolor.h (working copy)
@@ -141,4 +141,7 @@
#define ICODE_ATTR_TREMOR_NOT_MDCT
+/* define this to turn on double click captures */
+#define ACCEPT_DOUBLE_CLICK
+
#endif
Index: firmware/export/config-ipodmini.h
===================================================================
--- firmware/export/config-ipodmini.h (revision 15044)
+++ firmware/export/config-ipodmini.h (working copy)
@@ -146,4 +146,7 @@
#define ICODE_ATTR_TREMOR_NOT_MDCT
+/* define this to turn on double click captures */
+#define ACCEPT_DOUBLE_CLICK
+
#endif
Index: firmware/export/config-ipod1g2g.h
===================================================================
--- firmware/export/config-ipod1g2g.h (revision 15044)
+++ firmware/export/config-ipod1g2g.h (working copy)
@@ -130,4 +130,7 @@
#define ICODE_ATTR_TREMOR_NOT_MDCT
+/* define this to turn on double click captures */
+#define ACCEPT_DOUBLE_CLICK
+
#endif /* SIMULATOR */
Index: firmware/export/config-ipodmini2g.h
===================================================================
--- firmware/export/config-ipodmini2g.h (revision 15044)
+++ firmware/export/config-ipodmini2g.h (working copy)
@@ -149,4 +149,7 @@
#define ICODE_ATTR_TREMOR_NOT_MDCT
+/* define this to turn on double click captures */
+#define ACCEPT_DOUBLE_CLICK
+
#endif
Index: firmware/export/config-ipodnano.h
===================================================================
--- firmware/export/config-ipodnano.h (revision 15044)
+++ firmware/export/config-ipodnano.h (working copy)
@@ -147,4 +147,7 @@
#define ICODE_ATTR_TREMOR_NOT_MDCT
+/* define this to turn on double click captures */
+#define ACCEPT_DOUBLE_CLICK
+
#endif
Index: firmware/export/config-ipod4g.h
===================================================================
--- firmware/export/config-ipod4g.h (revision 15044)
+++ firmware/export/config-ipod4g.h (working copy)
@@ -152,4 +152,7 @@
#define ICODE_ATTR_TREMOR_NOT_MDCT
+/* define this to turn on double click captures */
+#define ACCEPT_DOUBLE_CLICK
+
#endif