diff options
Diffstat (limited to 'apps/playlist.c')
-rw-r--r-- | apps/playlist.c | 167 |
1 files changed, 103 insertions, 64 deletions
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); | |||
175 | static int get_filename(struct playlist_info* playlist, int index, int seek, | 175 | static 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); |
177 | static int get_next_directory(char *dir); | 177 | static int get_next_directory(char *dir); |
178 | static int get_next_dir(char *dir, bool is_forward, bool recursion); | 178 | static int get_next_dir(char *dir, bool is_forward); |
179 | static int get_previous_directory(char *dir); | 179 | static int get_previous_directory(char *dir); |
180 | static int check_subdir_for_music(char *dir, const char *subdir, bool recurse); | 180 | static int check_subdir_for_music(char *dir, const char *subdir, bool recurse); |
181 | static int format_track_path(char *dest, char *src, int buf_length, int max, | 181 | static 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 | ||
1437 | static int get_next_directory(char *dir){ | 1438 | static 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 | ||
1441 | static int get_previous_directory(char *dir){ | 1442 | static 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 | */ |
1449 | static int get_next_dir(char *dir, bool is_forward, bool recursion) | 1450 | static int get_next_dir(char *dir, bool is_forward) |
1450 | { | 1451 | { |
1451 | struct playlist_info* playlist = ¤t_playlist; | 1452 | struct playlist_info* playlist = ¤t_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 | { |