diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/playback.c | 45 |
1 files changed, 29 insertions, 16 deletions
diff --git a/apps/playback.c b/apps/playback.c index 13d2bd6b02..1f1852b959 100644 --- a/apps/playback.c +++ b/apps/playback.c | |||
@@ -164,6 +164,7 @@ static bool audio_is_initialized = false; | |||
164 | /* Variables are commented with the threads that use them: * | 164 | /* Variables are commented with the threads that use them: * |
165 | * A=audio, C=codec, V=voice. A suffix of - indicates that * | 165 | * A=audio, C=codec, V=voice. A suffix of - indicates that * |
166 | * the variable is read but not updated on that thread. */ | 166 | * the variable is read but not updated on that thread. */ |
167 | /* TBD: Split out "audio" and "calling" threads */ | ||
167 | 168 | ||
168 | /* Main state control */ | 169 | /* Main state control */ |
169 | static struct event_queue codec_callback_queue; /* Queue for codec callback responses */ | 170 | static struct event_queue codec_callback_queue; /* Queue for codec callback responses */ |
@@ -205,6 +206,7 @@ static bool playlist_end = false; /* Have we reached end of the cu | |||
205 | static bool dir_skip = false; /* Is a directory skip pending? (A) */ | 206 | static bool dir_skip = false; /* Is a directory skip pending? (A) */ |
206 | static bool new_playlist = false; /* Are we starting a new playlist? (A) */ | 207 | static bool new_playlist = false; /* Are we starting a new playlist? (A) */ |
207 | static int wps_offset = 0; /* Pending track change offset, to keep WPS responsive (A) */ | 208 | static int wps_offset = 0; /* Pending track change offset, to keep WPS responsive (A) */ |
209 | static bool quick_restart = false; /* Are we doing a quick restart for buffer resizing? (A) */ | ||
208 | 210 | ||
209 | /* Callbacks.. */ | 211 | /* Callbacks.. */ |
210 | void (*track_changed_callback)(struct mp3entry *id3); /* ...when current track has really changed */ | 212 | void (*track_changed_callback)(struct mp3entry *id3); /* ...when current track has really changed */ |
@@ -612,6 +614,7 @@ void audio_set_crossfade(int enable) | |||
612 | enable = 0; | 614 | enable = 0; |
613 | size = NATIVE_FREQUENCY*2; | 615 | size = NATIVE_FREQUENCY*2; |
614 | #endif | 616 | #endif |
617 | logf("%ld->%ld", (long) pcmbuf_get_bufsize(), (long) size); | ||
615 | if (pcmbuf_get_bufsize() == size) | 618 | if (pcmbuf_get_bufsize() == size) |
616 | return ; | 619 | return ; |
617 | 620 | ||
@@ -622,10 +625,8 @@ void audio_set_crossfade(int enable) | |||
622 | 625 | ||
623 | /* Playback has to be stopped before changing the buffer size. */ | 626 | /* Playback has to be stopped before changing the buffer size. */ |
624 | gui_syncsplash(0, true, (char *)str(LANG_RESTARTING_PLAYBACK)); | 627 | gui_syncsplash(0, true, (char *)str(LANG_RESTARTING_PLAYBACK)); |
625 | LOGFQUEUE("audio > audio Q_AUDIO_STOP"); | 628 | quick_restart = true; |
626 | queue_post(&audio_queue, Q_AUDIO_STOP, 0); | 629 | audio_stop(); |
627 | while (audio_codec_loaded) | ||
628 | yield(); | ||
629 | } | 630 | } |
630 | 631 | ||
631 | voice_stop(); | 632 | voice_stop(); |
@@ -642,13 +643,8 @@ void audio_set_crossfade(int enable) | |||
642 | /* Restart playback. */ | 643 | /* Restart playback. */ |
643 | if (was_playing) | 644 | if (was_playing) |
644 | { | 645 | { |
645 | LOGFQUEUE("audio > audio Q_AUDIO_PLAY"); | 646 | audio_play(offset); |
646 | queue_post(&audio_queue, Q_AUDIO_PLAY, (void *)offset); | 647 | quick_restart = false; |
647 | |||
648 | /* Wait for the playback to start again (and display the splash | ||
649 | screen during that period. */ | ||
650 | while (!playing) | ||
651 | yield(); | ||
652 | } | 648 | } |
653 | } | 649 | } |
654 | 650 | ||
@@ -674,7 +670,9 @@ void audio_preinit(void) | |||
674 | track_ridx = 0; /* Just to prevent CUR_TI from being anything random. */ | 670 | track_ridx = 0; /* Just to prevent CUR_TI from being anything random. */ |
675 | prev_ti = &tracks[MAX_TRACK-1]; /* And prevent prev_ti being random too */ | 671 | prev_ti = &tracks[MAX_TRACK-1]; /* And prevent prev_ti being random too */ |
676 | 672 | ||
673 | #ifdef PLAYBACK_VOICE | ||
677 | mutex_init(&mutex_codecthread); | 674 | mutex_init(&mutex_codecthread); |
675 | #endif | ||
678 | 676 | ||
679 | queue_init(&audio_queue, true); | 677 | queue_init(&audio_queue, true); |
680 | queue_init(&codec_queue, true); | 678 | queue_init(&codec_queue, true); |
@@ -954,9 +952,11 @@ static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize) | |||
954 | case Q_VOICE_STOP: | 952 | case Q_VOICE_STOP: |
955 | LOGFQUEUE("voice < Q_VOICE_STOP"); | 953 | LOGFQUEUE("voice < Q_VOICE_STOP"); |
956 | if (ev.data == (void *)1 && !playing && pcm_is_playing()) | 954 | if (ev.data == (void *)1 && !playing && pcm_is_playing()) |
955 | { | ||
957 | /* Aborting: Slight hack - flush PCM buffer if | 956 | /* Aborting: Slight hack - flush PCM buffer if |
958 | only being used for voice */ | 957 | only being used for voice */ |
959 | pcmbuf_play_stop(); | 958 | pcmbuf_play_stop(); |
959 | } | ||
960 | if (voice_is_playing) | 960 | if (voice_is_playing) |
961 | { | 961 | { |
962 | /* Clear the current buffer */ | 962 | /* Clear the current buffer */ |
@@ -1732,12 +1732,14 @@ static void codec_thread(void) | |||
1732 | LOGFQUEUE("codec > voice Q_AUDIO_PLAY"); | 1732 | LOGFQUEUE("codec > voice Q_AUDIO_PLAY"); |
1733 | queue_post(&voice_queue, Q_AUDIO_PLAY, 0); | 1733 | queue_post(&voice_queue, Q_AUDIO_PLAY, 0); |
1734 | } | 1734 | } |
1735 | #endif | ||
1736 | mutex_lock(&mutex_codecthread); | 1735 | mutex_lock(&mutex_codecthread); |
1736 | #endif | ||
1737 | current_codec = CODEC_IDX_AUDIO; | 1737 | current_codec = CODEC_IDX_AUDIO; |
1738 | ci.stop_codec = false; | 1738 | ci.stop_codec = false; |
1739 | status = codec_load_file((const char *)ev.data, &ci); | 1739 | status = codec_load_file((const char *)ev.data, &ci); |
1740 | #ifdef PLAYBACK_VOICE | ||
1740 | mutex_unlock(&mutex_codecthread); | 1741 | mutex_unlock(&mutex_codecthread); |
1742 | #endif | ||
1741 | break ; | 1743 | break ; |
1742 | 1744 | ||
1743 | case Q_CODEC_LOAD: | 1745 | case Q_CODEC_LOAD: |
@@ -1761,14 +1763,16 @@ static void codec_thread(void) | |||
1761 | LOGFQUEUE("codec > voice Q_AUDIO_PLAY"); | 1763 | LOGFQUEUE("codec > voice Q_AUDIO_PLAY"); |
1762 | queue_post(&voice_queue, Q_AUDIO_PLAY, 0); | 1764 | queue_post(&voice_queue, Q_AUDIO_PLAY, 0); |
1763 | } | 1765 | } |
1764 | #endif | ||
1765 | mutex_lock(&mutex_codecthread); | 1766 | mutex_lock(&mutex_codecthread); |
1767 | #endif | ||
1766 | current_codec = CODEC_IDX_AUDIO; | 1768 | current_codec = CODEC_IDX_AUDIO; |
1767 | ci.stop_codec = false; | 1769 | ci.stop_codec = false; |
1768 | wrap = (size_t)&filebuf[filebuflen] - (size_t)CUR_TI->codecbuf; | 1770 | wrap = (size_t)&filebuf[filebuflen] - (size_t)CUR_TI->codecbuf; |
1769 | status = codec_load_ram(CUR_TI->codecbuf, CUR_TI->codecsize, | 1771 | status = codec_load_ram(CUR_TI->codecbuf, CUR_TI->codecsize, |
1770 | &filebuf[0], wrap, &ci); | 1772 | &filebuf[0], wrap, &ci); |
1773 | #ifdef PLAYBACK_VOICE | ||
1771 | mutex_unlock(&mutex_codecthread); | 1774 | mutex_unlock(&mutex_codecthread); |
1775 | #endif | ||
1772 | break ; | 1776 | break ; |
1773 | 1777 | ||
1774 | #if defined(HAVE_RECORDING) && !defined(SIMULATOR) | 1778 | #if defined(HAVE_RECORDING) && !defined(SIMULATOR) |
@@ -1810,6 +1814,7 @@ static void codec_thread(void) | |||
1810 | status = CODEC_OK; | 1814 | status = CODEC_OK; |
1811 | if (!playing) | 1815 | if (!playing) |
1812 | pcmbuf_play_stop(); | 1816 | pcmbuf_play_stop(); |
1817 | |||
1813 | } | 1818 | } |
1814 | audio_codec_loaded = false; | 1819 | audio_codec_loaded = false; |
1815 | } | 1820 | } |
@@ -1848,8 +1853,11 @@ static void codec_thread(void) | |||
1848 | CUR_TI->id3.elapsed = CUR_TI->id3.length - pcmbuf_get_latency(); | 1853 | CUR_TI->id3.elapsed = CUR_TI->id3.length - pcmbuf_get_latency(); |
1849 | sleep(1); | 1854 | sleep(1); |
1850 | } | 1855 | } |
1851 | LOGFQUEUE("codec > audio Q_AUDIO_STOP"); | 1856 | if (!quick_restart) |
1852 | queue_post(&audio_queue, Q_AUDIO_STOP, 0); | 1857 | { |
1858 | LOGFQUEUE("codec > audio Q_AUDIO_STOP"); | ||
1859 | queue_post(&audio_queue, Q_AUDIO_STOP, 0); | ||
1860 | } | ||
1853 | break; | 1861 | break; |
1854 | } | 1862 | } |
1855 | } | 1863 | } |
@@ -2983,7 +2991,6 @@ static void audio_stop_playback(void) | |||
2983 | 2991 | ||
2984 | /* Mark all entries null. */ | 2992 | /* Mark all entries null. */ |
2985 | audio_clear_track_entries(false); | 2993 | audio_clear_track_entries(false); |
2986 | memset(tracks, 0, sizeof(struct track_info) * MAX_TRACK); | ||
2987 | } | 2994 | } |
2988 | 2995 | ||
2989 | static void audio_play_start(size_t offset) | 2996 | static void audio_play_start(size_t offset) |
@@ -3102,20 +3109,24 @@ static void audio_reset_buffer(void) | |||
3102 | /* Allow 2 codecs at end of file buffer */ | 3109 | /* Allow 2 codecs at end of file buffer */ |
3103 | filebuflen -= 2 * (CODEC_IRAM_SIZE + CODEC_SIZE); | 3110 | filebuflen -= 2 * (CODEC_IRAM_SIZE + CODEC_SIZE); |
3104 | 3111 | ||
3112 | #ifdef PLAYBACK_VOICE | ||
3105 | iram_buf[0] = &filebuf[filebuflen]; | 3113 | iram_buf[0] = &filebuf[filebuflen]; |
3106 | iram_buf[1] = &filebuf[filebuflen+CODEC_IRAM_SIZE]; | 3114 | iram_buf[1] = &filebuf[filebuflen+CODEC_IRAM_SIZE]; |
3107 | dram_buf[0] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE*2]; | 3115 | dram_buf[0] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE*2]; |
3108 | dram_buf[1] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE*2+CODEC_SIZE]; | 3116 | dram_buf[1] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE*2+CODEC_SIZE]; |
3117 | #endif | ||
3109 | } | 3118 | } |
3110 | else | 3119 | else |
3111 | { | 3120 | { |
3112 | /* Allow for 1 codec at end of file buffer */ | 3121 | /* Allow for 1 codec at end of file buffer */ |
3113 | filebuflen -= CODEC_IRAM_SIZE + CODEC_SIZE; | 3122 | filebuflen -= CODEC_IRAM_SIZE + CODEC_SIZE; |
3114 | 3123 | ||
3124 | #ifdef PLAYBACK_VOICE | ||
3115 | iram_buf[0] = &filebuf[filebuflen]; | 3125 | iram_buf[0] = &filebuf[filebuflen]; |
3116 | iram_buf[1] = NULL; | 3126 | iram_buf[1] = NULL; |
3117 | dram_buf[0] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE]; | 3127 | dram_buf[0] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE]; |
3118 | dram_buf[1] = NULL; | 3128 | dram_buf[1] = NULL; |
3129 | #endif | ||
3119 | } | 3130 | } |
3120 | 3131 | ||
3121 | /* Ensure that file buffer is aligned */ | 3132 | /* Ensure that file buffer is aligned */ |
@@ -3123,6 +3134,8 @@ static void audio_reset_buffer(void) | |||
3123 | filebuf += offset; | 3134 | filebuf += offset; |
3124 | filebuflen -= offset; | 3135 | filebuflen -= offset; |
3125 | filebuflen &= ~3; | 3136 | filebuflen &= ~3; |
3137 | |||
3138 | /* Clear any references to the file buffer */ | ||
3126 | } | 3139 | } |
3127 | 3140 | ||
3128 | 3141 | ||