diff options
Diffstat (limited to 'apps/mpeg.c')
-rw-r--r-- | apps/mpeg.c | 72 |
1 files changed, 23 insertions, 49 deletions
diff --git a/apps/mpeg.c b/apps/mpeg.c index 2783a24085..5fd1bfdb82 100644 --- a/apps/mpeg.c +++ b/apps/mpeg.c | |||
@@ -527,7 +527,13 @@ static int shrink_callback(int handle, unsigned hints, void* start, size_t old_s | |||
527 | ssize_t size = (ssize_t)old_size - wanted_size; | 527 | ssize_t size = (ssize_t)old_size - wanted_size; |
528 | /* keep at least 256K for the buffering */ | 528 | /* keep at least 256K for the buffering */ |
529 | if ((size - extradata_size) < AUDIO_BUFFER_RESERVE) | 529 | if ((size - extradata_size) < AUDIO_BUFFER_RESERVE) |
530 | return BUFLIB_CB_CANNOT_SHRINK; | 530 | { |
531 | /* check if buflib needs the memory really hard. if yes we give | ||
532 | * up playback for now, otherwise refuse to shrink to keep at least | ||
533 | * 256K for the buffering */ | ||
534 | if ((hints & BUFLIB_SHRINK_POS_MASK) != BUFLIB_SHRINK_POS_MASK) | ||
535 | return BUFLIB_CB_CANNOT_SHRINK; | ||
536 | } | ||
531 | /* TODO: Do it without stopping playback, if possible */ | 537 | /* TODO: Do it without stopping playback, if possible */ |
532 | bool playing = (audio_status() & AUDIO_STATUS_PLAY) == AUDIO_STATUS_PLAY; | 538 | bool playing = (audio_status() & AUDIO_STATUS_PLAY) == AUDIO_STATUS_PLAY; |
533 | long offset = audio_current_track()->offset; | 539 | long offset = audio_current_track()->offset; |
@@ -539,7 +545,6 @@ static int shrink_callback(int handle, unsigned hints, void* start, size_t old_s | |||
539 | } | 545 | } |
540 | else | 546 | else |
541 | audio_stop(); | 547 | audio_stop(); |
542 | talk_buffer_steal(); /* we obtain control over the buffer */ | ||
543 | 548 | ||
544 | switch (hints & BUFLIB_SHRINK_POS_MASK) | 549 | switch (hints & BUFLIB_SHRINK_POS_MASK) |
545 | { | 550 | { |
@@ -551,6 +556,12 @@ static int shrink_callback(int handle, unsigned hints, void* start, size_t old_s | |||
551 | core_shrink(handle, start + wanted_size, size); | 556 | core_shrink(handle, start + wanted_size, size); |
552 | audio_reset_buffer_noalloc(start + wanted_size, size); | 557 | audio_reset_buffer_noalloc(start + wanted_size, size); |
553 | break; | 558 | break; |
559 | case BUFLIB_SHRINK_POS_MASK: | ||
560 | audiobuf_handle = core_free(audiobuf_handle); | ||
561 | mpeg_audiobuf = NULL; | ||
562 | talk_buffer_set_policy(TALK_BUFFER_DEFAULT); | ||
563 | playing = false; | ||
564 | break; | ||
554 | } | 565 | } |
555 | if (playing) | 566 | if (playing) |
556 | { /* safe to call even from the audio thread (due to queue_post()) */ | 567 | { /* safe to call even from the audio thread (due to queue_post()) */ |
@@ -565,45 +576,6 @@ static struct buflib_callbacks ops = { | |||
565 | .shrink_callback = shrink_callback, | 576 | .shrink_callback = shrink_callback, |
566 | }; | 577 | }; |
567 | 578 | ||
568 | static size_t audio_talkbuf_init(char *bufstart) | ||
569 | { | ||
570 | size_t ret = talkbuf_init(bufstart); | ||
571 | if (ret > (size_t)audiobuflen) /* does the voice even fit? */ | ||
572 | { | ||
573 | talk_buffer_steal(); | ||
574 | return 0; | ||
575 | } | ||
576 | return ret; | ||
577 | } | ||
578 | |||
579 | unsigned char * audio_get_buffer(bool talk_buf, size_t *buffer_size) | ||
580 | { | ||
581 | (void)talk_buf; /* always grab the voice buffer for now */ | ||
582 | |||
583 | if (audio_is_initialized) | ||
584 | audio_hard_stop(); | ||
585 | |||
586 | if (!buffer_size) /* special case for talk_init() */ | ||
587 | return NULL; | ||
588 | |||
589 | if (!audiobuf_handle) | ||
590 | { | ||
591 | size_t bufsize; | ||
592 | /* audio_hard_stop() frees audiobuf, so re-aquire */ | ||
593 | audiobuf_handle = core_alloc_maximum("audiobuf", &bufsize, &ops); | ||
594 | audiobuflen = bufsize; | ||
595 | if (buffer_size) | ||
596 | *buffer_size = audiobuflen; | ||
597 | } | ||
598 | mpeg_audiobuf = core_get_data(audiobuf_handle); | ||
599 | /* tell talk about the new buffer, don't re-enable just yet because the | ||
600 | * buffer is stolen */ | ||
601 | audio_talkbuf_init(mpeg_audiobuf); | ||
602 | |||
603 | return mpeg_audiobuf; | ||
604 | } | ||
605 | |||
606 | |||
607 | #ifndef SIMULATOR | 579 | #ifndef SIMULATOR |
608 | /* Send callback events to notify about removing old tracks. */ | 580 | /* Send callback events to notify about removing old tracks. */ |
609 | static void generate_unbuffer_events(void) | 581 | static void generate_unbuffer_events(void) |
@@ -2755,7 +2727,6 @@ size_t audio_buffer_available(void) | |||
2755 | 2727 | ||
2756 | static void audio_reset_buffer_noalloc(void* buf, size_t bufsize) | 2728 | static void audio_reset_buffer_noalloc(void* buf, size_t bufsize) |
2757 | { | 2729 | { |
2758 | talk_buffer_steal(); /* will use the mp3 buffer */ | ||
2759 | mpeg_audiobuf = buf; | 2730 | mpeg_audiobuf = buf; |
2760 | audiobuflen = bufsize; | 2731 | audiobuflen = bufsize; |
2761 | if (global_settings.cuesheet) | 2732 | if (global_settings.cuesheet) |
@@ -2764,16 +2735,20 @@ static void audio_reset_buffer_noalloc(void* buf, size_t bufsize) | |||
2764 | mpeg_audiobuf = SKIPBYTES(mpeg_audiobuf, sizeof(struct cuesheet)); | 2735 | mpeg_audiobuf = SKIPBYTES(mpeg_audiobuf, sizeof(struct cuesheet)); |
2765 | audiobuflen -= sizeof(struct cuesheet); | 2736 | audiobuflen -= sizeof(struct cuesheet); |
2766 | } | 2737 | } |
2767 | audio_talkbuf_init(mpeg_audiobuf); | ||
2768 | } | 2738 | } |
2769 | 2739 | ||
2770 | static void audio_reset_buffer(void) | 2740 | static void audio_reset_buffer(void) |
2771 | { | 2741 | { |
2772 | size_t bufsize = audiobuflen; | 2742 | size_t bufsize = audiobuflen; |
2773 | 2743 | ||
2774 | /* alloc buffer if it's was never allocated or freed by audio_hard_stop() */ | 2744 | /* alloc buffer if it's was never allocated or freed by audio_hard_stop() |
2745 | * because voice cannot be played during audio playback make | ||
2746 | * talk.c give up all buffers and disable itself */ | ||
2775 | if (!audiobuf_handle) | 2747 | if (!audiobuf_handle) |
2748 | { | ||
2749 | talk_buffer_set_policy(TALK_BUFFER_LOOSE); | ||
2776 | audiobuf_handle = core_alloc_maximum("audiobuf", &bufsize, &ops); | 2750 | audiobuf_handle = core_alloc_maximum("audiobuf", &bufsize, &ops); |
2751 | } | ||
2777 | 2752 | ||
2778 | audio_reset_buffer_noalloc(core_get_data(audiobuf_handle), bufsize); | 2753 | audio_reset_buffer_noalloc(core_get_data(audiobuf_handle), bufsize); |
2779 | } | 2754 | } |
@@ -2818,6 +2793,8 @@ void audio_play(long offset) | |||
2818 | 2793 | ||
2819 | void audio_stop(void) | 2794 | void audio_stop(void) |
2820 | { | 2795 | { |
2796 | if (audiobuf_handle <= 0) | ||
2797 | return; /* nothing to do, must be hard-stopped already */ | ||
2821 | #ifndef SIMULATOR | 2798 | #ifndef SIMULATOR |
2822 | mpeg_stop_done = false; | 2799 | mpeg_stop_done = false; |
2823 | queue_post(&mpeg_queue, MPEG_STOP, 0); | 2800 | queue_post(&mpeg_queue, MPEG_STOP, 0); |
@@ -2828,8 +2805,6 @@ void audio_stop(void) | |||
2828 | is_playing = false; | 2805 | is_playing = false; |
2829 | playing = false; | 2806 | playing = false; |
2830 | #endif /* SIMULATOR */ | 2807 | #endif /* SIMULATOR */ |
2831 | /* give voice our entire buffer */ | ||
2832 | audio_talkbuf_init(mpeg_audiobuf); | ||
2833 | } | 2808 | } |
2834 | 2809 | ||
2835 | /* dummy */ | 2810 | /* dummy */ |
@@ -2840,13 +2815,12 @@ void audio_stop_recording(void) | |||
2840 | 2815 | ||
2841 | void audio_hard_stop(void) | 2816 | void audio_hard_stop(void) |
2842 | { | 2817 | { |
2843 | audio_stop(); | ||
2844 | /* tell voice we obtain the buffer before freeing */ | ||
2845 | talk_buffer_steal(); | ||
2846 | if (audiobuf_handle > 0) | 2818 | if (audiobuf_handle > 0) |
2847 | { | 2819 | { |
2820 | audio_stop(); | ||
2848 | audiobuf_handle = core_free(audiobuf_handle); | 2821 | audiobuf_handle = core_free(audiobuf_handle); |
2849 | mpeg_audiobuf = NULL; | 2822 | mpeg_audiobuf = NULL; |
2823 | talk_buffer_set_policy(TALK_BUFFER_DEFAULT); | ||
2850 | } | 2824 | } |
2851 | } | 2825 | } |
2852 | 2826 | ||