diff options
Diffstat (limited to 'apps/playback.c')
-rw-r--r-- | apps/playback.c | 278 |
1 files changed, 117 insertions, 161 deletions
diff --git a/apps/playback.c b/apps/playback.c index 2873c90772..31ec21afda 100644 --- a/apps/playback.c +++ b/apps/playback.c | |||
@@ -832,57 +832,11 @@ void audio_set_crossfade(int enable) | |||
832 | audio_play(offset); | 832 | audio_play(offset); |
833 | } | 833 | } |
834 | 834 | ||
835 | void audio_preinit(void) | ||
836 | { | ||
837 | logf("playback system pre-init"); | ||
838 | |||
839 | filling = false; | ||
840 | set_current_codec(CODEC_IDX_AUDIO); | ||
841 | playing = false; | ||
842 | paused = false; | ||
843 | audio_codec_loaded = false; | ||
844 | #ifdef PLAYBACK_VOICE | ||
845 | voice_is_playing = false; | ||
846 | voice_thread_start = false; | ||
847 | voice_codec_loaded = false; | ||
848 | #endif | ||
849 | track_changed = false; | ||
850 | current_fd = -1; | ||
851 | track_buffer_callback = NULL; | ||
852 | track_unbuffer_callback = NULL; | ||
853 | track_changed_callback = NULL; | ||
854 | track_ridx = 0; /* Just to prevent CUR_TI from being anything random. */ | ||
855 | prev_ti = &tracks[MAX_TRACK-1]; /* And prevent prev_ti being random too */ | ||
856 | |||
857 | #ifdef PLAYBACK_VOICE | ||
858 | mutex_init(&mutex_codecthread); | ||
859 | #endif | ||
860 | |||
861 | queue_init(&audio_queue, true); | ||
862 | queue_enable_queue_send(&audio_queue, &audio_queue_sender_list); | ||
863 | queue_init(&codec_queue, true); | ||
864 | |||
865 | create_thread(audio_thread, audio_stack, sizeof(audio_stack), | ||
866 | audio_thread_name IF_PRIO(, PRIORITY_BUFFERING) | ||
867 | IF_COP(, CPU, false)); | ||
868 | } | ||
869 | |||
870 | void audio_init(void) | ||
871 | { | ||
872 | LOGFQUEUE("audio > audio Q_AUDIO_POSTINIT"); | ||
873 | queue_post(&audio_queue, Q_AUDIO_POSTINIT, 0); | ||
874 | } | ||
875 | |||
876 | void voice_init(void) | 835 | void voice_init(void) |
877 | { | 836 | { |
878 | #ifdef PLAYBACK_VOICE | 837 | #ifdef PLAYBACK_VOICE |
879 | if (!filebuf) | 838 | if (voice_thread_p || !filebuf || voice_codec_loaded || |
880 | return; /* Audio buffers not yet set up */ | 839 | !talk_voice_required()) |
881 | |||
882 | if (voice_thread_p) | ||
883 | return; | ||
884 | |||
885 | if (!talk_voice_required()) | ||
886 | return; | 840 | return; |
887 | 841 | ||
888 | logf("Starting voice codec"); | 842 | logf("Starting voice codec"); |
@@ -1283,22 +1237,20 @@ static bool voice_request_next_track_callback(void) | |||
1283 | 1237 | ||
1284 | static void voice_thread(void) | 1238 | static void voice_thread(void) |
1285 | { | 1239 | { |
1286 | while (1) | 1240 | logf("Loading voice codec"); |
1287 | { | 1241 | voice_codec_loaded = true; |
1288 | logf("Loading voice codec"); | 1242 | mutex_lock(&mutex_codecthread); |
1289 | voice_codec_loaded = true; | 1243 | set_current_codec(CODEC_IDX_VOICE); |
1290 | mutex_lock(&mutex_codecthread); | 1244 | dsp_configure(DSP_RESET, 0); |
1291 | set_current_codec(CODEC_IDX_VOICE); | 1245 | voice_remaining = 0; |
1292 | dsp_configure(DSP_RESET, 0); | 1246 | voice_getmore = NULL; |
1293 | voice_remaining = 0; | ||
1294 | voice_getmore = NULL; | ||
1295 | 1247 | ||
1296 | codec_load_file(get_codec_filename(AFMT_MPA_L3), &ci_voice); | 1248 | codec_load_file(get_codec_filename(AFMT_MPA_L3), &ci_voice); |
1297 | 1249 | ||
1298 | logf("Voice codec finished"); | 1250 | logf("Voice codec finished"); |
1299 | voice_codec_loaded = false; | 1251 | voice_codec_loaded = false; |
1300 | mutex_unlock(&mutex_codecthread); | 1252 | mutex_unlock(&mutex_codecthread); |
1301 | } | 1253 | remove_thread(NULL); |
1302 | } /* voice_thread */ | 1254 | } /* voice_thread */ |
1303 | 1255 | ||
1304 | #endif /* PLAYBACK_VOICE */ | 1256 | #endif /* PLAYBACK_VOICE */ |
@@ -3465,103 +3417,6 @@ static void audio_reset_buffer(size_t pcmbufsize) | |||
3465 | buffer_state = BUFFER_STATE_NORMAL; | 3417 | buffer_state = BUFFER_STATE_NORMAL; |
3466 | } | 3418 | } |
3467 | 3419 | ||
3468 | #ifdef ROCKBOX_HAS_LOGF | ||
3469 | static void audio_test_track_changed_event(struct mp3entry *id3) | ||
3470 | { | ||
3471 | (void)id3; | ||
3472 | |||
3473 | logf("tce:%s", id3->path); | ||
3474 | } | ||
3475 | #endif | ||
3476 | |||
3477 | static void audio_playback_init(void) | ||
3478 | { | ||
3479 | #ifdef PLAYBACK_VOICE | ||
3480 | static bool voicetagtrue = true; | ||
3481 | static struct mp3entry id3_voice; | ||
3482 | #endif | ||
3483 | struct event ev; | ||
3484 | |||
3485 | logf("playback api init"); | ||
3486 | pcm_init(); | ||
3487 | |||
3488 | #ifdef AUDIO_HAVE_RECORDING | ||
3489 | rec_set_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK); | ||
3490 | #endif | ||
3491 | |||
3492 | #ifdef ROCKBOX_HAS_LOGF | ||
3493 | audio_set_track_changed_event(audio_test_track_changed_event); | ||
3494 | #endif | ||
3495 | |||
3496 | /* Initialize codec api. */ | ||
3497 | ci.read_filebuf = codec_filebuf_callback; | ||
3498 | ci.pcmbuf_insert = codec_pcmbuf_insert_callback; | ||
3499 | ci.get_codec_memory = codec_get_memory_callback; | ||
3500 | ci.request_buffer = codec_request_buffer_callback; | ||
3501 | ci.advance_buffer = codec_advance_buffer_callback; | ||
3502 | ci.advance_buffer_loc = codec_advance_buffer_loc_callback; | ||
3503 | ci.request_next_track = codec_request_next_track_callback; | ||
3504 | ci.mp3_get_filepos = codec_mp3_get_filepos_callback; | ||
3505 | ci.seek_buffer = codec_seek_buffer_callback; | ||
3506 | ci.seek_complete = codec_seek_complete_callback; | ||
3507 | ci.set_elapsed = codec_set_elapsed_callback; | ||
3508 | ci.set_offset = codec_set_offset_callback; | ||
3509 | ci.configure = codec_configure_callback; | ||
3510 | ci.discard_codec = codec_discard_codec_callback; | ||
3511 | |||
3512 | /* Initialize voice codec api. */ | ||
3513 | #ifdef PLAYBACK_VOICE | ||
3514 | memcpy(&ci_voice, &ci, sizeof(struct codec_api)); | ||
3515 | memset(&id3_voice, 0, sizeof(struct mp3entry)); | ||
3516 | ci_voice.read_filebuf = voice_filebuf_callback; | ||
3517 | ci_voice.pcmbuf_insert = voice_pcmbuf_insert_callback; | ||
3518 | ci_voice.get_codec_memory = voice_get_memory_callback; | ||
3519 | ci_voice.request_buffer = voice_request_buffer_callback; | ||
3520 | ci_voice.advance_buffer = voice_advance_buffer_callback; | ||
3521 | ci_voice.advance_buffer_loc = voice_advance_buffer_loc_callback; | ||
3522 | ci_voice.request_next_track = voice_request_next_track_callback; | ||
3523 | ci_voice.mp3_get_filepos = voice_mp3_get_filepos_callback; | ||
3524 | ci_voice.seek_buffer = voice_seek_buffer_callback; | ||
3525 | ci_voice.seek_complete = voice_do_nothing; | ||
3526 | ci_voice.set_elapsed = voice_set_elapsed_callback; | ||
3527 | ci_voice.set_offset = voice_set_offset_callback; | ||
3528 | ci_voice.discard_codec = voice_do_nothing; | ||
3529 | ci_voice.taginfo_ready = &voicetagtrue; | ||
3530 | ci_voice.id3 = &id3_voice; | ||
3531 | id3_voice.frequency = 11200; | ||
3532 | id3_voice.length = 1000000L; | ||
3533 | #endif | ||
3534 | |||
3535 | codec_thread_p = create_thread( | ||
3536 | codec_thread, codec_stack, sizeof(codec_stack), | ||
3537 | codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK) | ||
3538 | IF_COP(, COP, true)); | ||
3539 | |||
3540 | while (1) | ||
3541 | { | ||
3542 | queue_wait(&audio_queue, &ev); | ||
3543 | if (ev.id == Q_AUDIO_POSTINIT) | ||
3544 | break ; | ||
3545 | |||
3546 | #ifndef SIMULATOR | ||
3547 | if (ev.id == SYS_USB_CONNECTED) | ||
3548 | { | ||
3549 | logf("USB: Audio preinit"); | ||
3550 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
3551 | usb_wait_for_disconnect(&audio_queue); | ||
3552 | } | ||
3553 | #endif | ||
3554 | } | ||
3555 | |||
3556 | /* initialize the buffer */ | ||
3557 | filebuf = audiobuf; /* must be non-NULL for audio_set_crossfade */ | ||
3558 | buffer_state = BUFFER_STATE_TRASHED; /* force it */ | ||
3559 | audio_set_crossfade(global_settings.crossfade); | ||
3560 | |||
3561 | audio_is_initialized = true; | ||
3562 | |||
3563 | sound_settings_apply(); | ||
3564 | } | ||
3565 | #if MEM > 8 | 3420 | #if MEM > 8 |
3566 | /* we dont want this rebuffering on targets with little ram | 3421 | /* we dont want this rebuffering on targets with little ram |
3567 | because the disk may never spin down */ | 3422 | because the disk may never spin down */ |
@@ -3575,8 +3430,6 @@ static bool ata_fillbuffer_callback(void) | |||
3575 | static void audio_thread(void) | 3430 | static void audio_thread(void) |
3576 | { | 3431 | { |
3577 | struct event ev; | 3432 | struct event ev; |
3578 | /* At first initialize audio system in background. */ | ||
3579 | audio_playback_init(); | ||
3580 | 3433 | ||
3581 | while (1) | 3434 | while (1) |
3582 | { | 3435 | { |
@@ -3707,3 +3560,106 @@ static void audio_thread(void) | |||
3707 | } /* end while */ | 3560 | } /* end while */ |
3708 | } | 3561 | } |
3709 | 3562 | ||
3563 | #ifdef ROCKBOX_HAS_LOGF | ||
3564 | static void audio_test_track_changed_event(struct mp3entry *id3) | ||
3565 | { | ||
3566 | (void)id3; | ||
3567 | |||
3568 | logf("tce:%s", id3->path); | ||
3569 | } | ||
3570 | #endif | ||
3571 | |||
3572 | /* Initialize the audio system - called from init() in main.c. | ||
3573 | * Last function because of all the references to internal symbols | ||
3574 | */ | ||
3575 | void audio_init(void) | ||
3576 | { | ||
3577 | #ifdef PLAYBACK_VOICE | ||
3578 | static bool voicetagtrue = true; | ||
3579 | static struct mp3entry id3_voice; | ||
3580 | #endif | ||
3581 | |||
3582 | logf("audio: %s", audio_is_initialized ? | ||
3583 | "initializing" : "already initialized"); | ||
3584 | |||
3585 | /* Can never do this twice */ | ||
3586 | if (audio_is_initialized) | ||
3587 | return; | ||
3588 | |||
3589 | /* Initialize queues before giving control elsewhere in case it likes | ||
3590 | to send messages. Thread creation will be delayed however so nothing | ||
3591 | starts running until ready if something yields such as talk_init. */ | ||
3592 | #ifdef PLAYBACK_VOICE | ||
3593 | mutex_init(&mutex_codecthread); | ||
3594 | #endif | ||
3595 | queue_init(&audio_queue, true); | ||
3596 | queue_enable_queue_send(&audio_queue, &audio_queue_sender_list); | ||
3597 | queue_init(&codec_queue, true); | ||
3598 | |||
3599 | pcm_init(); | ||
3600 | |||
3601 | #ifdef ROCKBOX_HAS_LOGF | ||
3602 | audio_set_track_changed_event(audio_test_track_changed_event); | ||
3603 | #endif | ||
3604 | |||
3605 | /* Initialize codec api. */ | ||
3606 | ci.read_filebuf = codec_filebuf_callback; | ||
3607 | ci.pcmbuf_insert = codec_pcmbuf_insert_callback; | ||
3608 | ci.get_codec_memory = codec_get_memory_callback; | ||
3609 | ci.request_buffer = codec_request_buffer_callback; | ||
3610 | ci.advance_buffer = codec_advance_buffer_callback; | ||
3611 | ci.advance_buffer_loc = codec_advance_buffer_loc_callback; | ||
3612 | ci.request_next_track = codec_request_next_track_callback; | ||
3613 | ci.mp3_get_filepos = codec_mp3_get_filepos_callback; | ||
3614 | ci.seek_buffer = codec_seek_buffer_callback; | ||
3615 | ci.seek_complete = codec_seek_complete_callback; | ||
3616 | ci.set_elapsed = codec_set_elapsed_callback; | ||
3617 | ci.set_offset = codec_set_offset_callback; | ||
3618 | ci.configure = codec_configure_callback; | ||
3619 | ci.discard_codec = codec_discard_codec_callback; | ||
3620 | |||
3621 | /* Initialize voice codec api. */ | ||
3622 | #ifdef PLAYBACK_VOICE | ||
3623 | memcpy(&ci_voice, &ci, sizeof(ci_voice)); | ||
3624 | memset(&id3_voice, 0, sizeof(id3_voice)); | ||
3625 | ci_voice.read_filebuf = voice_filebuf_callback; | ||
3626 | ci_voice.pcmbuf_insert = voice_pcmbuf_insert_callback; | ||
3627 | ci_voice.get_codec_memory = voice_get_memory_callback; | ||
3628 | ci_voice.request_buffer = voice_request_buffer_callback; | ||
3629 | ci_voice.advance_buffer = voice_advance_buffer_callback; | ||
3630 | ci_voice.advance_buffer_loc = voice_advance_buffer_loc_callback; | ||
3631 | ci_voice.request_next_track = voice_request_next_track_callback; | ||
3632 | ci_voice.mp3_get_filepos = voice_mp3_get_filepos_callback; | ||
3633 | ci_voice.seek_buffer = voice_seek_buffer_callback; | ||
3634 | ci_voice.seek_complete = voice_do_nothing; | ||
3635 | ci_voice.set_elapsed = voice_set_elapsed_callback; | ||
3636 | ci_voice.set_offset = voice_set_offset_callback; | ||
3637 | ci_voice.discard_codec = voice_do_nothing; | ||
3638 | ci_voice.taginfo_ready = &voicetagtrue; | ||
3639 | ci_voice.id3 = &id3_voice; | ||
3640 | id3_voice.frequency = 11200; | ||
3641 | id3_voice.length = 1000000L; | ||
3642 | #endif | ||
3643 | |||
3644 | /* initialize the buffer */ | ||
3645 | filebuf = audiobuf; /* must be non-NULL for audio_set_crossfade */ | ||
3646 | /* audio_reset_buffer must to know the size of voice buffer so init | ||
3647 | voice first */ | ||
3648 | talk_init(); | ||
3649 | |||
3650 | codec_thread_p = create_thread( | ||
3651 | codec_thread, codec_stack, sizeof(codec_stack), | ||
3652 | codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK) | ||
3653 | IF_COP(, COP, true)); | ||
3654 | |||
3655 | create_thread(audio_thread, audio_stack, sizeof(audio_stack), | ||
3656 | audio_thread_name IF_PRIO(, PRIORITY_BUFFERING) | ||
3657 | IF_COP(, CPU, false)); | ||
3658 | |||
3659 | audio_set_crossfade(global_settings.crossfade); | ||
3660 | |||
3661 | audio_is_initialized = true; | ||
3662 | |||
3663 | sound_settings_apply(); | ||
3664 | audio_set_buffer_margin(global_settings.buffer_margin); | ||
3665 | } /* audio_init */ | ||