diff options
Diffstat (limited to 'apps/playback.c')
-rw-r--r-- | apps/playback.c | 76 |
1 files changed, 67 insertions, 9 deletions
diff --git a/apps/playback.c b/apps/playback.c index e35d652ffb..af077e639a 100644 --- a/apps/playback.c +++ b/apps/playback.c | |||
@@ -732,8 +732,6 @@ static void scratch_mem_init(void *mem) | |||
732 | } | 732 | } |
733 | } | 733 | } |
734 | 734 | ||
735 | /* Buffer must not move. And not shrink for now */ | ||
736 | static struct buflib_callbacks ops = { NULL, NULL }; | ||
737 | static int audiobuf_handle; | 735 | static int audiobuf_handle; |
738 | static size_t filebuflen; | 736 | static size_t filebuflen; |
739 | 737 | ||
@@ -744,8 +742,9 @@ size_t audio_buffer_available(void) | |||
744 | return core_available(); | 742 | return core_available(); |
745 | } | 743 | } |
746 | 744 | ||
747 | /* Set up the audio buffer for playback */ | 745 | /* Set up the audio buffer for playback |
748 | static void audio_reset_buffer(void) | 746 | * filebuflen must be pre-initialized with the maximum size */ |
747 | static void audio_reset_buffer_noalloc(void* filebuf) | ||
749 | { | 748 | { |
750 | /* | 749 | /* |
751 | * Layout audio buffer as follows: | 750 | * Layout audio buffer as follows: |
@@ -761,11 +760,6 @@ static void audio_reset_buffer(void) | |||
761 | 760 | ||
762 | /* Initially set up file buffer as all space available */ | 761 | /* Initially set up file buffer as all space available */ |
763 | size_t allocsize; | 762 | size_t allocsize; |
764 | if (audiobuf_handle > 0) | ||
765 | audiobuf_handle = core_free(audiobuf_handle); | ||
766 | |||
767 | audiobuf_handle = core_alloc_maximum("audiobuf", &filebuflen, &ops); | ||
768 | unsigned char *filebuf = core_get_data(audiobuf_handle); | ||
769 | 763 | ||
770 | /* Subtract whatever voice needs */ | 764 | /* Subtract whatever voice needs */ |
771 | allocsize = talkbuf_init(filebuf); | 765 | allocsize = talkbuf_init(filebuf); |
@@ -830,6 +824,70 @@ bufpanic: | |||
830 | panicf("%s(): EOM (%zu > %zu)", __func__, allocsize, filebuflen); | 824 | panicf("%s(): EOM (%zu > %zu)", __func__, allocsize, filebuflen); |
831 | } | 825 | } |
832 | 826 | ||
827 | |||
828 | /* Buffer must not move. */ | ||
829 | static int shrink_callback(int handle, unsigned hints, void* start, size_t old_size) | ||
830 | { | ||
831 | long offset = audio_current_track()->offset; | ||
832 | int status = audio_status(); | ||
833 | /* TODO: Do it without stopping playback, if possible */ | ||
834 | /* don't call audio_hard_stop() as it frees this handle */ | ||
835 | if (thread_self() == audio_thread_id) | ||
836 | { /* inline case Q_AUDIO_STOP (audio_hard_stop() response | ||
837 | * if we're in the audio thread */ | ||
838 | audio_stop_playback(); | ||
839 | queue_clear(&audio_queue); | ||
840 | } | ||
841 | else | ||
842 | audio_queue_send(Q_AUDIO_STOP, 1); | ||
843 | #ifdef PLAYBACK_VOICE | ||
844 | voice_stop(); | ||
845 | #endif | ||
846 | /* we should be free to change the buffer now */ | ||
847 | size_t wanted_size = (hints & BUFLIB_SHRINK_SIZE_MASK); | ||
848 | ssize_t size = (ssize_t)old_size - wanted_size; | ||
849 | /* set final buffer size before calling audio_reset_buffer_noalloc() */ | ||
850 | filebuflen = size; | ||
851 | switch (hints & BUFLIB_SHRINK_POS_MASK) | ||
852 | { | ||
853 | case BUFLIB_SHRINK_POS_BACK: | ||
854 | core_shrink(handle, start, size); | ||
855 | audio_reset_buffer_noalloc(start); | ||
856 | break; | ||
857 | case BUFLIB_SHRINK_POS_FRONT: | ||
858 | core_shrink(handle, start + wanted_size, size); | ||
859 | audio_reset_buffer_noalloc(start + wanted_size); | ||
860 | break; | ||
861 | } | ||
862 | if ((status & AUDIO_STATUS_PLAY) == AUDIO_STATUS_PLAY) | ||
863 | { | ||
864 | if (thread_self() == audio_thread_id) | ||
865 | audio_start_playback(offset, 0); /* inline Q_AUDIO_PLAY */ | ||
866 | else | ||
867 | audio_play(offset); | ||
868 | } | ||
869 | |||
870 | return BUFLIB_CB_OK; | ||
871 | } | ||
872 | |||
873 | static struct buflib_callbacks ops = { | ||
874 | .move_callback = NULL, | ||
875 | .shrink_callback = shrink_callback, | ||
876 | }; | ||
877 | |||
878 | static void audio_reset_buffer(void) | ||
879 | { | ||
880 | if (audiobuf_handle > 0) | ||
881 | { | ||
882 | core_free(audiobuf_handle); | ||
883 | audiobuf_handle = 0; | ||
884 | } | ||
885 | audiobuf_handle = core_alloc_maximum("audiobuf", &filebuflen, &ops); | ||
886 | unsigned char *filebuf = core_get_data(audiobuf_handle); | ||
887 | |||
888 | audio_reset_buffer_noalloc(filebuf); | ||
889 | } | ||
890 | |||
833 | /* Set the buffer margin to begin rebuffering when 'seconds' from empty */ | 891 | /* Set the buffer margin to begin rebuffering when 'seconds' from empty */ |
834 | static void audio_update_filebuf_watermark(int seconds) | 892 | static void audio_update_filebuf_watermark(int seconds) |
835 | { | 893 | { |