diff options
Diffstat (limited to 'apps/playlist.c')
-rw-r--r-- | apps/playlist.c | 402 |
1 files changed, 234 insertions, 168 deletions
diff --git a/apps/playlist.c b/apps/playlist.c index d760b2450d..25939bb3ee 100644 --- a/apps/playlist.c +++ b/apps/playlist.c | |||
@@ -175,7 +175,11 @@ static int format_track_path(char *dest, char *src, int buf_length, int max, | |||
175 | char *dir); | 175 | char *dir); |
176 | static void display_playlist_count(int count, const unsigned char *fmt); | 176 | static void display_playlist_count(int count, const unsigned char *fmt); |
177 | static void display_buffer_full(void); | 177 | static void display_buffer_full(void); |
178 | static int flush_pending_control(struct playlist_info* playlist); | 178 | static int flush_cached_control(struct playlist_info* playlist); |
179 | static int update_control(struct playlist_info* playlist, | ||
180 | enum playlist_command command, int i1, int i2, | ||
181 | const char* s1, const char* s2, void* data); | ||
182 | static void sync_control(struct playlist_info* playlist, bool force); | ||
179 | static int rotate_index(const struct playlist_info* playlist, int index); | 183 | static int rotate_index(const struct playlist_info* playlist, int index); |
180 | 184 | ||
181 | #ifdef HAVE_DIRCACHE | 185 | #ifdef HAVE_DIRCACHE |
@@ -218,7 +222,9 @@ static void empty_playlist(struct playlist_info* playlist, bool resume) | |||
218 | playlist->shuffle_modified = false; | 222 | playlist->shuffle_modified = false; |
219 | playlist->deleted = false; | 223 | playlist->deleted = false; |
220 | playlist->num_inserted_tracks = 0; | 224 | playlist->num_inserted_tracks = 0; |
221 | playlist->shuffle_flush = false; | 225 | |
226 | playlist->num_cached = 0; | ||
227 | playlist->pending_control_sync = false; | ||
222 | 228 | ||
223 | if (!resume && playlist->current) | 229 | if (!resume && playlist->current) |
224 | { | 230 | { |
@@ -255,11 +261,9 @@ static void new_playlist(struct playlist_info* playlist, const char *dir, | |||
255 | 261 | ||
256 | if (playlist->control_fd >= 0) | 262 | if (playlist->control_fd >= 0) |
257 | { | 263 | { |
258 | if (fdprintf(playlist->control_fd, "P:%d:%s:%s\n", | 264 | update_control(playlist, PLAYLIST_COMMAND_PLAYLIST, |
259 | PLAYLIST_CONTROL_FILE_VERSION, dir, file) > 0) | 265 | PLAYLIST_CONTROL_FILE_VERSION, -1, dir, file, NULL); |
260 | fsync(playlist->control_fd); | 266 | sync_control(playlist, false); |
261 | else | ||
262 | gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_CONTROL_UPDATE_ERROR)); | ||
263 | } | 267 | } |
264 | } | 268 | } |
265 | 269 | ||
@@ -304,12 +308,9 @@ static int check_control(struct playlist_info* playlist) | |||
304 | 308 | ||
305 | playlist->filename[playlist->dirlen-1] = '\0'; | 309 | playlist->filename[playlist->dirlen-1] = '\0'; |
306 | 310 | ||
307 | if (fdprintf(playlist->control_fd, "P:%d:%s:%s\n", | 311 | update_control(playlist, PLAYLIST_COMMAND_PLAYLIST, |
308 | PLAYLIST_CONTROL_FILE_VERSION, dir, file) > 0) | 312 | PLAYLIST_CONTROL_FILE_VERSION, -1, dir, file, NULL); |
309 | fsync(playlist->control_fd); | 313 | sync_control(playlist, false); |
310 | else | ||
311 | gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_CONTROL_UPDATE_ERROR)); | ||
312 | |||
313 | playlist->filename[playlist->dirlen-1] = c; | 314 | playlist->filename[playlist->dirlen-1] = c; |
314 | } | 315 | } |
315 | } | 316 | } |
@@ -548,33 +549,12 @@ static int add_track_to_playlist(struct playlist_info* playlist, | |||
548 | 549 | ||
549 | if (seek_pos < 0 && playlist->control_fd >= 0) | 550 | if (seek_pos < 0 && playlist->control_fd >= 0) |
550 | { | 551 | { |
551 | int result = -1; | 552 | int result = update_control(playlist, |
552 | 553 | (queue?PLAYLIST_COMMAND_QUEUE:PLAYLIST_COMMAND_ADD), position, | |
553 | if (flush_pending_control(playlist) < 0) | 554 | playlist->last_insert_pos, filename, NULL, &seek_pos); |
554 | return -1; | ||
555 | |||
556 | mutex_lock(&playlist->control_mutex); | ||
557 | |||
558 | if (lseek(playlist->control_fd, 0, SEEK_END) >= 0) | ||
559 | { | ||
560 | if (fdprintf(playlist->control_fd, "%c:%d:%d:", (queue?'Q':'A'), | ||
561 | position, playlist->last_insert_pos) > 0) | ||
562 | { | ||
563 | /* save the position in file where track name is written */ | ||
564 | seek_pos = lseek(playlist->control_fd, 0, SEEK_CUR); | ||
565 | |||
566 | if (fdprintf(playlist->control_fd, "%s\n", filename) > 0) | ||
567 | result = 0; | ||
568 | } | ||
569 | } | ||
570 | |||
571 | mutex_unlock(&playlist->control_mutex); | ||
572 | 555 | ||
573 | if (result < 0) | 556 | if (result < 0) |
574 | { | ||
575 | gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_CONTROL_UPDATE_ERROR)); | ||
576 | return result; | 557 | return result; |
577 | } | ||
578 | } | 558 | } |
579 | 559 | ||
580 | playlist->indices[insert_position] = flags | seek_pos; | 560 | playlist->indices[insert_position] = flags | seek_pos; |
@@ -758,29 +738,13 @@ static int remove_track_from_playlist(struct playlist_info* playlist, | |||
758 | 738 | ||
759 | if (write && playlist->control_fd >= 0) | 739 | if (write && playlist->control_fd >= 0) |
760 | { | 740 | { |
761 | int result = -1; | 741 | int result = update_control(playlist, PLAYLIST_COMMAND_DELETE, |
762 | 742 | position, -1, NULL, NULL, NULL); | |
763 | if (flush_pending_control(playlist) < 0) | ||
764 | return -1; | ||
765 | |||
766 | mutex_lock(&playlist->control_mutex); | ||
767 | |||
768 | if (lseek(playlist->control_fd, 0, SEEK_END) >= 0) | ||
769 | { | ||
770 | if (fdprintf(playlist->control_fd, "D:%d\n", position) > 0) | ||
771 | { | ||
772 | fsync(playlist->control_fd); | ||
773 | result = 0; | ||
774 | } | ||
775 | } | ||
776 | |||
777 | mutex_unlock(&playlist->control_mutex); | ||
778 | 743 | ||
779 | if (result < 0) | 744 | if (result < 0) |
780 | { | ||
781 | gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_CONTROL_UPDATE_ERROR)); | ||
782 | return result; | 745 | return result; |
783 | } | 746 | |
747 | sync_control(playlist, false); | ||
784 | } | 748 | } |
785 | 749 | ||
786 | return 0; | 750 | return 0; |
@@ -838,9 +802,8 @@ static int randomise_playlist(struct playlist_info* playlist, | |||
838 | 802 | ||
839 | if (write) | 803 | if (write) |
840 | { | 804 | { |
841 | /* Don't write to disk immediately. Instead, save in settings and | 805 | update_control(playlist, PLAYLIST_COMMAND_SHUFFLE, seed, |
842 | only flush if playlist is modified (insertion/deletion) */ | 806 | playlist->first_index, NULL, NULL, NULL); |
843 | playlist->shuffle_flush = true; | ||
844 | global_settings.resume_seed = seed; | 807 | global_settings.resume_seed = seed; |
845 | settings_save(); | 808 | settings_save(); |
846 | } | 809 | } |
@@ -878,9 +841,8 @@ static int sort_playlist(struct playlist_info* playlist, bool start_current, | |||
878 | playlist->shuffle_modified = false; | 841 | playlist->shuffle_modified = false; |
879 | if (write && playlist->control_fd >= 0) | 842 | if (write && playlist->control_fd >= 0) |
880 | { | 843 | { |
881 | /* Don't write to disk immediately. Instead, save in settings and | 844 | update_control(playlist, PLAYLIST_COMMAND_UNSHUFFLE, |
882 | only flush if playlist is modified (insertion/deletion) */ | 845 | playlist->first_index, -1, NULL, NULL, NULL); |
883 | playlist->shuffle_flush = true; | ||
884 | global_settings.resume_seed = 0; | 846 | global_settings.resume_seed = 0; |
885 | settings_save(); | 847 | settings_save(); |
886 | } | 848 | } |
@@ -1094,7 +1056,8 @@ static int compare(const void* p1, const void* p2) | |||
1094 | #ifdef HAVE_DIRCACHE | 1056 | #ifdef HAVE_DIRCACHE |
1095 | /** | 1057 | /** |
1096 | * Thread to update filename pointers to dircache on background | 1058 | * Thread to update filename pointers to dircache on background |
1097 | * without affecting playlist load up performance. | 1059 | * without affecting playlist load up performance. This thread also flushes |
1060 | * any pending control commands when the disk spins up. | ||
1098 | */ | 1061 | */ |
1099 | static void playlist_thread(void) | 1062 | static void playlist_thread(void) |
1100 | { | 1063 | { |
@@ -1107,9 +1070,15 @@ static void playlist_thread(void) | |||
1107 | int seek; | 1070 | int seek; |
1108 | bool control_file; | 1071 | bool control_file; |
1109 | 1072 | ||
1073 | int sleep_time = 5; | ||
1074 | |||
1075 | if (global_settings.disk_spindown > 1 && | ||
1076 | global_settings.disk_spindown <= 5) | ||
1077 | sleep_time = global_settings.disk_spindown - 1; | ||
1078 | |||
1110 | while (1) | 1079 | while (1) |
1111 | { | 1080 | { |
1112 | queue_wait_w_tmo(&playlist_queue, &ev, HZ*5); | 1081 | queue_wait_w_tmo(&playlist_queue, &ev, HZ*sleep_time); |
1113 | 1082 | ||
1114 | switch (ev.id) | 1083 | switch (ev.id) |
1115 | { | 1084 | { |
@@ -1117,12 +1086,22 @@ static void playlist_thread(void) | |||
1117 | dirty_pointers = true; | 1086 | dirty_pointers = true; |
1118 | break ; | 1087 | break ; |
1119 | 1088 | ||
1120 | /* Start the background scanning after 5s. */ | 1089 | /* Start the background scanning after either the disk spindown |
1090 | timeout or 5s, whichever is less */ | ||
1121 | case SYS_TIMEOUT: | 1091 | case SYS_TIMEOUT: |
1092 | playlist = ¤t_playlist; | ||
1093 | |||
1094 | if (playlist->control_fd >= 0 && ata_disk_is_active()) | ||
1095 | { | ||
1096 | if (playlist->num_cached > 0) | ||
1097 | flush_cached_control(playlist); | ||
1098 | |||
1099 | sync_control(playlist, true); | ||
1100 | } | ||
1101 | |||
1122 | if (!dirty_pointers) | 1102 | if (!dirty_pointers) |
1123 | break ; | 1103 | break ; |
1124 | 1104 | ||
1125 | playlist = ¤t_playlist; | ||
1126 | if (!dircache_is_enabled() || !playlist->filenames | 1105 | if (!dircache_is_enabled() || !playlist->filenames |
1127 | || playlist->amount <= 0) | 1106 | || playlist->amount <= 0) |
1128 | break ; | 1107 | break ; |
@@ -1543,56 +1522,157 @@ static void display_buffer_full(void) | |||
1543 | } | 1522 | } |
1544 | 1523 | ||
1545 | /* | 1524 | /* |
1546 | * Flush any pending control commands to disk. Called when playlist is being | 1525 | * Flush any cached control commands to disk. Called when playlist is being |
1547 | * modified. Returns 0 on success and -1 on failure. | 1526 | * modified. Returns 0 on success and -1 on failure. |
1548 | */ | 1527 | */ |
1549 | static int flush_pending_control(struct playlist_info* playlist) | 1528 | static int flush_cached_control(struct playlist_info* playlist) |
1550 | { | 1529 | { |
1551 | int result = 0; | 1530 | int result = 0; |
1552 | 1531 | int i; | |
1553 | if (playlist->shuffle_flush && global_settings.resume_seed >= 0) | 1532 | |
1533 | lseek(playlist->control_fd, 0, SEEK_END); | ||
1534 | |||
1535 | for (i=0; i<playlist->num_cached; i++) | ||
1554 | { | 1536 | { |
1555 | /* pending shuffle */ | 1537 | struct playlist_control_cache* cache = |
1556 | mutex_lock(&playlist->control_mutex); | 1538 | &(playlist->control_cache[i]); |
1557 | 1539 | ||
1558 | if (lseek(playlist->control_fd, 0, SEEK_END) >= 0) | 1540 | switch (cache->command) |
1559 | { | 1541 | { |
1560 | if (global_settings.resume_seed == 0) | 1542 | case PLAYLIST_COMMAND_PLAYLIST: |
1561 | result = fdprintf(playlist->control_fd, "U:%d\n", | 1543 | result = fdprintf(playlist->control_fd, "P:%d:%s:%s\n", |
1562 | playlist->first_index); | 1544 | cache->i1, cache->s1, cache->s2); |
1563 | else | 1545 | break; |
1546 | case PLAYLIST_COMMAND_ADD: | ||
1547 | case PLAYLIST_COMMAND_QUEUE: | ||
1548 | result = fdprintf(playlist->control_fd, "%c:%d:%d:", | ||
1549 | (cache->command == PLAYLIST_COMMAND_ADD)?'A':'Q', | ||
1550 | cache->i1, cache->i2); | ||
1551 | if (result > 0) | ||
1552 | { | ||
1553 | /* save the position in file where name is written */ | ||
1554 | int* seek_pos = (int *)cache->data; | ||
1555 | *seek_pos = lseek(playlist->control_fd, 0, SEEK_CUR); | ||
1556 | result = fdprintf(playlist->control_fd, "%s\n", | ||
1557 | cache->s1); | ||
1558 | } | ||
1559 | break; | ||
1560 | case PLAYLIST_COMMAND_DELETE: | ||
1561 | result = fdprintf(playlist->control_fd, "D:%d\n", cache->i1); | ||
1562 | break; | ||
1563 | case PLAYLIST_COMMAND_SHUFFLE: | ||
1564 | result = fdprintf(playlist->control_fd, "S:%d:%d\n", | 1564 | result = fdprintf(playlist->control_fd, "S:%d:%d\n", |
1565 | global_settings.resume_seed, playlist->first_index); | 1565 | cache->i1, cache->i2); |
1566 | 1566 | break; | |
1567 | if (result > 0) | 1567 | case PLAYLIST_COMMAND_UNSHUFFLE: |
1568 | { | 1568 | result = fdprintf(playlist->control_fd, "U:%d\n", cache->i1); |
1569 | fsync(playlist->control_fd); | 1569 | break; |
1570 | case PLAYLIST_COMMAND_RESET: | ||
1571 | result = fdprintf(playlist->control_fd, "R\n"); | ||
1572 | break; | ||
1573 | default: | ||
1574 | break; | ||
1575 | } | ||
1570 | 1576 | ||
1571 | playlist->shuffle_flush = false; | 1577 | if (result <= 0) |
1572 | global_settings.resume_seed = -1; | 1578 | break; |
1573 | settings_save(); | 1579 | } |
1574 | 1580 | ||
1575 | result = 0; | 1581 | if (result > 0) |
1576 | } | 1582 | { |
1577 | else | 1583 | if (global_settings.resume_seed >= 0) |
1578 | result = -1; | ||
1579 | } | ||
1580 | else | ||
1581 | result = -1; | ||
1582 | |||
1583 | mutex_unlock(&playlist->control_mutex); | ||
1584 | |||
1585 | if (result < 0) | ||
1586 | { | 1584 | { |
1587 | gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_CONTROL_UPDATE_ERROR)); | 1585 | global_settings.resume_seed = -1; |
1588 | return result; | 1586 | settings_save(); |
1589 | } | 1587 | } |
1588 | |||
1589 | playlist->num_cached = 0; | ||
1590 | playlist->pending_control_sync = true; | ||
1591 | |||
1592 | result = 0; | ||
1593 | } | ||
1594 | else | ||
1595 | result = -1; | ||
1596 | |||
1597 | if (result < 0) | ||
1598 | { | ||
1599 | gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_CONTROL_UPDATE_ERROR)); | ||
1600 | return result; | ||
1590 | } | 1601 | } |
1591 | 1602 | ||
1592 | return result; | 1603 | return result; |
1593 | } | 1604 | } |
1594 | 1605 | ||
1595 | /* | 1606 | /* |
1607 | * Update control data with new command. Depending on the command, it may be | ||
1608 | * cached or flushed to disk. | ||
1609 | */ | ||
1610 | static int update_control(struct playlist_info* playlist, | ||
1611 | enum playlist_command command, int i1, int i2, | ||
1612 | const char* s1, const char* s2, void* data) | ||
1613 | { | ||
1614 | int result = 0; | ||
1615 | struct playlist_control_cache* cache; | ||
1616 | bool flush = false; | ||
1617 | |||
1618 | mutex_lock(&playlist->control_mutex); | ||
1619 | |||
1620 | cache = &(playlist->control_cache[playlist->num_cached++]); | ||
1621 | |||
1622 | cache->command = command; | ||
1623 | cache->i1 = i1; | ||
1624 | cache->i2 = i2; | ||
1625 | cache->s1 = s1; | ||
1626 | cache->s2 = s2; | ||
1627 | cache->data = data; | ||
1628 | |||
1629 | switch (command) | ||
1630 | { | ||
1631 | case PLAYLIST_COMMAND_PLAYLIST: | ||
1632 | case PLAYLIST_COMMAND_ADD: | ||
1633 | case PLAYLIST_COMMAND_QUEUE: | ||
1634 | #ifndef HAVE_DIRCACHE | ||
1635 | case PLAYLIST_COMMAND_DELETE: | ||
1636 | case PLAYLIST_COMMAND_RESET: | ||
1637 | #endif | ||
1638 | flush = true; | ||
1639 | break; | ||
1640 | case PLAYLIST_COMMAND_SHUFFLE: | ||
1641 | case PLAYLIST_COMMAND_UNSHUFFLE: | ||
1642 | default: | ||
1643 | /* only flush when needed */ | ||
1644 | break; | ||
1645 | } | ||
1646 | |||
1647 | if (flush || playlist->num_cached == PLAYLIST_MAX_CACHE) | ||
1648 | result = flush_cached_control(playlist); | ||
1649 | |||
1650 | mutex_unlock(&playlist->control_mutex); | ||
1651 | |||
1652 | return result; | ||
1653 | } | ||
1654 | |||
1655 | /* | ||
1656 | * sync control file to disk | ||
1657 | */ | ||
1658 | static void sync_control(struct playlist_info* playlist, bool force) | ||
1659 | { | ||
1660 | (void) force; | ||
1661 | #ifdef HAVE_DIRCACHE | ||
1662 | if (force) | ||
1663 | #endif | ||
1664 | { | ||
1665 | if (playlist->pending_control_sync) | ||
1666 | { | ||
1667 | mutex_lock(&playlist->control_mutex); | ||
1668 | fsync(playlist->control_fd); | ||
1669 | playlist->pending_control_sync = false; | ||
1670 | mutex_unlock(&playlist->control_mutex); | ||
1671 | } | ||
1672 | } | ||
1673 | } | ||
1674 | |||
1675 | /* | ||
1596 | * Rotate indices such that first_index is index 0 | 1676 | * Rotate indices such that first_index is index 0 |
1597 | */ | 1677 | */ |
1598 | static int rotate_index(const struct playlist_info* playlist, int index) | 1678 | static int rotate_index(const struct playlist_info* playlist, int index) |
@@ -1637,6 +1717,26 @@ void playlist_init(void) | |||
1637 | } | 1717 | } |
1638 | 1718 | ||
1639 | /* | 1719 | /* |
1720 | * Clean playlist at shutdown | ||
1721 | */ | ||
1722 | void playlist_shutdown(void) | ||
1723 | { | ||
1724 | struct playlist_info* playlist = ¤t_playlist; | ||
1725 | |||
1726 | if (playlist->control_fd >= 0) | ||
1727 | { | ||
1728 | mutex_lock(&playlist->control_mutex); | ||
1729 | |||
1730 | if (playlist->num_cached > 0) | ||
1731 | flush_cached_control(playlist); | ||
1732 | |||
1733 | close(playlist->control_fd); | ||
1734 | |||
1735 | mutex_unlock(&playlist->control_mutex); | ||
1736 | } | ||
1737 | } | ||
1738 | |||
1739 | /* | ||
1640 | * Create new playlist | 1740 | * Create new playlist |
1641 | */ | 1741 | */ |
1642 | int playlist_create(const char *dir, const char *file) | 1742 | int playlist_create(const char *dir, const char *file) |
@@ -1669,17 +1769,6 @@ int playlist_resume(void) | |||
1669 | bool first = true; | 1769 | bool first = true; |
1670 | bool sorted = true; | 1770 | bool sorted = true; |
1671 | 1771 | ||
1672 | enum { | ||
1673 | resume_playlist, | ||
1674 | resume_add, | ||
1675 | resume_queue, | ||
1676 | resume_delete, | ||
1677 | resume_shuffle, | ||
1678 | resume_unshuffle, | ||
1679 | resume_reset, | ||
1680 | resume_comment | ||
1681 | }; | ||
1682 | |||
1683 | /* use mp3 buffer for maximum load speed */ | 1772 | /* use mp3 buffer for maximum load speed */ |
1684 | #if CONFIG_CODEC != SWCODEC | 1773 | #if CONFIG_CODEC != SWCODEC |
1685 | talk_buffer_steal(); /* we use the mp3 buffer, need to tell */ | 1774 | talk_buffer_steal(); /* we use the mp3 buffer, need to tell */ |
@@ -1721,7 +1810,7 @@ int playlist_resume(void) | |||
1721 | { | 1810 | { |
1722 | int result = 0; | 1811 | int result = 0; |
1723 | int count; | 1812 | int count; |
1724 | int current_command = resume_comment; | 1813 | enum playlist_command current_command = PLAYLIST_COMMAND_COMMENT; |
1725 | int last_newline = 0; | 1814 | int last_newline = 0; |
1726 | int str_count = -1; | 1815 | int str_count = -1; |
1727 | bool newline = true; | 1816 | bool newline = true; |
@@ -1743,7 +1832,7 @@ int playlist_resume(void) | |||
1743 | 1832 | ||
1744 | switch (current_command) | 1833 | switch (current_command) |
1745 | { | 1834 | { |
1746 | case resume_playlist: | 1835 | case PLAYLIST_COMMAND_PLAYLIST: |
1747 | { | 1836 | { |
1748 | /* str1=version str2=dir str3=file */ | 1837 | /* str1=version str2=dir str3=file */ |
1749 | int version; | 1838 | int version; |
@@ -1787,8 +1876,8 @@ int playlist_resume(void) | |||
1787 | 1876 | ||
1788 | break; | 1877 | break; |
1789 | } | 1878 | } |
1790 | case resume_add: | 1879 | case PLAYLIST_COMMAND_ADD: |
1791 | case resume_queue: | 1880 | case PLAYLIST_COMMAND_QUEUE: |
1792 | { | 1881 | { |
1793 | /* str1=position str2=last_position str3=file */ | 1882 | /* str1=position str2=last_position str3=file */ |
1794 | int position, last_position; | 1883 | int position, last_position; |
@@ -1804,7 +1893,8 @@ int playlist_resume(void) | |||
1804 | position = atoi(str1); | 1893 | position = atoi(str1); |
1805 | last_position = atoi(str2); | 1894 | last_position = atoi(str2); |
1806 | 1895 | ||
1807 | queue = (current_command == resume_add)?false:true; | 1896 | queue = (current_command == PLAYLIST_COMMAND_ADD)? |
1897 | false:true; | ||
1808 | 1898 | ||
1809 | /* seek position is based on str3's position in | 1899 | /* seek position is based on str3's position in |
1810 | buffer */ | 1900 | buffer */ |
@@ -1816,7 +1906,7 @@ int playlist_resume(void) | |||
1816 | 1906 | ||
1817 | break; | 1907 | break; |
1818 | } | 1908 | } |
1819 | case resume_delete: | 1909 | case PLAYLIST_COMMAND_DELETE: |
1820 | { | 1910 | { |
1821 | /* str1=position */ | 1911 | /* str1=position */ |
1822 | int position; | 1912 | int position; |
@@ -1836,7 +1926,7 @@ int playlist_resume(void) | |||
1836 | 1926 | ||
1837 | break; | 1927 | break; |
1838 | } | 1928 | } |
1839 | case resume_shuffle: | 1929 | case PLAYLIST_COMMAND_SHUFFLE: |
1840 | { | 1930 | { |
1841 | /* str1=seed str2=first_index */ | 1931 | /* str1=seed str2=first_index */ |
1842 | int seed; | 1932 | int seed; |
@@ -1864,7 +1954,7 @@ int playlist_resume(void) | |||
1864 | sorted = false; | 1954 | sorted = false; |
1865 | break; | 1955 | break; |
1866 | } | 1956 | } |
1867 | case resume_unshuffle: | 1957 | case PLAYLIST_COMMAND_UNSHUFFLE: |
1868 | { | 1958 | { |
1869 | /* str1=first_index */ | 1959 | /* str1=first_index */ |
1870 | if (!str1) | 1960 | if (!str1) |
@@ -1882,12 +1972,12 @@ int playlist_resume(void) | |||
1882 | sorted = true; | 1972 | sorted = true; |
1883 | break; | 1973 | break; |
1884 | } | 1974 | } |
1885 | case resume_reset: | 1975 | case PLAYLIST_COMMAND_RESET: |
1886 | { | 1976 | { |
1887 | playlist->last_insert_pos = -1; | 1977 | playlist->last_insert_pos = -1; |
1888 | break; | 1978 | break; |
1889 | } | 1979 | } |
1890 | case resume_comment: | 1980 | case PLAYLIST_COMMAND_COMMENT: |
1891 | default: | 1981 | default: |
1892 | break; | 1982 | break; |
1893 | } | 1983 | } |
@@ -1895,7 +1985,7 @@ int playlist_resume(void) | |||
1895 | newline = true; | 1985 | newline = true; |
1896 | 1986 | ||
1897 | /* to ignore any extra newlines */ | 1987 | /* to ignore any extra newlines */ |
1898 | current_command = resume_comment; | 1988 | current_command = PLAYLIST_COMMAND_COMMENT; |
1899 | } | 1989 | } |
1900 | else if(newline) | 1990 | else if(newline) |
1901 | { | 1991 | { |
@@ -1920,28 +2010,28 @@ int playlist_resume(void) | |||
1920 | break; | 2010 | break; |
1921 | } | 2011 | } |
1922 | 2012 | ||
1923 | current_command = resume_playlist; | 2013 | current_command = PLAYLIST_COMMAND_PLAYLIST; |
1924 | break; | 2014 | break; |
1925 | case 'A': | 2015 | case 'A': |
1926 | current_command = resume_add; | 2016 | current_command = PLAYLIST_COMMAND_ADD; |
1927 | break; | 2017 | break; |
1928 | case 'Q': | 2018 | case 'Q': |
1929 | current_command = resume_queue; | 2019 | current_command = PLAYLIST_COMMAND_QUEUE; |
1930 | break; | 2020 | break; |
1931 | case 'D': | 2021 | case 'D': |
1932 | current_command = resume_delete; | 2022 | current_command = PLAYLIST_COMMAND_DELETE; |
1933 | break; | 2023 | break; |
1934 | case 'S': | 2024 | case 'S': |
1935 | current_command = resume_shuffle; | 2025 | current_command = PLAYLIST_COMMAND_SHUFFLE; |
1936 | break; | 2026 | break; |
1937 | case 'U': | 2027 | case 'U': |
1938 | current_command = resume_unshuffle; | 2028 | current_command = PLAYLIST_COMMAND_UNSHUFFLE; |
1939 | break; | 2029 | break; |
1940 | case 'R': | 2030 | case 'R': |
1941 | current_command = resume_reset; | 2031 | current_command = PLAYLIST_COMMAND_RESET; |
1942 | break; | 2032 | break; |
1943 | case '#': | 2033 | case '#': |
1944 | current_command = resume_comment; | 2034 | current_command = PLAYLIST_COMMAND_COMMENT; |
1945 | break; | 2035 | break; |
1946 | default: | 2036 | default: |
1947 | result = -1; | 2037 | result = -1; |
@@ -1954,7 +2044,7 @@ int playlist_resume(void) | |||
1954 | str2 = NULL; | 2044 | str2 = NULL; |
1955 | str3 = NULL; | 2045 | str3 = NULL; |
1956 | } | 2046 | } |
1957 | else if(current_command != resume_comment) | 2047 | else if(current_command != PLAYLIST_COMMAND_COMMENT) |
1958 | { | 2048 | { |
1959 | /* all control file strings are separated with a colon. | 2049 | /* all control file strings are separated with a colon. |
1960 | Replace the colon with 0 to get proper strings that can be | 2050 | Replace the colon with 0 to get proper strings that can be |
@@ -2097,9 +2187,6 @@ int playlist_shuffle(int random_seed, int start_index) | |||
2097 | 2187 | ||
2098 | randomise_playlist(playlist, random_seed, start_current, true); | 2188 | randomise_playlist(playlist, random_seed, start_current, true); |
2099 | 2189 | ||
2100 | /* Flush shuffle command to disk */ | ||
2101 | flush_pending_control(playlist); | ||
2102 | |||
2103 | return playlist->index; | 2190 | return playlist->index; |
2104 | } | 2191 | } |
2105 | 2192 | ||
@@ -2300,27 +2387,13 @@ int playlist_next(int steps) | |||
2300 | 2387 | ||
2301 | if (playlist->control_fd >= 0) | 2388 | if (playlist->control_fd >= 0) |
2302 | { | 2389 | { |
2303 | int result = -1; | 2390 | int result = update_control(playlist, PLAYLIST_COMMAND_RESET, |
2304 | 2391 | -1, -1, NULL, NULL, NULL); | |
2305 | mutex_lock(&playlist->control_mutex); | ||
2306 | |||
2307 | if (lseek(playlist->control_fd, 0, SEEK_END) >= 0) | ||
2308 | { | ||
2309 | if (fdprintf(playlist->control_fd, "R\n") > 0) | ||
2310 | { | ||
2311 | fsync(playlist->control_fd); | ||
2312 | result = 0; | ||
2313 | } | ||
2314 | } | ||
2315 | |||
2316 | mutex_unlock(&playlist->control_mutex); | ||
2317 | 2392 | ||
2318 | if (result < 0) | 2393 | if (result < 0) |
2319 | { | ||
2320 | gui_syncsplash(HZ*2, true, | ||
2321 | str(LANG_PLAYLIST_CONTROL_UPDATE_ERROR)); | ||
2322 | return result; | 2394 | return result; |
2323 | } | 2395 | |
2396 | sync_control(playlist, false); | ||
2324 | } | 2397 | } |
2325 | } | 2398 | } |
2326 | } | 2399 | } |
@@ -2536,8 +2609,12 @@ int playlist_set_current(struct playlist_info* playlist) | |||
2536 | current_playlist.shuffle_modified = playlist->shuffle_modified; | 2609 | current_playlist.shuffle_modified = playlist->shuffle_modified; |
2537 | current_playlist.deleted = playlist->deleted; | 2610 | current_playlist.deleted = playlist->deleted; |
2538 | current_playlist.num_inserted_tracks = playlist->num_inserted_tracks; | 2611 | current_playlist.num_inserted_tracks = playlist->num_inserted_tracks; |
2539 | current_playlist.shuffle_flush = playlist->shuffle_flush; | ||
2540 | 2612 | ||
2613 | memcpy(current_playlist.control_cache, playlist->control_cache, | ||
2614 | sizeof(current_playlist.control_cache)); | ||
2615 | current_playlist.num_cached = playlist->num_cached; | ||
2616 | current_playlist.pending_control_sync = playlist->pending_control_sync; | ||
2617 | |||
2541 | return 0; | 2618 | return 0; |
2542 | } | 2619 | } |
2543 | 2620 | ||
@@ -2581,10 +2658,7 @@ int playlist_insert_track(struct playlist_info* playlist, | |||
2581 | 2658 | ||
2582 | if (result != -1) | 2659 | if (result != -1) |
2583 | { | 2660 | { |
2584 | mutex_lock(&playlist->control_mutex); | 2661 | sync_control(playlist, false); |
2585 | fsync(playlist->control_fd); | ||
2586 | mutex_unlock(&playlist->control_mutex); | ||
2587 | |||
2588 | if (audio_status() & AUDIO_STATUS_PLAY) | 2662 | if (audio_status() & AUDIO_STATUS_PLAY) |
2589 | audio_flush_and_reload_tracks(); | 2663 | audio_flush_and_reload_tracks(); |
2590 | } | 2664 | } |
@@ -2626,9 +2700,7 @@ int playlist_insert_directory(struct playlist_info* playlist, | |||
2626 | result = add_directory_to_playlist(playlist, dirname, &position, queue, | 2700 | result = add_directory_to_playlist(playlist, dirname, &position, queue, |
2627 | &count, recurse); | 2701 | &count, recurse); |
2628 | 2702 | ||
2629 | mutex_lock(&playlist->control_mutex); | 2703 | sync_control(playlist, false); |
2630 | fsync(playlist->control_fd); | ||
2631 | mutex_unlock(&playlist->control_mutex); | ||
2632 | 2704 | ||
2633 | display_playlist_count(count, count_str); | 2705 | display_playlist_count(count, count_str); |
2634 | 2706 | ||
@@ -2741,13 +2813,11 @@ int playlist_insert_playlist(struct playlist_info* playlist, char *filename, | |||
2741 | 2813 | ||
2742 | close(fd); | 2814 | close(fd); |
2743 | 2815 | ||
2744 | mutex_lock(&playlist->control_mutex); | ||
2745 | fsync(playlist->control_fd); | ||
2746 | mutex_unlock(&playlist->control_mutex); | ||
2747 | |||
2748 | if (temp_ptr) | 2816 | if (temp_ptr) |
2749 | *temp_ptr = '/'; | 2817 | *temp_ptr = '/'; |
2750 | 2818 | ||
2819 | sync_control(playlist, false); | ||
2820 | |||
2751 | display_playlist_count(count, count_str); | 2821 | display_playlist_count(count, count_str); |
2752 | 2822 | ||
2753 | if (audio_status() & AUDIO_STATUS_PLAY) | 2823 | if (audio_status() & AUDIO_STATUS_PLAY) |
@@ -2870,10 +2940,6 @@ int playlist_move(struct playlist_info* playlist, int index, int new_index) | |||
2870 | } | 2940 | } |
2871 | } | 2941 | } |
2872 | 2942 | ||
2873 | mutex_lock(&playlist->control_mutex); | ||
2874 | fsync(playlist->control_fd); | ||
2875 | mutex_unlock(&playlist->control_mutex); | ||
2876 | |||
2877 | if (audio_status() & AUDIO_STATUS_PLAY) | 2943 | if (audio_status() & AUDIO_STATUS_PLAY) |
2878 | audio_flush_and_reload_tracks(); | 2944 | audio_flush_and_reload_tracks(); |
2879 | } | 2945 | } |