diff --git a/apps/filetree.c b/apps/filetree.c index 7ab0e6d0cf..fc5e4d3934 100644 --- a/apps/filetree.c +++ b/apps/filetree.c @@ -55,6 +55,8 @@ #include "backdrop.h" +static int compare_sort_dir; /* qsort key for sorting directories */ + int ft_build_playlist(struct tree_context* c, int start_index) { int i; @@ -189,13 +191,13 @@ static int compare(const void* p1, const void* p2) if (e1->attr & ATTR_DIRECTORY && e2->attr & ATTR_DIRECTORY) { /* two directories */ - criteria = global_settings.sort_dir; + criteria = compare_sort_dir; #ifdef HAVE_MULTIVOLUME if (e1->attr & ATTR_VOLUME || e2->attr & ATTR_VOLUME) { /* a volume identifier is involved */ if (e1->attr & ATTR_VOLUME && e2->attr & ATTR_VOLUME) - criteria = 0; /* two volumes: sort alphabetically */ + criteria = SORT_ALPHA; /* two volumes: sort alphabetically */ else /* only one is a volume: volume first */ return (e2->attr & ATTR_VOLUME) - (e1->attr & ATTR_VOLUME); } @@ -207,11 +209,12 @@ static int compare(const void* p1, const void* p2) criteria = global_settings.sort_file; } else /* dir and file, dir goes first */ - return ( e2->attr & ATTR_DIRECTORY ) - ( e1->attr & ATTR_DIRECTORY ); + return (e2->attr & ATTR_DIRECTORY) - (e1->attr & ATTR_DIRECTORY); switch(criteria) { - case 3: /* sort type */ + case SORT_TYPE: + case SORT_TYPE_REVERSED: { int t1 = e1->attr & FILE_ATTR_MASK; int t2 = e2->attr & FILE_ATTR_MASK; @@ -221,27 +224,31 @@ static int compare(const void* p1, const void* p2) if (!t2) /* unknown type */ t2 = INT_MAX; /* gets a high number, to sort after known */ - if (t1 - t2) /* if different */ - return t1 - t2; + if (t1 != t2) /* if different */ + return (t1 - t2) * (criteria == SORT_TYPE_REVERSED ? -1 : 1); /* else fall through to alphabetical sorting */ } - case 0: /* sort alphabetically asc */ + + case SORT_DATE: + case SORT_DATE_REVERSED: + /* Ignore SORT_TYPE */ + if (criteria == SORT_DATE || criteria == SORT_DATE_REVERSED) + { + if (e1->time_write != e2->time_write) + return (e1->time_write - e2->time_write) + * (criteria == SORT_DATE_REVERSED ? -1 : 1); + /* else fall through to alphabetical sorting */ + } + + case SORT_ALPHA: + case SORT_ALPHA_REVERSED: if (global_settings.sort_case) - return strncmp(e1->name, e2->name, MAX_PATH); + return strncmp(e1->name, e2->name, MAX_PATH) + * (criteria == SORT_ALPHA_REVERSED ? -1 : 1); else - return strncasecmp(e1->name, e2->name, MAX_PATH); + return strncasecmp(e1->name, e2->name, MAX_PATH) + * (criteria == SORT_ALPHA_REVERSED ? -1 : 1); - case 4: /* sort alphabetically desc */ - if (global_settings.sort_case) - return strncmp(e2->name, e1->name, MAX_PATH); - else - return strncasecmp(e2->name, e1->name, MAX_PATH); - - case 1: /* sort date */ - return e1->time_write - e2->time_write; - - case 2: /* sort date, newest first */ - return e2->time_write - e1->time_write; } return 0; /* never reached */ } @@ -345,6 +352,7 @@ int ft_load(struct tree_context* c, const char* tempdir) c->dirlength = i; closedir(dir); + compare_sort_dir = c->sort_dir; qsort(c->dircache,i,sizeof(struct entry),compare); /* If thumbnail talking is enabled, make an extra run to mark files with diff --git a/apps/playlist.c b/apps/playlist.c index 018a39ae41..6768ac8708 100644 --- a/apps/playlist.c +++ b/apps/playlist.c @@ -179,7 +179,7 @@ static int get_filename(struct playlist_info* playlist, int index, int seek, static int get_next_directory(char *dir); static int get_next_dir(char *dir, bool is_forward, bool recursion); static int get_previous_directory(char *dir); -static int check_subdir_for_music(char *dir, char *subdir, bool recurse); +static int check_subdir_for_music(char *dir, const char *subdir, bool recurse); static int format_track_path(char *dest, char *src, int buf_length, int max, const char *dir); static void display_playlist_count(int count, const unsigned char *fmt, @@ -1425,20 +1425,23 @@ static int get_next_dir(char *dir, bool is_forward, bool recursion) { struct playlist_info* playlist = ¤t_playlist; int result = -1; - int sort_dir = global_settings.sort_dir; char *start_dir = NULL; bool exit = false; + int i; struct tree_context* tc = tree_get_context(); - int dirfilter = *(tc->dirfilter); + int saved_dirfilter = *(tc->dirfilter); + + /* process random folder advance */ if (global_settings.next_folder == FOLDER_ADVANCE_RANDOM) { - int fd = open(ROCKBOX_DIR "/folder_advance_list.dat",O_RDONLY); - char buffer[MAX_PATH]; - int folder_count = 0,i; - srand(current_tick); - *(tc->dirfilter) = SHOW_MUSIC; + int fd = open(ROCKBOX_DIR "/folder_advance_list.dat", O_RDONLY); if (fd >= 0) { + char buffer[MAX_PATH]; + int folder_count = 0; + srand(current_tick); + *(tc->dirfilter) = SHOW_MUSIC; + tc->sort_dir = global_settings.sort_dir; read(fd,&folder_count,sizeof(int)); if (!folder_count) exit = true; @@ -1453,17 +1456,21 @@ static int get_next_dir(char *dir, bool is_forward, bool recursion) if (folder_count) strcpy(dir,buffer); close(fd); - *(tc->dirfilter) = dirfilter; + *(tc->dirfilter) = saved_dirfilter; + tc->sort_dir = global_settings.sort_dir; reload_directory(); return 0; } } - /* not random folder advance */ - if (recursion){ + + /* not random folder advance (or random folder advance unavailable) */ + if (recursion) + { /* start with root */ dir[0] = '\0'; } - else{ + else + { /* start with current directory */ strncpy(dir, playlist->filename, playlist->dirlen-1); dir[playlist->dirlen-1] = '\0'; @@ -1472,16 +1479,27 @@ static int get_next_dir(char *dir, bool is_forward, bool recursion) /* use the tree browser dircache to load files */ *(tc->dirfilter) = SHOW_ALL; - /* sort in another direction if previous dir is requested */ - if(!is_forward){ - if ((global_settings.sort_dir == 0) || (global_settings.sort_dir == 3)) - global_settings.sort_dir = 4; - else if (global_settings.sort_dir == 1) - global_settings.sort_dir = 2; - else if (global_settings.sort_dir == 2) - global_settings.sort_dir = 1; - else if (global_settings.sort_dir == 4) - global_settings.sort_dir = 0; + /* set up sorting/direction */ + tc->sort_dir = global_settings.sort_dir; + if (!is_forward) + { + /* Sort options, indices of forward/reverse options differ in bit 0 */ + const int sortpairs[] = + { + SORT_ALPHA, SORT_ALPHA_REVERSED, + SORT_DATE, SORT_DATE_REVERSED, + SORT_TYPE, SORT_TYPE_REVERSED, + -1 + }; + + for (i = 0; sortpairs[i] >= 0; i++) + { + if (sortpairs[i] == global_settings.sort_dir) + { + tc->sort_dir = sortpairs[i^1]; + break; + } + } } while (!exit) @@ -1492,7 +1510,6 @@ static int get_next_dir(char *dir, bool is_forward, bool recursion) if (ft_load(tc, (dir[0]=='\0')?"/":dir) < 0) { - splash(HZ*2, ID2P(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR)); exit = true; result = -1; break; @@ -1542,13 +1559,13 @@ static int get_next_dir(char *dir, bool is_forward, bool recursion) } } - /* restore dirfilter & sort_dir */ - *(tc->dirfilter) = dirfilter; - global_settings.sort_dir = sort_dir; + /* restore dirfilter */ + *(tc->dirfilter) = saved_dirfilter; + tc->sort_dir = global_settings.sort_dir; /* special case if nothing found: try start searching again from root */ if (result == -1 && !recursion){ - result = get_next_dir(dir,is_forward, true); + result = get_next_dir(dir, is_forward, true); } return result; @@ -1558,7 +1575,7 @@ static int get_next_dir(char *dir, bool is_forward, bool recursion) * Checks if there are any music files in the dir or any of its * subdirectories. May be called recursively. */ -static int check_subdir_for_music(char *dir, char *subdir, bool recurse) +static int check_subdir_for_music(char *dir, const char *subdir, bool recurse) { int result = -1; int dirlen = strlen(dir); @@ -1573,7 +1590,6 @@ static int check_subdir_for_music(char *dir, char *subdir, bool recurse) if (ft_load(tc, dir) < 0) { - splash(HZ*2, ID2P(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR)); return -2; } diff --git a/apps/settings.h b/apps/settings.h index f1fd7cc2c4..9ba4396f9d 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -139,6 +139,10 @@ enum { SHOW_ALL, SHOW_SUPPORTED, SHOW_MUSIC, SHOW_PLAYLIST, SHOW_ID3DB, NUM_FILTER_MODES, SHOW_WPS, SHOW_RWPS, SHOW_FMR, SHOW_CFG, SHOW_LNG, SHOW_MOD, SHOW_FONT, SHOW_PLUGINS}; +/* file and dir sort options */ +enum { SORT_ALPHA, SORT_DATE, SORT_DATE_REVERSED, SORT_TYPE, /* available as settings */ + SORT_ALPHA_REVERSED, SORT_TYPE_REVERSED }; /* internal use only */ + /* recursive dir insert options */ enum { RECURSE_OFF, RECURSE_ON, RECURSE_ASK }; diff --git a/apps/tree.c b/apps/tree.c index 3e469247c8..768223ec4d 100644 --- a/apps/tree.c +++ b/apps/tree.c @@ -900,6 +900,7 @@ int rockbox_browse(const char *root, int dirfilter) int ret_val = 0; int *last_filter = tc.dirfilter; tc.dirfilter = &dirfilter; + tc.sort_dir = global_settings.sort_dir; reload_dir = true; if (dirfilter >= NUM_FILTER_MODES) @@ -940,6 +941,7 @@ void tree_mem_init(void) /* initialize tree context struct */ memset(&tc, 0, sizeof(tc)); tc.dirfilter = &global_settings.dirfilter; + tc.sort_dir = global_settings.sort_dir; tc.name_buffer_size = AVERAGE_FILENAME_LENGTH * max_files; tc.name_buffer = buffer_alloc(tc.name_buffer_size); diff --git a/apps/tree.h b/apps/tree.h index 5cf743c2f8..a4f36d96fa 100644 --- a/apps/tree.h +++ b/apps/tree.h @@ -67,6 +67,7 @@ struct tree_context { int name_buffer_size; int dentry_size; bool dirfull; + int sort_dir; /* directory sort order */ }; void tree_mem_init(void);