Index: rockbox-devel/apps/action.h =================================================================== --- rockbox-devel.orig/apps/action.h +++ rockbox-devel/apps/action.h @@ -99,6 +99,7 @@ enum { ACTION_WPS_BROWSE, ACTION_WPS_PLAY, ACTION_WPS_SEEKBACK, + ACTION_WPS_TRACKLOCK, ACTION_WPS_SEEKFWD, ACTION_WPS_STOPSEEK, ACTION_WPS_SKIPNEXT, Index: rockbox-devel/apps/gui/gwps-common.c =================================================================== --- rockbox-devel.orig/apps/gui/gwps-common.c +++ rockbox-devel/apps/gui/gwps-common.c @@ -53,6 +53,7 @@ #endif #include "dsp.h" #include "action.h" +#include "pcmbuf.h" #ifdef HAVE_LCD_CHARCELLS static bool draw_player_progress(struct gui_wps *gwps); @@ -2331,6 +2332,35 @@ bool update_onvol_change(struct gui_wps return false; } +void play_hop(int direction) +{ + if(!wps_state.id3 || !wps_state.id3->length) + return; +#define STEP (global_settings.tracklock_step *1000) + if(direction == 1 + && wps_state.id3->length - wps_state.id3->elapsed < STEP+1000) { + pcmbuf_beep(1000, 150, 1500*global_settings.beep); + return; + } + if((direction == -1 && wps_state.id3->elapsed < STEP)) + wps_state.id3->elapsed = 0; + else + wps_state.id3->elapsed += STEP *direction; + if((audio_status() & AUDIO_STATUS_PLAY) && !wps_state.paused) { +#if (CONFIG_CODEC == SWCODEC) + audio_pre_ff_rewind(); +#else + audio_pause(); +#endif + } + audio_ff_rewind(wps_state.id3->elapsed); +#if (CONFIG_CODEC != SWCODEC) + if (!wps_state.paused) + audio_resume(); +#endif +#undef STEP +} + bool ffwd_rew(int button) { static const int ff_rew_steps[] = { Index: rockbox-devel/apps/gui/gwps-common.h =================================================================== --- rockbox-devel.orig/apps/gui/gwps-common.h +++ rockbox-devel/apps/gui/gwps-common.h @@ -32,6 +32,7 @@ bool gui_wps_display(void); void setvol(void); bool update_onvol_change(struct gui_wps * gwps); bool update(struct gui_wps *gwps); +void play_hop(int direction); bool ffwd_rew(int button); bool wps_data_preload_tags(struct wps_data *data, char *buf, const char *bmpdir, size_t bmpdirlen); Index: rockbox-devel/apps/gui/gwps.c =================================================================== --- rockbox-devel.orig/apps/gui/gwps.c +++ rockbox-devel/apps/gui/gwps.c @@ -81,6 +81,7 @@ static void gui_wps_set_margin(struct gu gwps->display->setmargins(0, offset); } #endif +#include "talk.h" long gui_wps_show(void) { @@ -91,6 +92,7 @@ long gui_wps_show(void) bool update_track = false; int i; long last_left = 0, last_right = 0; + bool tracklock = global_settings.tracklock; action_signalscreenchange(); @@ -300,7 +302,7 @@ long gui_wps_show(void) case ACTION_WPS_SEEKFWD: if (global_settings.party_mode) break; - if (current_tick -last_right < HZ) + if (!tracklock && current_tick -last_right < HZ) audio_next_dir(); else ffwd_rew(ACTION_WPS_SEEKFWD); last_right = 0; @@ -310,12 +312,20 @@ long gui_wps_show(void) case ACTION_WPS_SEEKBACK: if (global_settings.party_mode) break; - if (current_tick -last_left < HZ) + if (!tracklock && current_tick -last_left < HZ) audio_prev_dir(); else ffwd_rew(ACTION_WPS_SEEKBACK); last_left = 0; break; + case ACTION_WPS_TRACKLOCK: + tracklock = !tracklock; + if (global_settings.talk_menu) { + talk_id(LANG_TRACKLOCK, false); + talk_id(tracklock ? LANG_ON : LANG_OFF, false); + } + break; + /* prev / restart */ case ACTION_WPS_SKIPPREV: if (global_settings.party_mode) @@ -341,6 +351,11 @@ long gui_wps_show(void) /* ...otherwise, do it normally */ #endif + if(tracklock) { + if(global_settings.tracklock_step) + play_hop(-1); + break; + } if (!wps_state.id3 || (wps_state.id3->elapsed < 3*1000)) { audio_prev(); } @@ -385,6 +400,11 @@ long gui_wps_show(void) } /* ...otherwise, do it normally */ #endif + if(tracklock) { + if(global_settings.tracklock_step) + play_hop(1); + break; + } audio_next(); break; /* next / prev directories */ Index: rockbox-devel/apps/keymaps/keymap-x5.c =================================================================== --- rockbox-devel.orig/apps/keymaps/keymap-x5.c +++ rockbox-devel/apps/keymaps/keymap-x5.c @@ -293,6 +293,8 @@ const struct button_mapping button_conte { ACTION_WPS_SKIPNEXT, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT }, { ACTION_WPS_SEEKFWD, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_WPS_STOPSEEK, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT|BUTTON_REPEAT }, + { ACTION_WPS_TRACKLOCK, BUTTON_POWER|BUTTON_REL, BUTTON_POWER }, + { ACTION_WPS_TRACKLOCK, BUTTON_POWER|BUTTON_REL, BUTTON_POWER|BUTTON_REPEAT }, { ACTION_WPS_VOLDOWN, BUTTON_DOWN, BUTTON_NONE }, { ACTION_WPS_VOLDOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, Index: rockbox-devel/apps/lang/english.lang =================================================================== --- rockbox-devel.orig/apps/lang/english.lang +++ rockbox-devel/apps/lang/english.lang @@ -10266,3 +10266,45 @@ *: "" + + id: LANG_TRACKLOCK + desc: playback settings menu + user: + + *: "Track lock" + + + *: "Track lock" + + + *: "Track lock" + + + + id: LANG_TRACKLOCK_ENABLE + desc: playback settings menu + user: + + *: "Enable Track lock" + + + *: "Enable Track lock" + + + *: "Enable Track lock" + + + + id: LANG_TRACKLOCK_STEP + desc: playback settings menu + user: + + *: "Track lock step" + + + *: "Track lock step" + + + *: "Track lock step" + + Index: rockbox-devel/apps/settings.c =================================================================== --- rockbox-devel.orig/apps/settings.c +++ rockbox-devel/apps/settings.c @@ -682,6 +682,8 @@ static const struct bit_entry hd_bits[] #ifdef CONFIG_TUNER {2, S_O(fm_region), 0, "fm_region", "eu,us,jp,kr" }, #endif + {1, S_O(tracklock), false, "track lock", off_on }, + {8, S_O(tracklock_step), 5, "track step", NULL }, {1, S_O(audioscrobbler), false, "Last.fm Logging", off_on}, Index: rockbox-devel/apps/settings.h =================================================================== --- rockbox-devel.orig/apps/settings.h +++ rockbox-devel/apps/settings.h @@ -273,6 +273,8 @@ struct user_settings int timeformat; /* time format: 0=24 hour clock, 1=12 hour clock */ bool playlist_shuffle; bool play_selected; /* Plays selected file even in shuffle mode */ + bool tracklock; /* Default tracklock setting on entering wps */ + unsigned tracklock_step; /* How many seconds to skip in tracklock. */ int ff_rewind_min_step; /* FF/Rewind minimum step size */ int ff_rewind_accel; /* FF/Rewind acceleration (in seconds per doubling) */ int disk_spindown; /* time until disk spindown, in seconds (0=off) */ Index: rockbox-devel/apps/settings_menu.c =================================================================== --- rockbox-devel.orig/apps/settings_menu.c +++ rockbox-devel/apps/settings_menu.c @@ -746,6 +746,33 @@ static bool play_selected(void) return set_bool( str(LANG_PLAY_SELECTED), &global_settings.play_selected ); } +static bool tracklock(void) +{ + return set_bool( str(LANG_TRACKLOCK_ENABLE), &global_settings.tracklock ); +} +static bool tracklock_step(void) +{ + return set_int(str(LANG_TRACKLOCK_STEP), "s", UNIT_SEC, + &global_settings.tracklock_step, NULL, + 1, 0, 250, NULL); +} +static bool tracklock_settings_menu(void) +{ + int m; + bool result; + + static const struct menu_item items[] = { + { ID2P(LANG_TRACKLOCK_ENABLE), tracklock }, + { ID2P(LANG_TRACKLOCK_STEP), tracklock_step }, + }; + + m=menu_init( items, sizeof(items) / sizeof(*items), NULL, + NULL, NULL, NULL); + result = menu_run(m); + menu_exit(m); + return result; +} + static bool dir_filter(void) { static const struct opt_items names[] = { @@ -1764,6 +1791,7 @@ static bool playback_settings_menu(void) { ID2P(LANG_PLAY_SELECTED), play_selected }, { ID2P(LANG_RESUME), resume }, { ID2P(LANG_WIND_MENU), ff_rewind_settings_menu }, + { ID2P(LANG_TRACKLOCK), tracklock_settings_menu }, { ID2P(LANG_MP3BUFFER_MARGIN), buffer_margin }, { ID2P(LANG_FADE_ON_STOP), set_fade_on_stop }, { ID2P(LANG_PARTY_MODE), set_party_mode },