summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorMiika Pekkarinen <miipekk@ihme.org>2005-11-17 19:31:29 +0000
committerMiika Pekkarinen <miipekk@ihme.org>2005-11-17 19:31:29 +0000
commit735f4537309d4a66e16dd020fa99149a9d5f8d29 (patch)
tree7326f1f8f45f43c40bc78b86e4809087dffa9aa7 /apps
parentbc8a4e4b8cb613b7a0e4f348fe81086f92d9a994 (diff)
downloadrockbox-735f4537309d4a66e16dd020fa99149a9d5f8d29.tar.gz
rockbox-735f4537309d4a66e16dd020fa99149a9d5f8d29.zip
Added dircache support to playlist. Now playlist filename pointers are
automatically accuired from dircache. WPS UI response with dircache enabled should be instant. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7931 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/filetree.c1
-rw-r--r--apps/lang/english.lang6
-rw-r--r--apps/playback.c137
-rw-r--r--apps/playlist.c216
-rw-r--r--apps/playlist.h3
-rw-r--r--apps/wps.c4
6 files changed, 292 insertions, 75 deletions
diff --git a/apps/filetree.c b/apps/filetree.c
index a873d85f1c..a9670e1be7 100644
--- a/apps/filetree.c
+++ b/apps/filetree.c
@@ -340,6 +340,7 @@ int ft_enter(struct tree_context* c)
340 int start_index=0; 340 int start_index=0;
341 341
342 lcd_stop_scroll(); 342 lcd_stop_scroll();
343 gui_syncsplash(0, true, str(LANG_WAIT));
343 switch ( file->attr & TREE_ATTR_MASK ) { 344 switch ( file->attr & TREE_ATTR_MASK ) {
344 case TREE_ATTR_M3U: 345 case TREE_ATTR_M3U:
345 if (bookmark_autoload(buf)) 346 if (bookmark_autoload(buf))
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 4e712a22af..6afcb573c9 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -3431,3 +3431,9 @@ eng: "Clear current presets?"
3431voice: "Clear current presets?" 3431voice: "Clear current presets?"
3432new: 3432new:
3433 3433
3434id: LANG_WAIT
3435desc: general please wait splash
3436eng: "=== Please Wait ==="
3437voice: "Please wait"
3438new:
3439
diff --git a/apps/playback.c b/apps/playback.c
index 7f28331b75..b68cb641fe 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -165,9 +165,6 @@ static volatile int buf_widx;
165/* Step count to the next unbuffered track. */ 165/* Step count to the next unbuffered track. */
166static int last_peek_offset; 166static int last_peek_offset;
167 167
168/* Index of the last buffered track. */
169static int last_index;
170
171/* Track information (count in file buffer, read/write indexes for 168/* Track information (count in file buffer, read/write indexes for
172 track ring structure. */ 169 track ring structure. */
173int track_count; 170int track_count;
@@ -589,7 +586,7 @@ static bool rebuffer_and_seek(int newpos)
589 586
590 while (cur_ti->available == 0 && cur_ti->filerem > 0) { 587 while (cur_ti->available == 0 && cur_ti->filerem > 0) {
591 yield(); 588 yield();
592 if (ci.stop_codec || ci.reload_codec) 589 if (ci.stop_codec || ci.reload_codec || !queue_empty(&audio_queue))
593 return false; 590 return false;
594 } 591 }
595 592
@@ -1048,8 +1045,6 @@ bool audio_load_track(int offset, bool start_play, int peek_offset)
1048 if (tracks[track_widx].filesize != 0) 1045 if (tracks[track_widx].filesize != 0)
1049 return false; 1046 return false;
1050 1047
1051 last_index = playlist_get_display_index();
1052
1053 peek_again: 1048 peek_again:
1054 /* Get track name from current playlist read position. */ 1049 /* Get track name from current playlist read position. */
1055 logf("Buffering track:%d/%d", track_widx, track_ridx); 1050 logf("Buffering track:%d/%d", track_widx, track_ridx);
@@ -1456,7 +1451,6 @@ void audio_update_trackinfo(void)
1456 } else { 1451 } else {
1457 pcmbuf_add_event(codec_track_changed); 1452 pcmbuf_add_event(codec_track_changed);
1458 } 1453 }
1459 last_index = playlist_get_display_index();
1460} 1454}
1461 1455
1462static void audio_stop_playback(void) 1456static void audio_stop_playback(void)
@@ -1519,8 +1513,8 @@ bool codec_request_next_track_callback(void)
1519{ 1513{
1520 if (current_codec == CODEC_IDX_VOICE) { 1514 if (current_codec == CODEC_IDX_VOICE) {
1521 voice_remaining = 0; 1515 voice_remaining = 0;
1522 /* Terminate the codec if they are messages waiting on the queue or 1516 /* Terminate the codec if there are messages waiting on the queue or
1523 core has been requested the codec to be terminated. */ 1517 the core has been requested the codec to be terminated. */
1524 return !ci_voice.stop_codec && queue_empty(&voice_codec_queue); 1518 return !ci_voice.stop_codec && queue_empty(&voice_codec_queue);
1525 } 1519 }
1526 1520
@@ -1531,12 +1525,7 @@ bool codec_request_next_track_callback(void)
1531 1525
1532 /* Advance to next track. */ 1526 /* Advance to next track. */
1533 if (ci.reload_codec && new_track > 0) { 1527 if (ci.reload_codec && new_track > 0) {
1534 if (!playlist_check(new_track)) {
1535 ci.reload_codec = false;
1536 return false;
1537 }
1538 last_peek_offset--; 1528 last_peek_offset--;
1539 playlist_next(new_track);
1540 if (++track_ridx == MAX_TRACK) 1529 if (++track_ridx == MAX_TRACK)
1541 track_ridx = 0; 1530 track_ridx = 0;
1542 1531
@@ -1549,7 +1538,6 @@ bool codec_request_next_track_callback(void)
1549 if (tracks[track_ridx].filesize == 0) { 1538 if (tracks[track_ridx].filesize == 0) {
1550 logf("Loading from disk..."); 1539 logf("Loading from disk...");
1551 new_track = 0; 1540 new_track = 0;
1552 last_index = -1;
1553 queue_post(&audio_queue, AUDIO_PLAY, 0); 1541 queue_post(&audio_queue, AUDIO_PLAY, 0);
1554 return false; 1542 return false;
1555 } 1543 }
@@ -1557,12 +1545,7 @@ bool codec_request_next_track_callback(void)
1557 1545
1558 /* Advance to previous track. */ 1546 /* Advance to previous track. */
1559 else if (ci.reload_codec && new_track < 0) { 1547 else if (ci.reload_codec && new_track < 0) {
1560 if (!playlist_check(new_track)) {
1561 ci.reload_codec = false;
1562 return false;
1563 }
1564 last_peek_offset++; 1548 last_peek_offset++;
1565 playlist_next(new_track);
1566 if (--track_ridx < 0) 1549 if (--track_ridx < 0)
1567 track_ridx = MAX_TRACK-1; 1550 track_ridx = MAX_TRACK-1;
1568 if (tracks[track_ridx].filesize == 0 || 1551 if (tracks[track_ridx].filesize == 0 ||
@@ -1570,7 +1553,6 @@ bool codec_request_next_track_callback(void)
1570 /*+ (off_t)tracks[track_ridx].codecsize*/ > filebuflen) { 1553 /*+ (off_t)tracks[track_ridx].codecsize*/ > filebuflen) {
1571 logf("Loading from disk..."); 1554 logf("Loading from disk...");
1572 new_track = 0; 1555 new_track = 0;
1573 last_index = -1;
1574 queue_post(&audio_queue, AUDIO_PLAY, 0); 1556 queue_post(&audio_queue, AUDIO_PLAY, 0);
1575 return false; 1557 return false;
1576 } 1558 }
@@ -1597,7 +1579,6 @@ bool codec_request_next_track_callback(void)
1597 logf("No more tracks [2]"); 1579 logf("No more tracks [2]");
1598 ci.stop_codec = true; 1580 ci.stop_codec = true;
1599 new_track = 0; 1581 new_track = 0;
1600 last_index = -1;
1601 queue_post(&audio_queue, AUDIO_PLAY, 0); 1582 queue_post(&audio_queue, AUDIO_PLAY, 0);
1602 return false; 1583 return false;
1603 } 1584 }
@@ -1652,7 +1633,6 @@ static void initiate_track_change(int peek_index)
1652 1633
1653 /* Detect if disk is spinning.. */ 1634 /* Detect if disk is spinning.. */
1654 if (filling) { 1635 if (filling) {
1655 playlist_next(peek_index);
1656 queue_post(&audio_queue, AUDIO_PLAY, 0); 1636 queue_post(&audio_queue, AUDIO_PLAY, 0);
1657 } else { 1637 } else {
1658 new_track = peek_index; 1638 new_track = peek_index;
@@ -1677,35 +1657,49 @@ static void initiate_dir_change(int direction)
1677void audio_thread(void) 1657void audio_thread(void)
1678{ 1658{
1679 struct event ev; 1659 struct event ev;
1660 int last_tick = 0;
1661 bool play_pending = false;
1680 1662
1681 while (1) { 1663 while (1) {
1682 yield_codecs(); 1664 if (!play_pending)
1683 1665 {
1684 audio_check_buffer(); 1666 yield_codecs();
1667 audio_check_buffer();
1668 }
1669 else
1670 {
1671 // ata_spin();
1672 sleep(1);
1673 }
1685 1674
1686 queue_wait_w_tmo(&audio_queue, &ev, 0); 1675 queue_wait_w_tmo(&audio_queue, &ev, 0);
1676 if (ev.id == SYS_TIMEOUT && play_pending)
1677 {
1678 ev.id = AUDIO_PLAY;
1679 ev.data = 0;
1680 }
1681
1687 switch (ev.id) { 1682 switch (ev.id) {
1688 case AUDIO_PLAY: 1683 case AUDIO_PLAY:
1689 /* Refuse to start playback if we are already playing 1684 /* Don't start playing immediately if user is skipping tracks
1690 the requested track. This is needed because when skipping 1685 * fast to prevent UI lag. */
1691 tracks fast, AUDIO_PLAY commands will get queued with the 1686 track_count = 0;
1692 the same track and playback will stutter. */ 1687 last_peek_offset = 0;
1693 if (last_index == playlist_get_display_index() && playing 1688 if (current_tick - last_tick < HZ/2)
1694 && pcm_is_playing()) { 1689 {
1695 logf("already playing req. track"); 1690 play_pending = true;
1696 break ; 1691 break ;
1697 } 1692 }
1698 1693 play_pending = false;
1694
1699 /* Do not start crossfading if audio is paused. */ 1695 /* Do not start crossfading if audio is paused. */
1700 if (paused) { 1696 if (paused)
1701 audio_stop_playback(); 1697 pcmbuf_play_stop();
1702 paused = false;
1703 }
1704 1698
1705#ifdef CONFIG_TUNER 1699#ifdef CONFIG_TUNER
1706 /* check if radio is playing */ 1700 /* check if radio is playing */
1707 if(radio_get_status() != FMRADIO_OFF){ 1701 if (radio_get_status() != FMRADIO_OFF) {
1708 radio_stop(); 1702 radio_stop();
1709 } 1703 }
1710#endif 1704#endif
1711 1705
@@ -1751,15 +1745,13 @@ void audio_thread(void)
1751 1745
1752 case AUDIO_NEXT: 1746 case AUDIO_NEXT:
1753 logf("audio_next"); 1747 logf("audio_next");
1754 if (global_settings.beep) 1748 last_tick = current_tick;
1755 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
1756 initiate_track_change(1); 1749 initiate_track_change(1);
1757 break ; 1750 break ;
1758 1751
1759 case AUDIO_PREV: 1752 case AUDIO_PREV:
1760 logf("audio_prev"); 1753 logf("audio_prev");
1761 if (global_settings.beep) 1754 last_tick = current_tick;
1762 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
1763 initiate_track_change(-1); 1755 initiate_track_change(-1);
1764 break; 1756 break;
1765 1757
@@ -1793,7 +1785,7 @@ void audio_thread(void)
1793 // audio_change_track(); 1785 // audio_change_track();
1794 break ; 1786 break ;
1795 1787
1796#ifndef SIMULATOR 1788#ifndef SIMULATOR
1797 case SYS_USB_CONNECTED: 1789 case SYS_USB_CONNECTED:
1798 logf("USB: Audio core"); 1790 logf("USB: Audio core");
1799 audio_stop_playback(); 1791 audio_stop_playback();
@@ -1973,12 +1965,28 @@ void voice_init(void)
1973 1965
1974struct mp3entry* audio_current_track(void) 1966struct mp3entry* audio_current_track(void)
1975{ 1967{
1976 // logf("audio_current_track"); 1968 const char *filename;
1969 const char *p;
1970 static struct mp3entry temp_id3;
1977 1971
1978 if (track_count > 0 && cur_ti->taginfo_ready) 1972 if (track_count > 0 && cur_ti->taginfo_ready)
1979 return (struct mp3entry *)&cur_ti->id3; 1973 return (struct mp3entry *)&cur_ti->id3;
1980 else 1974 else {
1981 return NULL; 1975 filename = playlist_peek(0);
1976 if (!filename)
1977 filename = "No file!";
1978 p = strrchr(filename, '/');
1979 if (!p)
1980 p = filename;
1981 else
1982 p++;
1983
1984 memset(&temp_id3, 0, sizeof(struct mp3entry));
1985 strncpy(temp_id3.path, p, sizeof(temp_id3.path)-1);
1986 temp_id3.title = &temp_id3.path[0];
1987
1988 return &temp_id3;
1989 }
1982} 1990}
1983 1991
1984struct mp3entry* audio_next_track(void) 1992struct mp3entry* audio_next_track(void)
@@ -1994,16 +2002,12 @@ struct mp3entry* audio_next_track(void)
1994 if (!tracks[next_idx].taginfo_ready) 2002 if (!tracks[next_idx].taginfo_ready)
1995 return NULL; 2003 return NULL;
1996 2004
1997 //logf("audio_next_track");
1998
1999 return &tracks[next_idx].id3; 2005 return &tracks[next_idx].id3;
2000} 2006}
2001 2007
2002bool audio_has_changed_track(void) 2008bool audio_has_changed_track(void)
2003{ 2009{
2004 if (track_changed && track_count > 0 && playing) { 2010 if (track_changed) {
2005 if (!cur_ti->taginfo_ready)
2006 return false;
2007 track_changed = false; 2011 track_changed = false;
2008 return true; 2012 return true;
2009 } 2013 }
@@ -2014,7 +2018,6 @@ bool audio_has_changed_track(void)
2014void audio_play(int offset) 2018void audio_play(int offset)
2015{ 2019{
2016 logf("audio_play"); 2020 logf("audio_play");
2017 last_index = -1;
2018 queue_post(&audio_queue, AUDIO_PLAY, (void *)offset); 2021 queue_post(&audio_queue, AUDIO_PLAY, (void *)offset);
2019} 2022}
2020 2023
@@ -2043,11 +2046,37 @@ void audio_resume(void)
2043 2046
2044void audio_next(void) 2047void audio_next(void)
2045{ 2048{
2049 /* Prevent UI lag and update the WPS immediately. */
2050 if (global_settings.beep)
2051 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
2052
2053 if (!playlist_check(1))
2054 return ;
2055 playlist_next(1);
2056 track_changed = true;
2057
2058 /* Force WPS to update even if audio thread is blocked spinning. */
2059 if (mutex_bufferfill.locked)
2060 cur_ti->taginfo_ready = false;
2061
2046 queue_post(&audio_queue, AUDIO_NEXT, 0); 2062 queue_post(&audio_queue, AUDIO_NEXT, 0);
2047} 2063}
2048 2064
2049void audio_prev(void) 2065void audio_prev(void)
2050{ 2066{
2067 /* Prevent UI lag and update the WPS immediately. */
2068 if (global_settings.beep)
2069 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
2070
2071 if (!playlist_check(-1))
2072 return ;
2073 playlist_next(-1);
2074 track_changed = true;
2075
2076 /* Force WPS to update even if audio thread is blocked spinning. */
2077 if (mutex_bufferfill.locked)
2078 cur_ti->taginfo_ready = false;
2079
2051 queue_post(&audio_queue, AUDIO_PREV, 0); 2080 queue_post(&audio_queue, AUDIO_PREV, 0);
2052} 2081}
2053 2082
diff --git a/apps/playlist.c b/apps/playlist.c
index a2f46cf99f..ee09eecf40 100644
--- a/apps/playlist.c
+++ b/apps/playlist.c
@@ -86,6 +86,9 @@
86#include "button.h" 86#include "button.h"
87#include "filetree.h" 87#include "filetree.h"
88#include "abrepeat.h" 88#include "abrepeat.h"
89#include "dircache.h"
90#include "thread.h"
91#include "usb.h"
89#ifdef HAVE_LCD_BITMAP 92#ifdef HAVE_LCD_BITMAP
90#include "icons.h" 93#include "icons.h"
91#include "widgets.h" 94#include "widgets.h"
@@ -162,7 +165,7 @@ static int get_next_index(const struct playlist_info* playlist, int steps,
162static void find_and_set_playlist_index(struct playlist_info* playlist, 165static void find_and_set_playlist_index(struct playlist_info* playlist,
163 unsigned int seek); 166 unsigned int seek);
164static int compare(const void* p1, const void* p2); 167static int compare(const void* p1, const void* p2);
165static int get_filename(struct playlist_info* playlist, int seek, 168static int get_filename(struct playlist_info* playlist, int index, int seek,
166 bool control_file, char *buf, int buf_length); 169 bool control_file, char *buf, int buf_length);
167static int get_next_directory(char *dir); 170static int get_next_directory(char *dir);
168static int get_next_dir(char *dir, bool is_forward, bool recursion); 171static int get_next_dir(char *dir, bool is_forward, bool recursion);
@@ -175,6 +178,14 @@ static void display_buffer_full(void);
175static int flush_pending_control(struct playlist_info* playlist); 178static int flush_pending_control(struct playlist_info* playlist);
176static int rotate_index(const struct playlist_info* playlist, int index); 179static int rotate_index(const struct playlist_info* playlist, int index);
177 180
181#ifdef HAVE_DIRCACHE
182#define PLAYLIST_LOAD_POINTERS 1
183
184static struct event_queue playlist_queue;
185static long playlist_stack[(DEFAULT_STACK_SIZE + 0x400)/sizeof(long)];
186static const char playlist_thread_name[] = "playlist cachectrl";
187#endif
188
178/* 189/*
179 * remove any files and indices associated with the playlist 190 * remove any files and indices associated with the playlist
180 */ 191 */
@@ -394,11 +405,15 @@ static int add_indices_to_playlist(struct playlist_info* playlist,
394 { 405 {
395 /* Store a new entry */ 406 /* Store a new entry */
396 playlist->indices[ playlist->amount ] = i+count; 407 playlist->indices[ playlist->amount ] = i+count;
397 playlist->amount++; 408#ifdef HAVE_DIRCACHE
409 if (playlist->filenames)
410 playlist->filenames[ playlist->amount ] = NULL;
411#endif
398 if ( playlist->amount >= playlist->max_playlist_size ) { 412 if ( playlist->amount >= playlist->max_playlist_size ) {
399 display_buffer_full(); 413 display_buffer_full();
400 return -1; 414 return -1;
401 } 415 }
416 playlist->amount++;
402 } 417 }
403 } 418 }
404 } 419 }
@@ -406,6 +421,10 @@ static int add_indices_to_playlist(struct playlist_info* playlist,
406 i+= count; 421 i+= count;
407 } 422 }
408 423
424#ifdef HAVE_DIRCACHE
425 queue_post(&playlist_queue, PLAYLIST_LOAD_POINTERS, 0);
426#endif
427
409 return 0; 428 return 0;
410} 429}
411 430
@@ -499,8 +518,14 @@ static int add_track_to_playlist(struct playlist_info* playlist,
499 518
500 /* shift indices so that track can be added */ 519 /* shift indices so that track can be added */
501 for (i=playlist->amount; i>insert_position; i--) 520 for (i=playlist->amount; i>insert_position; i--)
521 {
502 playlist->indices[i] = playlist->indices[i-1]; 522 playlist->indices[i] = playlist->indices[i-1];
503 523#ifdef HAVE_DIRCACHE
524 if (playlist->filenames)
525 playlist->filenames[i] = playlist->filenames[i-1];
526#endif
527 }
528
504 /* update stored indices if needed */ 529 /* update stored indices if needed */
505 if (playlist->amount > 0 && insert_position <= playlist->index) 530 if (playlist->amount > 0 && insert_position <= playlist->index)
506 playlist->index++; 531 playlist->index++;
@@ -554,6 +579,12 @@ static int add_track_to_playlist(struct playlist_info* playlist,
554 579
555 playlist->indices[insert_position] = flags | seek_pos; 580 playlist->indices[insert_position] = flags | seek_pos;
556 581
582#ifdef HAVE_DIRCACHE
583 if (playlist->filenames)
584 playlist->filenames[insert_position] = NULL;
585 queue_post(&playlist_queue, PLAYLIST_LOAD_POINTERS, 0);
586#endif
587
557 playlist->amount++; 588 playlist->amount++;
558 playlist->num_inserted_tracks++; 589 playlist->num_inserted_tracks++;
559 590
@@ -693,7 +724,13 @@ static int remove_track_from_playlist(struct playlist_info* playlist,
693 724
694 /* shift indices now that track has been removed */ 725 /* shift indices now that track has been removed */
695 for (i=position; i<playlist->amount; i++) 726 for (i=position; i<playlist->amount; i++)
727 {
696 playlist->indices[i] = playlist->indices[i+1]; 728 playlist->indices[i] = playlist->indices[i+1];
729#ifdef HAVE_DIRCACHE
730 if (playlist->filenames)
731 playlist->filenames[i] = playlist->filenames[i+1];
732#endif
733 }
697 734
698 playlist->amount--; 735 playlist->amount--;
699 736
@@ -780,6 +817,14 @@ static int randomise_playlist(struct playlist_info* playlist,
780 store = playlist->indices[candidate]; 817 store = playlist->indices[candidate];
781 playlist->indices[candidate] = playlist->indices[count]; 818 playlist->indices[candidate] = playlist->indices[count];
782 playlist->indices[count] = store; 819 playlist->indices[count] = store;
820#ifdef HAVE_DIRCACHE
821 if (playlist->filenames)
822 {
823 store = (int)playlist->filenames[candidate];
824 playlist->filenames[candidate] = playlist->filenames[count];
825 playlist->filenames[count] = (struct dircache_entry *)store;
826 }
827#endif
783 } 828 }
784 829
785 if (start_current) 830 if (start_current)
@@ -817,6 +862,13 @@ static int sort_playlist(struct playlist_info* playlist, bool start_current,
817 qsort(playlist->indices, playlist->amount, 862 qsort(playlist->indices, playlist->amount,
818 sizeof(playlist->indices[0]), compare); 863 sizeof(playlist->indices[0]), compare);
819 864
865#ifdef HAVE_DIRCACHE
866 /** We need to re-check the song names from disk because qsort can't
867 * sort two arrays at once :/
868 * FIXME: Please implement a better way to do this. */
869 queue_post(&playlist_queue, PLAYLIST_LOAD_POINTERS, 0);
870#endif
871
820 if (start_current) 872 if (start_current)
821 find_and_set_playlist_index(playlist, current); 873 find_and_set_playlist_index(playlist, current);
822 874
@@ -1040,10 +1092,88 @@ static int compare(const void* p1, const void* p2)
1040 return *e1 - *e2; 1092 return *e1 - *e2;
1041} 1093}
1042 1094
1095#ifdef HAVE_DIRCACHE
1096/**
1097 * Thread to update filename pointers to dircache on background
1098 * without affecting playlist load up performance.
1099 */
1100static void playlist_thread(void)
1101{
1102 struct event ev;
1103 bool dirty_pointers = false;
1104 static char tmp[MAX_PATH+1];
1105
1106 struct playlist_info *playlist;
1107 int index;
1108 int seek;
1109 bool control_file;
1110
1111 while (1)
1112 {
1113 queue_wait_w_tmo(&playlist_queue, &ev, HZ*5);
1114
1115 switch (ev.id)
1116 {
1117 case PLAYLIST_LOAD_POINTERS:
1118 dirty_pointers = true;
1119 break ;
1120
1121 /* Start the background scanning after 5s. */
1122 case SYS_TIMEOUT:
1123 if (!dirty_pointers)
1124 break ;
1125
1126 playlist = &current_playlist;
1127 if (!dircache_is_enabled() || !playlist->filenames
1128 || playlist->amount <= 0)
1129 break ;
1130
1131#ifdef HAVE_ADJUSTABLE_CPU_FREQ
1132 cpu_boost(true);
1133#endif
1134 for (index = 0; index < playlist->amount
1135 && queue_empty(&playlist_queue); index++)
1136 {
1137 /* Process only pointers that are not already loaded. */
1138 if (playlist->filenames[index])
1139 continue ;
1140
1141 control_file = playlist->indices[index] & PLAYLIST_INSERT_TYPE_MASK;
1142 seek = playlist->indices[index] & PLAYLIST_SEEK_MASK;
1143
1144 /* Load the filename from playlist file. */
1145 if (get_filename(playlist, index, seek, control_file, tmp,
1146 sizeof(tmp)) < 0)
1147 break ;
1148
1149 /* Set the dircache entry pointer. */
1150 playlist->filenames[index] = dircache_get_entry_ptr(tmp);
1151
1152 /* And be on background so user doesn't notice any delays. */
1153 yield();
1154 }
1155
1156#ifdef HAVE_ADJUSTABLE_CPU_FREQ
1157 cpu_boost(false);
1158#endif
1159 dirty_pointers = false;
1160 break ;
1161
1162#ifndef SIMULATOR
1163 case SYS_USB_CONNECTED:
1164 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1165 usb_wait_for_disconnect(&playlist_queue);
1166 break ;
1167#endif
1168 }
1169 }
1170}
1171#endif
1172
1043/* 1173/*
1044 * gets pathname for track at seek index 1174 * gets pathname for track at seek index
1045 */ 1175 */
1046static int get_filename(struct playlist_info* playlist, int seek, 1176static int get_filename(struct playlist_info* playlist, int index, int seek,
1047 bool control_file, char *buf, int buf_length) 1177 bool control_file, char *buf, int buf_length)
1048{ 1178{
1049 int fd; 1179 int fd;
@@ -1054,13 +1184,26 @@ static int get_filename(struct playlist_info* playlist, int seek,
1054 if (buf_length > MAX_PATH+1) 1184 if (buf_length > MAX_PATH+1)
1055 buf_length = MAX_PATH+1; 1185 buf_length = MAX_PATH+1;
1056 1186
1057 if (playlist->in_ram && !control_file) 1187#ifdef HAVE_DIRCACHE
1188 if (dircache_is_enabled() && playlist->filenames)
1189 {
1190 if (playlist->filenames[index] != NULL)
1191 {
1192 dircache_copy_path(playlist->filenames[index], tmp_buf, sizeof(tmp_buf)-1);
1193 max = strlen(tmp_buf) + 1;
1194 }
1195 }
1196#else
1197 (void)index;
1198#endif
1199
1200 if (playlist->in_ram && !control_file && max < 0)
1058 { 1201 {
1059 strncpy(tmp_buf, &playlist->buffer[seek], sizeof(tmp_buf)); 1202 strncpy(tmp_buf, &playlist->buffer[seek], sizeof(tmp_buf));
1060 tmp_buf[MAX_PATH] = '\0'; 1203 tmp_buf[MAX_PATH] = '\0';
1061 max = strlen(tmp_buf) + 1; 1204 max = strlen(tmp_buf) + 1;
1062 } 1205 }
1063 else 1206 else if (max < 0)
1064 { 1207 {
1065 if (control_file) 1208 if (control_file)
1066 fd = playlist->control_fd; 1209 fd = playlist->control_fd;
@@ -1482,6 +1625,16 @@ void playlist_init(void)
1482 playlist->buffer = buffer_alloc(playlist->buffer_size); 1625 playlist->buffer = buffer_alloc(playlist->buffer_size);
1483 mutex_init(&playlist->control_mutex); 1626 mutex_init(&playlist->control_mutex);
1484 empty_playlist(playlist, true); 1627 empty_playlist(playlist, true);
1628
1629#ifdef HAVE_DIRCACHE
1630 playlist->filenames = buffer_alloc(
1631 playlist->max_playlist_size * sizeof(int));
1632 memset(playlist->filenames, 0,
1633 playlist->max_playlist_size * sizeof(int));
1634 create_thread(playlist_thread, playlist_stack, sizeof(playlist_stack),
1635 playlist_thread_name);
1636 queue_init(&playlist_queue);
1637#endif
1485} 1638}
1486 1639
1487/* 1640/*
@@ -1906,8 +2059,9 @@ int playlist_add(const char *filename)
1906 return -1; 2059 return -1;
1907 } 2060 }
1908 2061
1909 playlist->indices[playlist->amount++] = playlist->buffer_end_pos; 2062 playlist->indices[playlist->amount] = playlist->buffer_end_pos;
1910 2063 playlist->amount++;
2064
1911 strcpy(&playlist->buffer[playlist->buffer_end_pos], filename); 2065 strcpy(&playlist->buffer[playlist->buffer_end_pos], filename);
1912 playlist->buffer_end_pos += len; 2066 playlist->buffer_end_pos += len;
1913 playlist->buffer[playlist->buffer_end_pos++] = '\0'; 2067 playlist->buffer[playlist->buffer_end_pos++] = '\0';
@@ -1991,7 +2145,7 @@ char* playlist_peek(int steps)
1991 control_file = playlist->indices[index] & PLAYLIST_INSERT_TYPE_MASK; 2145 control_file = playlist->indices[index] & PLAYLIST_INSERT_TYPE_MASK;
1992 seek = playlist->indices[index] & PLAYLIST_SEEK_MASK; 2146 seek = playlist->indices[index] & PLAYLIST_SEEK_MASK;
1993 2147
1994 if (get_filename(playlist, seek, control_file, now_playing, 2148 if (get_filename(playlist, index, seek, control_file, now_playing,
1995 MAX_PATH+1) < 0) 2149 MAX_PATH+1) < 0)
1996 return NULL; 2150 return NULL;
1997 2151
@@ -2003,11 +2157,21 @@ char* playlist_peek(int steps)
2003 (workaround for buggy playlist creation tools) */ 2157 (workaround for buggy playlist creation tools) */
2004 while (temp_ptr) 2158 while (temp_ptr)
2005 { 2159 {
2006 fd = open(temp_ptr, O_RDONLY); 2160#ifdef HAVE_DIRCACHE
2007 if (fd >= 0) 2161 if (dircache_is_enabled())
2008 { 2162 {
2009 close(fd); 2163 if (dircache_get_entry_ptr(temp_ptr))
2010 break; 2164 break;
2165 }
2166 else
2167#endif
2168 {
2169 fd = open(temp_ptr, O_RDONLY);
2170 if (fd >= 0)
2171 {
2172 close(fd);
2173 break;
2174 }
2011 } 2175 }
2012 2176
2013 temp_ptr = strchr(temp_ptr+1, '/'); 2177 temp_ptr = strchr(temp_ptr+1, '/');
@@ -2278,16 +2442,26 @@ int playlist_create_ex(struct playlist_info* playlist,
2278 { 2442 {
2279 int num_indices = index_buffer_size / sizeof(int); 2443 int num_indices = index_buffer_size / sizeof(int);
2280 2444
2445#ifdef HAVE_DIRCACHE
2446 num_indices /= 2;
2447#endif
2281 if (num_indices > global_settings.max_files_in_playlist) 2448 if (num_indices > global_settings.max_files_in_playlist)
2282 num_indices = global_settings.max_files_in_playlist; 2449 num_indices = global_settings.max_files_in_playlist;
2283 2450
2284 playlist->max_playlist_size = num_indices; 2451 playlist->max_playlist_size = num_indices;
2285 playlist->indices = index_buffer; 2452 playlist->indices = index_buffer;
2453#ifdef HAVE_DIRCACHE
2454 playlist->filenames = (const struct dircache_entry **)
2455 &playlist->indices[num_indices];
2456#endif
2286 } 2457 }
2287 else 2458 else
2288 { 2459 {
2289 playlist->max_playlist_size = current_playlist.max_playlist_size; 2460 playlist->max_playlist_size = current_playlist.max_playlist_size;
2290 playlist->indices = current_playlist.indices; 2461 playlist->indices = current_playlist.indices;
2462#ifdef HAVE_DIRCACHE
2463 playlist->filenames = current_playlist.filenames;
2464#endif
2291 } 2465 }
2292 2466
2293 playlist->buffer_size = 0; 2467 playlist->buffer_size = 0;
@@ -2336,9 +2510,15 @@ int playlist_set_current(struct playlist_info* playlist)
2336 current_playlist.dirlen = playlist->dirlen; 2510 current_playlist.dirlen = playlist->dirlen;
2337 2511
2338 if (playlist->indices && playlist->indices != current_playlist.indices) 2512 if (playlist->indices && playlist->indices != current_playlist.indices)
2513 {
2339 memcpy(current_playlist.indices, playlist->indices, 2514 memcpy(current_playlist.indices, playlist->indices,
2340 playlist->max_playlist_size*sizeof(int)); 2515 playlist->max_playlist_size*sizeof(int));
2341 2516#ifdef HAVE_DIRCACHE
2517 memcpy(current_playlist.filenames, playlist->filenames,
2518 playlist->max_playlist_size*sizeof(int));
2519#endif
2520 }
2521
2342 current_playlist.first_index = playlist->first_index; 2522 current_playlist.first_index = playlist->first_index;
2343 current_playlist.amount = playlist->amount; 2523 current_playlist.amount = playlist->amount;
2344 current_playlist.last_insert_pos = playlist->last_insert_pos; 2524 current_playlist.last_insert_pos = playlist->last_insert_pos;
@@ -2620,7 +2800,7 @@ int playlist_move(struct playlist_info* playlist, int index, int new_index)
2620 queue = playlist->indices[index] & PLAYLIST_QUEUE_MASK; 2800 queue = playlist->indices[index] & PLAYLIST_QUEUE_MASK;
2621 seek = playlist->indices[index] & PLAYLIST_SEEK_MASK; 2801 seek = playlist->indices[index] & PLAYLIST_SEEK_MASK;
2622 2802
2623 if (get_filename(playlist, seek, control_file, filename, 2803 if (get_filename(playlist, index, seek, control_file, filename,
2624 sizeof(filename)) < 0) 2804 sizeof(filename)) < 0)
2625 return -1; 2805 return -1;
2626 2806
@@ -2812,7 +2992,7 @@ int playlist_get_track_info(struct playlist_info* playlist, int index,
2812 control_file = playlist->indices[index] & PLAYLIST_INSERT_TYPE_MASK; 2992 control_file = playlist->indices[index] & PLAYLIST_INSERT_TYPE_MASK;
2813 seek = playlist->indices[index] & PLAYLIST_SEEK_MASK; 2993 seek = playlist->indices[index] & PLAYLIST_SEEK_MASK;
2814 2994
2815 if (get_filename(playlist, seek, control_file, info->filename, 2995 if (get_filename(playlist, index, seek, control_file, info->filename,
2816 sizeof(info->filename)) < 0) 2996 sizeof(info->filename)) < 0)
2817 return -1; 2997 return -1;
2818 2998
@@ -2883,7 +3063,7 @@ int playlist_save(struct playlist_info* playlist, char *filename)
2883 /* Don't save queued files */ 3063 /* Don't save queued files */
2884 if (!queue) 3064 if (!queue)
2885 { 3065 {
2886 if (get_filename(playlist, seek, control_file, tmp_buf, 3066 if (get_filename(playlist, index, seek, control_file, tmp_buf,
2887 MAX_PATH+1) < 0) 3067 MAX_PATH+1) < 0)
2888 { 3068 {
2889 result = -1; 3069 result = -1;
diff --git a/apps/playlist.h b/apps/playlist.h
index efac303f30..286823e0cf 100644
--- a/apps/playlist.h
+++ b/apps/playlist.h
@@ -36,7 +36,8 @@ struct playlist_info
36 int control_fd; /* descriptor of the open control file */ 36 int control_fd; /* descriptor of the open control file */
37 bool control_created; /* has control file been created? */ 37 bool control_created; /* has control file been created? */
38 int dirlen; /* Length of the path to the playlist file */ 38 int dirlen; /* Length of the path to the playlist file */
39 unsigned long *indices; /* array of indices */ 39 unsigned long *indices; /* array of indices */
40 const struct dircache_entry **filenames; /* Entries from dircache */
40 int max_playlist_size; /* Max number of files in playlist. Mirror of 41 int max_playlist_size; /* Max number of files in playlist. Mirror of
41 global_settings.max_files_in_playlist */ 42 global_settings.max_files_in_playlist */
42 bool in_ram; /* playlist stored in ram (dirplay) */ 43 bool in_ram; /* playlist stored in ram (dirplay) */
diff --git a/apps/wps.c b/apps/wps.c
index 266c506d37..573444fdc4 100644
--- a/apps/wps.c
+++ b/apps/wps.c
@@ -597,6 +597,7 @@ long wps_show(void)
597#endif 597#endif
598#endif 598#endif
599 left_lastclick = current_tick; 599 left_lastclick = current_tick;
600 update_track = true;
600 601
601#ifdef AB_REPEAT_ENABLE 602#ifdef AB_REPEAT_ENABLE
602 /* if we're in A/B repeat mode and the current position 603 /* if we're in A/B repeat mode and the current position
@@ -604,7 +605,6 @@ long wps_show(void)
604 if ( ab_repeat_mode_enabled() && ab_after_A_marker(id3->elapsed) ) 605 if ( ab_repeat_mode_enabled() && ab_after_A_marker(id3->elapsed) )
605 { 606 {
606 ab_jump_to_A_marker(); 607 ab_jump_to_A_marker();
607 update_track = true;
608 break; 608 break;
609 } 609 }
610 /* ...otherwise, do it normally */ 610 /* ...otherwise, do it normally */
@@ -655,6 +655,7 @@ long wps_show(void)
655#endif 655#endif
656#endif 656#endif
657 right_lastclick = current_tick; 657 right_lastclick = current_tick;
658 update_track = true;
658 659
659#ifdef AB_REPEAT_ENABLE 660#ifdef AB_REPEAT_ENABLE
660 /* if we're in A/B repeat mode and the current position is 661 /* if we're in A/B repeat mode and the current position is
@@ -662,7 +663,6 @@ long wps_show(void)
662 if ( ab_repeat_mode_enabled() && ab_before_A_marker(id3->elapsed) ) 663 if ( ab_repeat_mode_enabled() && ab_before_A_marker(id3->elapsed) )
663 { 664 {
664 ab_jump_to_A_marker(); 665 ab_jump_to_A_marker();
665 update_track = true;
666 break; 666 break;
667 } 667 }
668 /* ...otherwise, do it normally */ 668 /* ...otherwise, do it normally */