summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/lang/english.lang14
-rw-r--r--apps/menus/playback_menu.c4
-rw-r--r--apps/playback.c11
-rw-r--r--apps/playlist.c167
-rw-r--r--apps/plugins/random_folder_advance_config.c11
-rw-r--r--apps/settings.h2
-rw-r--r--apps/settings_list.c3
7 files changed, 144 insertions, 68 deletions
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 627fda8b12..d428bee232 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -12993,3 +12993,17 @@
12993 *: "Restart Sleep Timer On Keypress" 12993 *: "Restart Sleep Timer On Keypress"
12994 </voice> 12994 </voice>
12995</phrase> 12995</phrase>
12996<phrase>
12997 id: LANG_CONSTRAIN_NEXT_FOLDER
12998 desc: in settings_menu. Whether LANG_NEXT_FOLDER should be constrained to directories within LANG_SET_AS_START_DIR
12999 user: core
13000 <source>
13001 *: "Constrain Auto-Change"
13002 </source>
13003 <dest>
13004 *: "Constrain Auto-Change"
13005 </dest>
13006 <voice>
13007 *: "Constrain Auto-Change"
13008 </voice>
13009</phrase>
diff --git a/apps/menus/playback_menu.c b/apps/menus/playback_menu.c
index d5b20d09f5..17b7e57d32 100644
--- a/apps/menus/playback_menu.c
+++ b/apps/menus/playback_menu.c
@@ -135,6 +135,8 @@ MENUITEM_SETTING(beep, &global_settings.beep ,NULL);
135MENUITEM_SETTING(spdif_enable, &global_settings.spdif_enable, NULL); 135MENUITEM_SETTING(spdif_enable, &global_settings.spdif_enable, NULL);
136#endif 136#endif
137MENUITEM_SETTING(next_folder, &global_settings.next_folder, NULL); 137MENUITEM_SETTING(next_folder, &global_settings.next_folder, NULL);
138MENUITEM_SETTING(constrain_next_folder,
139 &global_settings.constrain_next_folder, NULL);
138static int audioscrobbler_callback(int action,const struct menu_item_ex *this_item) 140static int audioscrobbler_callback(int action,const struct menu_item_ex *this_item)
139{ 141{
140 (void)this_item; 142 (void)this_item;
@@ -205,7 +207,7 @@ MAKE_MENU(playback_settings,ID2P(LANG_PLAYBACK),0,
205#ifdef HAVE_SPDIF_POWER 207#ifdef HAVE_SPDIF_POWER
206 &spdif_enable, 208 &spdif_enable,
207#endif 209#endif
208 &next_folder, &audioscrobbler, &cuesheet 210 &next_folder, &constrain_next_folder, &audioscrobbler, &cuesheet
209#ifdef HAVE_HEADPHONE_DETECTION 211#ifdef HAVE_HEADPHONE_DETECTION
210 ,&unplug_menu 212 ,&unplug_menu
211#endif 213#endif
diff --git a/apps/playback.c b/apps/playback.c
index 8fe43eb884..28f664357c 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -2644,8 +2644,17 @@ static void audio_on_skip(void)
2644 skip_pending = TRACK_SKIP_NONE; 2644 skip_pending = TRACK_SKIP_NONE;
2645 2645
2646 /* Update the playlist current track now */ 2646 /* Update the playlist current track now */
2647 while (playlist_next(playlist_delta) < 0) 2647 int pl_retval;
2648 while ((pl_retval = playlist_next(playlist_delta)) < 0)
2648 { 2649 {
2650 if (pl_retval < -1)
2651 {
2652 /* Some variety of fatal error while updating playlist */
2653 filling = STATE_ENDED;
2654 audio_stop_playback();
2655 return;
2656 }
2657
2649 /* Manual skip out of range (because the playlist wasn't updated 2658 /* Manual skip out of range (because the playlist wasn't updated
2650 yet by us and so the check in audio_skip returned 'ok') - bring 2659 yet by us and so the check in audio_skip returned 'ok') - bring
2651 back into range */ 2660 back into range */
diff --git a/apps/playlist.c b/apps/playlist.c
index bf55671bf1..5b5f489cde 100644
--- a/apps/playlist.c
+++ b/apps/playlist.c
@@ -175,7 +175,7 @@ static int compare(const void* p1, const void* p2);
175static int get_filename(struct playlist_info* playlist, int index, int seek, 175static int get_filename(struct playlist_info* playlist, int index, int seek,
176 bool control_file, char *buf, int buf_length); 176 bool control_file, char *buf, int buf_length);
177static int get_next_directory(char *dir); 177static int get_next_directory(char *dir);
178static int get_next_dir(char *dir, bool is_forward, bool recursion); 178static int get_next_dir(char *dir, bool is_forward);
179static int get_previous_directory(char *dir); 179static int get_previous_directory(char *dir);
180static int check_subdir_for_music(char *dir, const char *subdir, bool recurse); 180static int check_subdir_for_music(char *dir, const char *subdir, bool recurse);
181static int format_track_path(char *dest, char *src, int buf_length, int max, 181static int format_track_path(char *dest, char *src, int buf_length, int max,
@@ -608,32 +608,33 @@ static int create_and_play_dir(int direction, bool play_last)
608 else 608 else
609 res = get_previous_directory(dir); 609 res = get_previous_directory(dir);
610 610
611 if (!res) 611 if (res < 0)
612 /* return the error encountered */
613 return res;
614
615 if (playlist_create(dir, NULL) != -1)
612 { 616 {
613 if (playlist_create(dir, NULL) != -1) 617 ft_build_playlist(tree_get_context(), 0);
614 {
615 ft_build_playlist(tree_get_context(), 0);
616 618
617 if (global_settings.playlist_shuffle) 619 if (global_settings.playlist_shuffle)
618 playlist_shuffle(current_tick, -1); 620 playlist_shuffle(current_tick, -1);
619 621
620 if (play_last && direction <= 0) 622 if (play_last && direction <= 0)
621 index = current_playlist.amount - 1; 623 index = current_playlist.amount - 1;
622 else 624 else
623 index = 0; 625 index = 0;
624 626
625#if (CONFIG_CODEC == SWCODEC) 627#if (CONFIG_CODEC == SWCODEC)
626 current_playlist.started = true; 628 current_playlist.started = true;
627#else 629#else
628 playlist_start(index, 0); 630 playlist_start(index, 0);
629#endif 631#endif
630 }
631
632 /* we've overwritten the dircache when getting the next/previous dir,
633 so the tree browser context will need to be reloaded */
634 reload_directory();
635 } 632 }
636 633
634 /* we've overwritten the dircache when getting the next/previous dir,
635 so the tree browser context will need to be reloaded */
636 reload_directory();
637
637 return index; 638 return index;
638} 639}
639 640
@@ -1435,18 +1436,18 @@ static int get_filename(struct playlist_info* playlist, int index, int seek,
1435} 1436}
1436 1437
1437static int get_next_directory(char *dir){ 1438static int get_next_directory(char *dir){
1438 return get_next_dir(dir,true,false); 1439 return get_next_dir(dir, true);
1439} 1440}
1440 1441
1441static int get_previous_directory(char *dir){ 1442static int get_previous_directory(char *dir){
1442 return get_next_dir(dir,false,false); 1443 return get_next_dir(dir, false);
1443} 1444}
1444 1445
1445/* 1446/*
1446 * search through all the directories (starting with the current) to find 1447 * search through all the directories (starting with the current) to find
1447 * one that has tracks to play 1448 * one that has tracks to play
1448 */ 1449 */
1449static int get_next_dir(char *dir, bool is_forward, bool recursion) 1450static int get_next_dir(char *dir, bool is_forward)
1450{ 1451{
1451 struct playlist_info* playlist = &current_playlist; 1452 struct playlist_info* playlist = &current_playlist;
1452 int result = -1; 1453 int result = -1;
@@ -1454,6 +1455,27 @@ static int get_next_dir(char *dir, bool is_forward, bool recursion)
1454 bool exit = false; 1455 bool exit = false;
1455 struct tree_context* tc = tree_get_context(); 1456 struct tree_context* tc = tree_get_context();
1456 int saved_dirfilter = *(tc->dirfilter); 1457 int saved_dirfilter = *(tc->dirfilter);
1458 unsigned int base_len;
1459
1460 if (global_settings.constrain_next_folder)
1461 {
1462 /* constrain results to directories below user's start directory */
1463 strcpy(dir, global_settings.start_directory);
1464 base_len = strlen(dir);
1465
1466 /* strip any trailing slash from base directory */
1467 if (base_len > 0 && dir[base_len - 1] == '/')
1468 {
1469 base_len--;
1470 dir[base_len] = '\0';
1471 }
1472 }
1473 else
1474 {
1475 /* start from root directory */
1476 dir[0] = '\0';
1477 base_len = 0;
1478 }
1457 1479
1458 /* process random folder advance */ 1480 /* process random folder advance */
1459 if (global_settings.next_folder == FOLDER_ADVANCE_RANDOM) 1481 if (global_settings.next_folder == FOLDER_ADVANCE_RANDOM)
@@ -1461,43 +1483,46 @@ static int get_next_dir(char *dir, bool is_forward, bool recursion)
1461 int fd = open(ROCKBOX_DIR "/folder_advance_list.dat", O_RDONLY); 1483 int fd = open(ROCKBOX_DIR "/folder_advance_list.dat", O_RDONLY);
1462 if (fd >= 0) 1484 if (fd >= 0)
1463 { 1485 {
1464 char buffer[MAX_PATH];
1465 int folder_count = 0; 1486 int folder_count = 0;
1466 srand(current_tick);
1467 *(tc->dirfilter) = SHOW_MUSIC;
1468 tc->sort_dir = global_settings.sort_dir;
1469 read(fd,&folder_count,sizeof(int)); 1487 read(fd,&folder_count,sizeof(int));
1470 if (!folder_count) 1488 if (folder_count)
1471 exit = true;
1472 while (!exit)
1473 { 1489 {
1474 int i = rand()%folder_count; 1490 char buffer[MAX_PATH];
1475 lseek(fd,sizeof(int) + (MAX_PATH*i),SEEK_SET); 1491 /* give up looking for a directory after we've had four
1476 read(fd,buffer,MAX_PATH); 1492 times as many tries as there are directories. */
1477 if (check_subdir_for_music(buffer, "", false) ==0) 1493 unsigned long allowed_tries = folder_count * 4;
1478 exit = true; 1494 int i;
1495 srand(current_tick);
1496 *(tc->dirfilter) = SHOW_MUSIC;
1497 tc->sort_dir = global_settings.sort_dir;
1498 while (!exit && allowed_tries--)
1499 {
1500 i = rand() % folder_count;
1501 lseek(fd, sizeof(int) + (MAX_PATH * i), SEEK_SET);
1502 read(fd, buffer, MAX_PATH);
1503 /* is the current dir within our base dir and has music? */
1504 if ((base_len == 0 || !strncmp(buffer, dir, base_len))
1505 && check_subdir_for_music(buffer, "", false) == 0)
1506 exit = true;
1507 }
1508 close(fd);
1509 *(tc->dirfilter) = saved_dirfilter;
1510 tc->sort_dir = global_settings.sort_dir;
1511 reload_directory();
1512 if (exit)
1513 {
1514 strcpy(dir,buffer);
1515 return 0;
1516 }
1479 } 1517 }
1480 if (folder_count) 1518 else
1481 strcpy(dir,buffer); 1519 close(fd);
1482 close(fd);
1483 *(tc->dirfilter) = saved_dirfilter;
1484 tc->sort_dir = global_settings.sort_dir;
1485 reload_directory();
1486 return 0;
1487 } 1520 }
1488 } 1521 }
1489 1522
1490 /* not random folder advance (or random folder advance unavailable) */ 1523 /* if the current file is within our base dir, use its dir instead */
1491 if (recursion) 1524 if (base_len == 0 || !strncmp(playlist->filename, dir, base_len))
1492 {
1493 /* start with root */
1494 dir[0] = '\0';
1495 }
1496 else
1497 {
1498 /* start with current directory */
1499 strlcpy(dir, playlist->filename, playlist->dirlen); 1525 strlcpy(dir, playlist->filename, playlist->dirlen);
1500 }
1501 1526
1502 /* use the tree browser dircache to load files */ 1527 /* use the tree browser dircache to load files */
1503 *(tc->dirfilter) = SHOW_ALL; 1528 *(tc->dirfilter) = SHOW_ALL;
@@ -1546,7 +1571,7 @@ static int get_next_dir(char *dir, bool is_forward, bool recursion)
1546 exit = true; 1571 exit = true;
1547 break; 1572 break;
1548 } 1573 }
1549 1574
1550 if (files[i].attr & ATTR_DIRECTORY) 1575 if (files[i].attr & ATTR_DIRECTORY)
1551 { 1576 {
1552 if (!start_dir) 1577 if (!start_dir)
@@ -1566,16 +1591,30 @@ static int get_next_dir(char *dir, bool is_forward, bool recursion)
1566 1591
1567 if (!exit) 1592 if (!exit)
1568 { 1593 {
1569 /* move down to parent directory. current directory name is 1594 /* we've already descended to the base dir with nothing found,
1570 stored as the starting point for the search in parent */ 1595 check whether that contains music */
1571 start_dir = strrchr(dir, '/'); 1596 if (strlen(dir) <= base_len)
1572 if (start_dir)
1573 { 1597 {
1574 *start_dir = '\0'; 1598 result = check_subdir_for_music(dir, "", true);
1575 start_dir++; 1599 if (result == -1)
1600 /* there's no music files in the base directory,
1601 treat as a fatal error */
1602 result = -2;
1603 break;
1576 } 1604 }
1577 else 1605 else
1578 break; 1606 {
1607 /* move down to parent directory. current directory name is
1608 stored as the starting point for the search in parent */
1609 start_dir = strrchr(dir, '/');
1610 if (start_dir)
1611 {
1612 *start_dir = '\0';
1613 start_dir++;
1614 }
1615 else
1616 break;
1617 }
1579 } 1618 }
1580 } 1619 }
1581 1620
@@ -1583,11 +1622,6 @@ static int get_next_dir(char *dir, bool is_forward, bool recursion)
1583 *(tc->dirfilter) = saved_dirfilter; 1622 *(tc->dirfilter) = saved_dirfilter;
1584 tc->sort_dir = global_settings.sort_dir; 1623 tc->sort_dir = global_settings.sort_dir;
1585 1624
1586 /* special case if nothing found: try start searching again from root */
1587 if (result == -1 && !recursion){
1588 result = get_next_dir(dir, is_forward, true);
1589 }
1590
1591 return result; 1625 return result;
1592} 1626}
1593 1627
@@ -1606,7 +1640,12 @@ static int check_subdir_for_music(char *dir, const char *subdir, bool recurse)
1606 bool has_subdir = false; 1640 bool has_subdir = false;
1607 struct tree_context* tc = tree_get_context(); 1641 struct tree_context* tc = tree_get_context();
1608 1642
1609 snprintf(dir+dirlen, MAX_PATH-dirlen, "/%s", subdir); 1643 snprintf(
1644 dir + dirlen, MAX_PATH - dirlen,
1645 /* only add a trailing slash if we need one */
1646 dirlen && dir[dirlen - 1] == '/' ? "%s" : "/%s",
1647 subdir
1648 );
1610 1649
1611 if (ft_load(tc, dir) < 0) 1650 if (ft_load(tc, dir) < 0)
1612 { 1651 {
diff --git a/apps/plugins/random_folder_advance_config.c b/apps/plugins/random_folder_advance_config.c
index f459aa0776..7f6018df4e 100644
--- a/apps/plugins/random_folder_advance_config.c
+++ b/apps/plugins/random_folder_advance_config.c
@@ -65,8 +65,15 @@ static void traversedir(char* location, char* name)
65 bool check = false; 65 bool check = false;
66 int i; 66 int i;
67 67
68 rb->snprintf(fullpath, sizeof(fullpath), "%s/%s", location, name); 68 /* behave differently if we're at root to avoid
69 dir = rb->opendir(fullpath); 69 duplication of the initial slash later on */
70 if (location[0] == '\0' && name[0] == '\0') {
71 rb->strcpy(fullpath, "");
72 dir = rb->opendir("/");
73 } else {
74 rb->snprintf(fullpath, sizeof(fullpath), "%s/%s", location, name);
75 dir = rb->opendir(fullpath);
76 }
70 if (dir) { 77 if (dir) {
71 entry = rb->readdir(dir); 78 entry = rb->readdir(dir);
72 while (entry) { 79 while (entry) {
diff --git a/apps/settings.h b/apps/settings.h
index 012e289d0c..777c7dbefe 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -590,6 +590,8 @@ struct user_settings
590 /* playlist/playback settings */ 590 /* playlist/playback settings */
591 int repeat_mode; /* 0=off 1=repeat all 2=repeat one 3=shuffle 4=ab */ 591 int repeat_mode; /* 0=off 1=repeat all 2=repeat one 3=shuffle 4=ab */
592 int next_folder; /* move to next folder */ 592 int next_folder; /* move to next folder */
593 bool constrain_next_folder; /* whether next_folder is constrained to
594 directories within start_directory */
593 int recursive_dir_insert; /* should directories be inserted recursively */ 595 int recursive_dir_insert; /* should directories be inserted recursively */
594 bool fade_on_stop; /* fade on pause/unpause/stop */ 596 bool fade_on_stop; /* fade on pause/unpause/stop */
595 bool playlist_shuffle; 597 bool playlist_shuffle;
diff --git a/apps/settings_list.c b/apps/settings_list.c
index 2258582a78..5acebef2a5 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -1328,6 +1328,9 @@ const struct settings_list settings[] = {
1328 "folder navigation", "off,on,random",NULL ,3, 1328 "folder navigation", "off,on,random",NULL ,3,
1329 ID2P(LANG_SET_BOOL_NO), ID2P(LANG_SET_BOOL_YES), 1329 ID2P(LANG_SET_BOOL_NO), ID2P(LANG_SET_BOOL_YES),
1330 ID2P(LANG_RANDOM)), 1330 ID2P(LANG_RANDOM)),
1331 BOOL_SETTING(0, constrain_next_folder, LANG_CONSTRAIN_NEXT_FOLDER, false,
1332 "constrain next folder", off_on,
1333 LANG_SET_BOOL_YES, LANG_SET_BOOL_NO, NULL),
1331 1334
1332#ifdef HAVE_TAGCACHE 1335#ifdef HAVE_TAGCACHE
1333#if CONFIG_CODEC == SWCODEC 1336#if CONFIG_CODEC == SWCODEC