summaryrefslogtreecommitdiff
path: root/apps/mpeg.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/mpeg.c')
-rw-r--r--apps/mpeg.c72
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
568static 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
579unsigned 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. */
609static void generate_unbuffer_events(void) 581static void generate_unbuffer_events(void)
@@ -2755,7 +2727,6 @@ size_t audio_buffer_available(void)
2755 2727
2756static void audio_reset_buffer_noalloc(void* buf, size_t bufsize) 2728static 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
2770static void audio_reset_buffer(void) 2740static 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
2819void audio_stop(void) 2794void 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
2841void audio_hard_stop(void) 2816void 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