diff options
author | Hardeep Sidhu <dyp@pobox.com> | 2006-02-05 18:17:41 +0000 |
---|---|---|
committer | Hardeep Sidhu <dyp@pobox.com> | 2006-02-05 18:17:41 +0000 |
commit | 75a60fbf69fb7d7be5839b35efc8253d682a1c7d (patch) | |
tree | 219ce4485e7128232090e3cbcdd357addbf09481 /apps/playlist.c | |
parent | 987879b958f87a9af7ef9edcf6ae417fe56db788 (diff) | |
download | rockbox-75a60fbf69fb7d7be5839b35efc8253d682a1c7d.tar.gz rockbox-75a60fbf69fb7d7be5839b35efc8253d682a1c7d.zip |
Added a cache for playlist control commands. On non-dircache systems, behaviour should be the same as before (all commands except shuffle flushed immediately). On dircache systems, commands are only flushed when disk is accessed or during shutdown. This especially reduces disk accesses when playing queued files and should fix the problem with gapless playback.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8584 a1c6a512-1295-4272-9138-f99709370657
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 | } |