Index: apps/playlist.c
===================================================================
--- apps/playlist.c (revision 16012)
+++ apps/playlist.c (working copy)
@@ -2719,6 +2719,67 @@
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;
+ struct playlist_track_info info;
+
+ /* get current track's path */
+ currfullpath = audio_current_track()->path;
+ dirlen = strrchr(currfullpath, '/') - currfullpath + 1;
+
+ /* find the dir, and compare with current dir */
+ for (i=playlist->index; i < playlist->amount; i++)
+ {
+ if (playlist_get_track_info(playlist, i, &info) == -1)
+ return -1;
+
+ if (strncmp(currfullpath, info.filename, dirlen) != 0)
+ { /* we found the next dir */
+ playlist_start(i, 0);
+ return 0;
+ }
+ }
+
+ /* fell off the bottom of playlist. do nothing */
+ return 0;
+}
+
+/* move to first track of current directory */
+int playlist_prev_album(void)
+{
+ struct playlist_info* playlist = ¤t_playlist;
+ const char* currfullpath;
+ int dirlen = 0;
+ int i;
+ struct playlist_track_info info;
+
+ /* get current track's path */
+ currfullpath = audio_current_track()->path;
+ dirlen = strrchr(currfullpath, '/') - currfullpath + 1;
+
+ /* find the dir, and compare with current dir */
+ for (i=playlist->index-1; i >= 0; i--)
+ {
+ if (playlist_get_track_info(playlist, i, &info) == -1)
+ return -1;
+
+ if (strncmp(currfullpath, 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 16012)
+++ 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(void);
/* 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 16012)
+++ apps/lang/english.lang (working copy)
@@ -2108,6 +2108,34 @@
+ id: LANG_DIR_SKIP
+ desc: in playback settings menu.
+ user:
+
+ *: "Directory Skip by Keypress"
+
+
+ *: "Directory Skip by Keypress"
+
+
+ *: "Directory Skip by Keypress"
+
+
+
+ id: LANG_WITHIN_PLAYLIST
+ desc: in directory skip in playback settings menu.
+ user:
+
+ *: "Within Playlist"
+
+
+ *: "Within Playlist"
+
+
+ *: "Within Playlist"
+
+
+
id: LANG_AUDIOSCROBBLER
desc: "Last.fm Log" in the playback menu
user:
Index: apps/gui/gwps.c
===================================================================
--- apps/gui/gwps.c (revision 16012)
+++ apps/gui/gwps.c (working copy)
@@ -332,30 +332,28 @@
}
}
break;
- /* fast forward
- OR next dir if this is straight after ACTION_WPS_SKIPNEXT */
+ /* fast forward */
case ACTION_WPS_SEEKFWD:
if (global_settings.party_mode)
break;
- if (current_tick -last_right < HZ)
- {
- if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type)
- {
- audio_next();
- }
- else
- {
- audio_next_dir();
- }
- }
- else ffwd_rew(ACTION_WPS_SEEKFWD);
- last_right = 0;
+ ffwd_rew(ACTION_WPS_SEEKFWD);
+ last_right = current_tick;
break;
- /* fast rewind
- OR prev dir if this is straight after ACTION_WPS_SKIPPREV */
+ /* fast rewind */
case ACTION_WPS_SEEKBACK:
if (global_settings.party_mode)
break;
+ ffwd_rew(ACTION_WPS_SEEKBACK);
+ last_left = current_tick;
+ break;
+
+ /* prev / restart
+ OR prev dir if this is straight after ACTION_WPS_SEEKBACK */
+ case ACTION_WPS_SKIPPREV:
+ if (global_settings.party_mode)
+ break;
+
+ update_track = true;
if (current_tick -last_left < HZ)
{
if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type)
@@ -370,102 +368,120 @@
}
else
{
- audio_prev_dir();
+ /* if Directory Skip is set to 'Within Playlist',
+ move to first song of the current-playing-track's album */
+ if (global_settings.directory_skip == 0)
+ playlist_prev_album();
+ else if (global_settings.directory_skip == 1)
+ audio_prev_dir();
}
}
- else ffwd_rew(ACTION_WPS_SEEKBACK);
- last_left = 0;
- break;
-
- /* prev / restart */
- case ACTION_WPS_SKIPPREV:
- if (global_settings.party_mode)
- break;
- last_left = current_tick;
- update_track = true;
-
+ else
+ {
#ifdef AB_REPEAT_ENABLE
- /* if we're in A/B repeat mode and the current position
- is past the A marker, jump back to the A marker... */
- if ( ab_repeat_mode_enabled() )
- {
- if ( ab_after_A_marker(wps_state.id3->elapsed) )
+ /* if we're in A/B repeat mode and the current position
+ is past the A marker, jump back to the A marker... */
+ if ( ab_repeat_mode_enabled() )
{
- ab_jump_to_A_marker();
- break;
+ if ( ab_after_A_marker(wps_state.id3->elapsed) )
+ {
+ ab_jump_to_A_marker();
+ break;
#if (AB_REPEAT_ENABLE == 2)
- } else {
- ab_reset_markers();
+ } else {
+ ab_reset_markers();
#endif
+ }
}
- }
- /* ...otherwise, do it normally */
+ /* ...otherwise, do it normally */
#endif
- if (!wps_state.id3 || (wps_state.id3->elapsed < 3*1000)) {
- audio_prev();
- }
- else {
-
- if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type)
- {
- curr_cuesheet_skip(-1, wps_state.id3->elapsed);
- break;
+ if (!wps_state.id3 || (wps_state.id3->elapsed < 3*1000)) {
+ audio_prev();
}
+ else {
- if (!wps_state.paused)
+ if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type)
+ {
+ curr_cuesheet_skip(-1, wps_state.id3->elapsed);
+ break;
+ }
+
+ if (!wps_state.paused)
#if (CONFIG_CODEC == SWCODEC)
- audio_pre_ff_rewind();
+ audio_pre_ff_rewind();
#else
- audio_pause();
+ audio_pause();
#endif
- audio_ff_rewind(0);
+ audio_ff_rewind(0);
#if (CONFIG_CODEC != SWCODEC)
- if (!wps_state.paused)
- audio_resume();
+ if (!wps_state.paused)
+ audio_resume();
#endif
+ }
}
+ last_left = 0;
break;
- /* next */
+ /* next
+ OR next dir if this is straight after ACTION_WPS_SEEKFWD */
case ACTION_WPS_SKIPNEXT:
if (global_settings.party_mode)
break;
- last_right = current_tick;
+
update_track = true;
-
-#ifdef AB_REPEAT_ENABLE
- /* if we're in A/B repeat mode and the current position is
- before the A marker, jump to the A marker... */
- if ( ab_repeat_mode_enabled() )
+ if (current_tick -last_right < HZ)
{
- if ( ab_before_A_marker(wps_state.id3->elapsed) )
+ if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type)
{
- ab_jump_to_A_marker();
- break;
+ audio_next();
+ }
+ else
+ {
+ /* if Directory Skip is set to 'Within Playlist',
+ skip to next album in the current playlist. */
+ if (global_settings.directory_skip == 0)
+ playlist_next_album();
+ else if (global_settings.directory_skip == 1)
+ audio_next_dir();
+ }
+ }
+ else
+ {
+#ifdef AB_REPEAT_ENABLE
+ /* if we're in A/B repeat mode and the current position is
+ before the A marker, jump to the A marker... */
+ if ( ab_repeat_mode_enabled() )
+ {
+ if ( ab_before_A_marker(wps_state.id3->elapsed) )
+ {
+ ab_jump_to_A_marker();
+ break;
#if (AB_REPEAT_ENABLE == 2)
- } else {
- ab_reset_markers();
+ } else {
+ ab_reset_markers();
#endif
+ }
}
- }
- /* ...otherwise, do it normally */
+ /* ...otherwise, do it normally */
#endif
- /* take care of if we're playing a cuesheet */
- if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type)
- {
- if (curr_cuesheet_skip(1, wps_state.id3->elapsed))
+ /* take care of if we're playing a cuesheet */
+ if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type)
{
- /* if the result was false, then we really want
- to skip to the next track */
- break;
+ if (curr_cuesheet_skip(1, wps_state.id3->elapsed))
+ {
+ /* if the result was false, then we really want
+ to skip to the next track */
+ break;
+ }
}
+
+ audio_next();
}
-
- audio_next();
+ last_right = 0;
break;
/* next / prev directories */
/* and set A-B markers if in a-b mode */
Index: apps/settings.h
===================================================================
--- apps/settings.h (revision 16012)
+++ apps/settings.h (working copy)
@@ -545,6 +545,7 @@
#endif /* HAVE_REMOTE_LCD */
int next_folder; /* move to next folder */
+ int directory_skip;
bool runtimedb; /* runtime database active? */
#if CONFIG_CODEC == SWCODEC
Index: apps/menus/playback_menu.c
===================================================================
--- apps/menus/playback_menu.c (revision 16012)
+++ apps/menus/playback_menu.c (working copy)
@@ -130,6 +130,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);
int audioscrobbler_callback(int action,const struct menu_item_ex *this_item)
{
(void)this_item;
@@ -186,7 +187,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 16012)
+++ apps/settings_list.c (working copy)
@@ -852,6 +852,9 @@
CHOICE_SETTING(0, next_folder, LANG_NEXT_FOLDER, FOLDER_ADVANCE_OFF,
"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,normal,never",NULL ,3,
+ ID2P(LANG_WITHIN_PLAYLIST), ID2P(LANG_NORMAL), ID2P(LANG_NEVER)),
OFFON_SETTING(0,runtimedb,LANG_RUNTIMEDB_ACTIVE,false,"gather runtime data",NULL),
#if CONFIG_CODEC == SWCODEC