Index: apps/playlist.c =================================================================== --- apps/playlist.c (revision 17486) +++ apps/playlist.c (working copy) @@ -2706,6 +2706,95 @@ return playlist_amount_ex(NULL); } +/* move to first track of next directory within a playlist */ +int playlist_next_album(void) +{ + struct playlist_info* playlist = ¤t_playlist; + const char* currfullpath; + int dirlen = 0; + int i, cur_idx; + struct playlist_track_info cur_info; + struct playlist_track_info next_info; + + /* do nothing if repeat mode is 'One' or 'A-B' */ + if ( (global_settings.repeat_mode == REPEAT_ONE) +#ifdef AB_REPEAT_ENABLE + || (global_settings.repeat_mode == REPEAT_AB) +#endif + ) + return 0; + + /* get current track's path. + since we've already pressed NEXT button, retrieve previous track's. */ + cur_idx=get_next_index(playlist,-1,-1); + playlist_get_track_info(playlist, cur_idx, &cur_info); + currfullpath = cur_info.filename; + dirlen = strrchr(currfullpath, '/') - currfullpath + 1; + + /* find the dir, and compare with current dir */ + for (i=cur_idx; i < playlist->amount; i++) + { + if (playlist_get_track_info(playlist, i, &next_info) == -1) + return -1; + + if (strncmp(currfullpath, next_info.filename, dirlen) != 0) + { /* we found the next dir */ + playlist_start(i, 0); + return 0; + } + } + + /* fell off the bottom of playlist. do nothing if repeat mode is not 'All' */ + if (global_settings.repeat_mode == REPEAT_ALL) + playlist_start(0, 0); + return 0; +} + +/* move to first track of current directory */ +int playlist_prev_album(bool moveto_prev) +{ + struct playlist_info* playlist = ¤t_playlist; + const char* currfullpath; + int dirlen = 0; + int i, cur_idx; + struct playlist_track_info cur_info; + struct playlist_track_info prev_info; + + /* do nothing if repeat mode is 'One' or 'A-B' */ + if ( (global_settings.repeat_mode == REPEAT_ONE) +#ifdef AB_REPEAT_ENABLE + || (global_settings.repeat_mode == REPEAT_AB) +#endif + ) + return 0; + + /* get current track's path */ + if (moveto_prev) + cur_idx=get_next_index(playlist,-1,-1); + else + cur_idx = playlist->index; + playlist_get_track_info(playlist, cur_idx, &cur_info); + currfullpath = cur_info.filename; + dirlen = strrchr(currfullpath, '/') - currfullpath + 1; + + /* find the dir, and compare with current dir */ + for (i=cur_idx-1; i >= 0; i--) + { + if (playlist_get_track_info(playlist, i, &prev_info) == -1) + return -1; + + if (strncmp(currfullpath, prev_info.filename, dirlen) != 0) + { /* we found the prev dir */ + playlist_start(i+1, 0); + return 0; + } + } + + /* fell off the top of the playlist, plays first track */ + playlist_start(0, 0); + return 0; +} + /* * Create a new playlist If playlist is not NULL then we're loading a * playlist off disk for viewing/editing. The index_buffer is used to store Index: apps/playlist.h =================================================================== --- apps/playlist.h (revision 17486) +++ apps/playlist.h (working copy) @@ -127,6 +127,8 @@ int playlist_update_resume_info(const struct mp3entry* id3); int playlist_get_display_index(void); int playlist_amount(void); +int playlist_next_album(void); +int playlist_prev_album(bool moveto_prev); /* Exported functions for all playlists. Pass NULL for playlist_info structure to work with current playlist. */ Index: apps/lang/english.lang =================================================================== --- apps/lang/english.lang (revision 17486) +++ apps/lang/english.lang (working copy) @@ -2111,6 +2111,48 @@ + id: LANG_DIR_SKIP + desc: in playback settings menu. + user: + + *: "Directory Skip" + + + *: "Directory Skip" + + + *: "Directory Skip" + + + + id: LANG_WITHIN_PLAYLIST + desc: in directory skip in playback settings menu. + user: + + *: "Within Playlist" + + + *: "Within Playlist" + + + *: "Within Playlist" + + + + id: LANG_NEXT_DIR + desc: in directory skip in playback settings menu. + user: + + *: "Next Directory" + + + *: "Next Directory" + + + *: "Next Directory" + + + id: LANG_AUDIOSCROBBLER desc: "Last.fm Log" in the playback menu user: Index: apps/gui/gwps-common.c =================================================================== --- apps/gui/gwps-common.c (revision 17486) +++ apps/gui/gwps-common.c (working copy) @@ -201,6 +201,14 @@ case ACTION_WPS_SEEKFWD: direction = 1; case ACTION_WPS_SEEKBACK: + /* if this is straight after ACTION_WPS_SKIPPREV or ACTION_WPS_SKIPNEXT, + we don't need to ffwd or rewind the new track*/ + if (wps_state.trackskip) + { + FOR_NB_SCREENS(i) + gui_wps_refresh(&gui_wps[i], 0, WPS_REFRESH_ALL); + break; + } if (wps_state.ff_rewind) { if (direction == 1) @@ -286,7 +294,10 @@ case ACTION_WPS_STOPSEEK: wps_state.id3->elapsed = wps_state.id3->elapsed+ff_rewind_count; - audio_ff_rewind(wps_state.id3->elapsed); + if (wps_state.trackskip) + wps_state.trackskip = false; + else + audio_ff_rewind(wps_state.id3->elapsed); ff_rewind_count = 0; wps_state.ff_rewind = false; status_set_ffmode(0); Index: apps/gui/gwps.c =================================================================== --- apps/gui/gwps.c (revision 17486) +++ apps/gui/gwps.c (working copy) @@ -394,11 +394,18 @@ } else { - audio_next_dir(); + /* if Directory Skip is set to 'Within Playlist', + skip to next album in the current playlist. */ + wps_state.trackskip=true; + if (global_settings.directory_skip == 0) + playlist_next_album(); + else if (global_settings.directory_skip == 1) + audio_next_dir(); } } else if(global_settings.study_mode && current_tick -last_left < HZ) { + wps_state.trackskip=true; next_track(); update_track = true; } @@ -427,12 +434,19 @@ } else { - audio_prev_dir(); + /* if Directory Skip is set to 'Within Playlist', + move to first song of the current-playing-track's album */ + wps_state.trackskip=true; + if (global_settings.directory_skip == 0) + playlist_prev_album(wps_state.id3->elapsed < 3*1000); + else if (global_settings.directory_skip == 1) + audio_prev_dir(); } } else if(global_settings.study_mode && current_tick -last_right < HZ) { + wps_state.trackskip=true; prev_track(3+global_settings.study_hop_step); update_track = true; } @@ -745,6 +759,7 @@ { wps_state.ff_rewind = false; wps_state.paused = false; + wps_state.trackskip = false; wps_state.id3 = NULL; wps_state.nid3 = NULL; wps_state.current_track_path[0] = '\0'; Index: apps/gui/gwps.h =================================================================== --- apps/gui/gwps.h (revision 17486) +++ apps/gui/gwps.h (working copy) @@ -440,6 +440,7 @@ { bool ff_rewind; bool paused; + bool trackskip; int ff_rewind_count; bool wps_time_countup; struct mp3entry* id3; Index: apps/settings.h =================================================================== --- apps/settings.h (revision 17486) +++ apps/settings.h (working copy) @@ -555,6 +555,7 @@ #endif /* HAVE_REMOTE_LCD */ int next_folder; /* move to next folder */ + int directory_skip; /* 0=skip within playlist 1=skip to next folder 2=off */ bool runtimedb; /* runtime database active? */ #if CONFIG_CODEC == SWCODEC Index: apps/menus/playback_menu.c =================================================================== --- apps/menus/playback_menu.c (revision 17486) +++ apps/menus/playback_menu.c (working copy) @@ -134,6 +134,7 @@ MENUITEM_SETTING(spdif_enable, &global_settings.spdif_enable, NULL); #endif MENUITEM_SETTING(next_folder, &global_settings.next_folder, NULL); +MENUITEM_SETTING(directory_skip, &global_settings.directory_skip, NULL); static int audioscrobbler_callback(int action,const struct menu_item_ex *this_item) { (void)this_item; @@ -195,7 +196,7 @@ #ifdef HAVE_SPDIF_POWER &spdif_enable, #endif - &next_folder, &audioscrobbler, &cuesheet + &next_folder, &directory_skip, &audioscrobbler, &cuesheet #ifdef HAVE_HEADPHONE_DETECTION ,&unplug_menu #endif Index: apps/settings_list.c =================================================================== --- apps/settings_list.c (revision 17486) +++ apps/settings_list.c (working copy) @@ -946,6 +946,10 @@ "folder navigation", "off,on,random",NULL ,3, ID2P(LANG_SET_BOOL_NO), ID2P(LANG_SET_BOOL_YES), ID2P(LANG_RANDOM)), + CHOICE_SETTING(0, directory_skip, LANG_DIR_SKIP, 0, + "dirskip mode", "within pl,next dir,off",NULL ,3, + ID2P(LANG_WITHIN_PLAYLIST), ID2P(LANG_NEXT_DIR), + ID2P(LANG_OFF)), OFFON_SETTING(0, runtimedb, LANG_RUNTIMEDB_ACTIVE, false, "gather runtime data", NULL),