diff options
author | Miika Pekkarinen <miipekk@ihme.org> | 2005-11-17 19:31:29 +0000 |
---|---|---|
committer | Miika Pekkarinen <miipekk@ihme.org> | 2005-11-17 19:31:29 +0000 |
commit | 735f4537309d4a66e16dd020fa99149a9d5f8d29 (patch) | |
tree | 7326f1f8f45f43c40bc78b86e4809087dffa9aa7 /apps/playback.c | |
parent | bc8a4e4b8cb613b7a0e4f348fe81086f92d9a994 (diff) | |
download | rockbox-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/playback.c')
-rw-r--r-- | apps/playback.c | 137 |
1 files changed, 83 insertions, 54 deletions
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. */ |
166 | static int last_peek_offset; | 166 | static int last_peek_offset; |
167 | 167 | ||
168 | /* Index of the last buffered track. */ | ||
169 | static 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. */ |
173 | int track_count; | 170 | int 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 | ||
1462 | static void audio_stop_playback(void) | 1456 | static 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) | |||
1677 | void audio_thread(void) | 1657 | void 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 | ||
1974 | struct mp3entry* audio_current_track(void) | 1966 | struct 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 | ||
1984 | struct mp3entry* audio_next_track(void) | 1992 | struct 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 | ||
2002 | bool audio_has_changed_track(void) | 2008 | bool 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) | |||
2014 | void audio_play(int offset) | 2018 | void 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 | ||
2044 | void audio_next(void) | 2047 | void 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 | ||
2049 | void audio_prev(void) | 2065 | void 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 | ||