summaryrefslogtreecommitdiff
path: root/apps/playback.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/playback.c')
-rw-r--r--apps/playback.c92
1 files changed, 53 insertions, 39 deletions
diff --git a/apps/playback.c b/apps/playback.c
index b80c68384f..0fd1c21daf 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -290,8 +290,8 @@ static void set_current_codec(int codec_idx);
290static void set_filebuf_watermark(int seconds); 290static void set_filebuf_watermark(int seconds);
291 291
292/* Audio thread */ 292/* Audio thread */
293static struct event_queue audio_queue; 293static struct event_queue audio_queue NOCACHEBSS_ATTR;
294static struct queue_sender_list audio_queue_sender_list; 294static struct queue_sender_list audio_queue_sender_list NOCACHEBSS_ATTR;
295static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)]; 295static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
296static const char audio_thread_name[] = "audio"; 296static const char audio_thread_name[] = "audio";
297 297
@@ -340,9 +340,10 @@ static unsigned char *dram_buf = NULL;
340 automatically swaps in the other and the swap when unlocking should not 340 automatically swaps in the other and the swap when unlocking should not
341 happen if the parity is even. 341 happen if the parity is even.
342 */ 342 */
343static bool swap_codec_parity = false; /* true=odd, false=even */ 343static bool swap_codec_parity NOCACHEBSS_ATTR = false; /* true=odd, false=even */
344/* Mutex to control which codec (normal/voice) is running */ 344/* Locking to control which codec (normal/voice) is running */
345static struct mutex mutex_codecthread NOCACHEBSS_ATTR; 345static struct semaphore sem_codecthread NOCACHEBSS_ATTR;
346static struct event event_codecthread NOCACHEBSS_ATTR;
346 347
347/* Voice state */ 348/* Voice state */
348static volatile bool voice_thread_start = false; /* Triggers voice playback (A/V) */ 349static volatile bool voice_thread_start = false; /* Triggers voice playback (A/V) */
@@ -424,8 +425,7 @@ static void wait_for_voice_swap_in(void)
424 if (NULL == iram_buf) 425 if (NULL == iram_buf)
425 return; 426 return;
426 427
427 while (current_codec != CODEC_IDX_VOICE) 428 event_wait(&event_codecthread, STATE_NONSIGNALED);
428 yield();
429#endif /* PLAYBACK_VOICE */ 429#endif /* PLAYBACK_VOICE */
430} 430}
431 431
@@ -924,21 +924,21 @@ static void swap_codec(void)
924 } 924 }
925 925
926 /* Release my semaphore */ 926 /* Release my semaphore */
927 mutex_unlock(&mutex_codecthread); 927 semaphore_release(&sem_codecthread);
928 logf("unlocked: %d", my_codec); 928 logf("unlocked: %d", my_codec);
929 929
930 /* Loop until the other codec has locked and run */ 930 /* Wait for other codec */
931 do { 931 event_wait(&event_codecthread,
932 /* Release my semaphore and force a task switch. */ 932 (my_codec == CODEC_IDX_AUDIO) ? STATE_NONSIGNALED : STATE_SIGNALED);
933 yield();
934 } while (my_codec == current_codec);
935 933
936 /* Wait for other codec to unlock */ 934 /* Wait for other codec to unlock */
937 mutex_lock(&mutex_codecthread); 935 logf("waiting for lock: %d", my_codec);
936 semaphore_wait(&sem_codecthread);
938 937
939 /* Take control */ 938 /* Take control */
940 logf("waiting for lock: %d", my_codec);
941 set_current_codec(my_codec); 939 set_current_codec(my_codec);
940 event_set_state(&event_codecthread,
941 (my_codec == CODEC_IDX_AUDIO) ? STATE_SIGNALED : STATE_NONSIGNALED);
942 942
943 /* Reload our IRAM and DRAM */ 943 /* Reload our IRAM and DRAM */
944 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE); 944 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
@@ -1161,7 +1161,7 @@ static bool voice_on_voice_stop(bool aborting, size_t *realsize)
1161 1161
1162static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize) 1162static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
1163{ 1163{
1164 struct event ev; 1164 struct queue_event ev;
1165 1165
1166 if (ci_voice.new_track) 1166 if (ci_voice.new_track)
1167 { 1167 {
@@ -1332,7 +1332,8 @@ static void voice_thread(void)
1332{ 1332{
1333 logf("Loading voice codec"); 1333 logf("Loading voice codec");
1334 voice_codec_loaded = true; 1334 voice_codec_loaded = true;
1335 mutex_lock(&mutex_codecthread); 1335 semaphore_wait(&sem_codecthread);
1336 event_set_state(&event_codecthread, false);
1336 set_current_codec(CODEC_IDX_VOICE); 1337 set_current_codec(CODEC_IDX_VOICE);
1337 dsp_configure(DSP_RESET, 0); 1338 dsp_configure(DSP_RESET, 0);
1338 voice_remaining = 0; 1339 voice_remaining = 0;
@@ -1344,9 +1345,8 @@ static void voice_thread(void)
1344 1345
1345 logf("Voice codec finished"); 1346 logf("Voice codec finished");
1346 voice_codec_loaded = false; 1347 voice_codec_loaded = false;
1347 mutex_unlock(&mutex_codecthread);
1348 voice_thread_p = NULL; 1348 voice_thread_p = NULL;
1349 remove_thread(NULL); 1349 semaphore_release(&sem_codecthread);
1350} /* voice_thread */ 1350} /* voice_thread */
1351 1351
1352#endif /* PLAYBACK_VOICE */ 1352#endif /* PLAYBACK_VOICE */
@@ -1968,7 +1968,7 @@ static bool codec_request_next_track_callback(void)
1968 1968
1969static void codec_thread(void) 1969static void codec_thread(void)
1970{ 1970{
1971 struct event ev; 1971 struct queue_event ev;
1972 int status; 1972 int status;
1973 size_t wrap; 1973 size_t wrap;
1974 1974
@@ -1988,13 +1988,14 @@ static void codec_thread(void)
1988 LOGFQUEUE("codec > voice Q_AUDIO_PLAY"); 1988 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1989 queue_post(&voice_queue, Q_AUDIO_PLAY, 0); 1989 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
1990 } 1990 }
1991 mutex_lock(&mutex_codecthread); 1991 semaphore_wait(&sem_codecthread);
1992 event_set_state(&event_codecthread, true);
1992#endif 1993#endif
1993 set_current_codec(CODEC_IDX_AUDIO); 1994 set_current_codec(CODEC_IDX_AUDIO);
1994 ci.stop_codec = false; 1995 ci.stop_codec = false;
1995 status = codec_load_file((const char *)ev.data, &ci); 1996 status = codec_load_file((const char *)ev.data, &ci);
1996#ifdef PLAYBACK_VOICE 1997#ifdef PLAYBACK_VOICE
1997 mutex_unlock(&mutex_codecthread); 1998 semaphore_release(&sem_codecthread);
1998#endif 1999#endif
1999 break; 2000 break;
2000 2001
@@ -2019,7 +2020,8 @@ static void codec_thread(void)
2019 LOGFQUEUE("codec > voice Q_AUDIO_PLAY"); 2020 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
2020 queue_post(&voice_queue, Q_AUDIO_PLAY, 0); 2021 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
2021 } 2022 }
2022 mutex_lock(&mutex_codecthread); 2023 semaphore_wait(&sem_codecthread);
2024 event_set_state(&event_codecthread, true);
2023#endif 2025#endif
2024 set_current_codec(CODEC_IDX_AUDIO); 2026 set_current_codec(CODEC_IDX_AUDIO);
2025 ci.stop_codec = false; 2027 ci.stop_codec = false;
@@ -2027,7 +2029,7 @@ static void codec_thread(void)
2027 status = codec_load_ram(CUR_TI->codecbuf, CUR_TI->codecsize, 2029 status = codec_load_ram(CUR_TI->codecbuf, CUR_TI->codecsize,
2028 &filebuf[0], wrap, &ci); 2030 &filebuf[0], wrap, &ci);
2029#ifdef PLAYBACK_VOICE 2031#ifdef PLAYBACK_VOICE
2030 mutex_unlock(&mutex_codecthread); 2032 semaphore_release(&sem_codecthread);
2031#endif 2033#endif
2032 break; 2034 break;
2033 2035
@@ -2041,14 +2043,15 @@ static void codec_thread(void)
2041 LOGFQUEUE("codec > voice Q_ENCODER_RECORD"); 2043 LOGFQUEUE("codec > voice Q_ENCODER_RECORD");
2042 queue_post(&voice_queue, Q_ENCODER_RECORD, 0); 2044 queue_post(&voice_queue, Q_ENCODER_RECORD, 0);
2043 } 2045 }
2044 mutex_lock(&mutex_codecthread); 2046 semaphore_wait(&sem_codecthread);
2047 event_set_state(&event_codecthread, true);
2045#endif 2048#endif
2046 logf("loading encoder"); 2049 logf("loading encoder");
2047 set_current_codec(CODEC_IDX_AUDIO); 2050 set_current_codec(CODEC_IDX_AUDIO);
2048 ci.stop_encoder = false; 2051 ci.stop_encoder = false;
2049 status = codec_load_file((const char *)ev.data, &ci); 2052 status = codec_load_file((const char *)ev.data, &ci);
2050#ifdef PLAYBACK_VOICE 2053#ifdef PLAYBACK_VOICE
2051 mutex_unlock(&mutex_codecthread); 2054 semaphore_release(&sem_codecthread);
2052#endif 2055#endif
2053 logf("encoder stopped"); 2056 logf("encoder stopped");
2054 break; 2057 break;
@@ -3594,13 +3597,13 @@ static bool ata_fillbuffer_callback(void)
3594 3597
3595static void audio_thread(void) 3598static void audio_thread(void)
3596{ 3599{
3597 struct event ev; 3600 struct queue_event ev;
3598 3601
3599 pcm_postinit(); 3602 pcm_postinit();
3600 3603
3601#ifdef PLAYBACK_VOICE 3604#ifdef PLAYBACK_VOICE
3602 /* Unlock mutex that init stage locks before creating this thread */ 3605 /* Unlock semaphore that init stage locks before creating this thread */
3603 mutex_unlock(&mutex_codecthread); 3606 semaphore_release(&sem_codecthread);
3604 3607
3605 /* Buffers must be set up by now - should panic - really */ 3608 /* Buffers must be set up by now - should panic - really */
3606 if (buffer_state != BUFFER_STATE_INITIALIZED) 3609 if (buffer_state != BUFFER_STATE_INITIALIZED)
@@ -3764,7 +3767,9 @@ void audio_init(void)
3764#ifdef PLAYBACK_VOICE 3767#ifdef PLAYBACK_VOICE
3765 static bool voicetagtrue = true; 3768 static bool voicetagtrue = true;
3766 static struct mp3entry id3_voice; 3769 static struct mp3entry id3_voice;
3770 struct thread_entry *voice_thread_p = NULL;
3767#endif 3771#endif
3772 struct thread_entry *audio_thread_p;
3768 3773
3769 /* Can never do this twice */ 3774 /* Can never do this twice */
3770 if (audio_is_initialized) 3775 if (audio_is_initialized)
@@ -3779,11 +3784,11 @@ void audio_init(void)
3779 to send messages. Thread creation will be delayed however so nothing 3784 to send messages. Thread creation will be delayed however so nothing
3780 starts running until ready if something yields such as talk_init. */ 3785 starts running until ready if something yields such as talk_init. */
3781#ifdef PLAYBACK_VOICE 3786#ifdef PLAYBACK_VOICE
3782 mutex_init(&mutex_codecthread);
3783 /* Take ownership of lock to prevent playback of anything before audio 3787 /* Take ownership of lock to prevent playback of anything before audio
3784 hardware is initialized - audio thread unlocks it after final init 3788 hardware is initialized - audio thread unlocks it after final init
3785 stage */ 3789 stage */
3786 mutex_lock(&mutex_codecthread); 3790 semaphore_init(&sem_codecthread, 1, 0);
3791 event_init(&event_codecthread, EVENT_MANUAL | STATE_SIGNALED);
3787#endif 3792#endif
3788 queue_init(&audio_queue, true); 3793 queue_init(&audio_queue, true);
3789 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list); 3794 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list);
@@ -3842,16 +3847,16 @@ void audio_init(void)
3842 talk first */ 3847 talk first */
3843 talk_init(); 3848 talk_init();
3844 3849
3845 /* Create the threads late now that we shouldn't be yielding again before
3846 returning */
3847 codec_thread_p = create_thread( 3850 codec_thread_p = create_thread(
3848 codec_thread, codec_stack, sizeof(codec_stack), 3851 codec_thread, codec_stack, sizeof(codec_stack),
3852 CREATE_THREAD_FROZEN,
3849 codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK) 3853 codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK)
3850 IF_COP(, CPU, true)); 3854 IF_COP(, CPU));
3851 3855
3852 create_thread(audio_thread, audio_stack, sizeof(audio_stack), 3856 audio_thread_p = create_thread(audio_thread, audio_stack,
3857 sizeof(audio_stack), CREATE_THREAD_FROZEN,
3853 audio_thread_name IF_PRIO(, PRIORITY_BUFFERING) 3858 audio_thread_name IF_PRIO(, PRIORITY_BUFFERING)
3854 IF_COP(, CPU, false)); 3859 IF_COP(, CPU));
3855 3860
3856#ifdef PLAYBACK_VOICE 3861#ifdef PLAYBACK_VOICE
3857 /* TODO: Change this around when various speech codecs can be used */ 3862 /* TODO: Change this around when various speech codecs can be used */
@@ -3859,9 +3864,10 @@ void audio_init(void)
3859 { 3864 {
3860 logf("Starting voice codec"); 3865 logf("Starting voice codec");
3861 queue_init(&voice_queue, true); 3866 queue_init(&voice_queue, true);
3862 create_thread(voice_thread, voice_stack, 3867 voice_thread_p = create_thread(voice_thread, voice_stack,
3863 sizeof(voice_stack), voice_thread_name 3868 sizeof(voice_stack), CREATE_THREAD_FROZEN,
3864 IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU, false)); 3869 voice_thread_name
3870 IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU));
3865 } 3871 }
3866#endif 3872#endif
3867 3873
@@ -3881,5 +3887,13 @@ void audio_init(void)
3881#ifndef HAVE_FLASH_STORAGE 3887#ifndef HAVE_FLASH_STORAGE
3882 audio_set_buffer_margin(global_settings.buffer_margin); 3888 audio_set_buffer_margin(global_settings.buffer_margin);
3883#endif 3889#endif
3890
3891 /* it's safe to let the threads run now */
3892 thread_thaw(codec_thread_p);
3893#ifdef PLAYBACK_VOICE
3894 if (voice_thread_p)
3895 thread_thaw(voice_thread_p);
3896#endif
3897 thread_thaw(audio_thread_p);
3884} /* audio_init */ 3898} /* audio_init */
3885 3899