diff options
Diffstat (limited to 'apps/playback.c')
-rw-r--r-- | apps/playback.c | 342 |
1 files changed, 92 insertions, 250 deletions
diff --git a/apps/playback.c b/apps/playback.c index 15a3fe9a61..01fa7a9dda 100644 --- a/apps/playback.c +++ b/apps/playback.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include "core_alloc.h" | 27 | #include "core_alloc.h" |
28 | #include "sound.h" | 28 | #include "sound.h" |
29 | #include "ata.h" | 29 | #include "ata.h" |
30 | #include "usb.h" | ||
31 | #include "codecs.h" | 30 | #include "codecs.h" |
32 | #include "codec_thread.h" | 31 | #include "codec_thread.h" |
33 | #include "voice_thread.h" | 32 | #include "voice_thread.h" |
@@ -38,6 +37,7 @@ | |||
38 | #include "playlist.h" | 37 | #include "playlist.h" |
39 | #include "abrepeat.h" | 38 | #include "abrepeat.h" |
40 | #include "pcmbuf.h" | 39 | #include "pcmbuf.h" |
40 | #include "audio_thread.h" | ||
41 | #include "playback.h" | 41 | #include "playback.h" |
42 | #include "misc.h" | 42 | #include "misc.h" |
43 | #include "settings.h" | 43 | #include "settings.h" |
@@ -46,10 +46,6 @@ | |||
46 | #include "tagcache.h" | 46 | #include "tagcache.h" |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | #ifdef AUDIO_HAVE_RECORDING | ||
50 | #include "pcm_record.h" | ||
51 | #endif | ||
52 | |||
53 | #ifdef HAVE_LCD_BITMAP | 49 | #ifdef HAVE_LCD_BITMAP |
54 | #ifdef HAVE_ALBUMART | 50 | #ifdef HAVE_ALBUMART |
55 | #include "albumart.h" | 51 | #include "albumart.h" |
@@ -104,8 +100,10 @@ | |||
104 | */ | 100 | */ |
105 | 101 | ||
106 | /** Miscellaneous **/ | 102 | /** Miscellaneous **/ |
107 | bool audio_is_initialized = false; /* (A,O-) */ | 103 | extern unsigned int audio_thread_id; /* from audio_thread.c */ |
108 | extern struct codec_api ci; /* (A,C) */ | 104 | extern struct event_queue audio_queue; /* from audio_thread.c */ |
105 | extern bool audio_is_initialized; /* from audio_thread.c */ | ||
106 | extern struct codec_api ci; /* from codecs.c */ | ||
109 | 107 | ||
110 | /** Possible arrangements of the main buffer **/ | 108 | /** Possible arrangements of the main buffer **/ |
111 | static enum audio_buffer_state | 109 | static enum audio_buffer_state |
@@ -190,7 +188,6 @@ static enum filling_state | |||
190 | STATE_FINISHED, /* all remaining tracks are fully buffered */ | 188 | STATE_FINISHED, /* all remaining tracks are fully buffered */ |
191 | STATE_ENDING, /* audio playback is ending */ | 189 | STATE_ENDING, /* audio playback is ending */ |
192 | STATE_ENDED, /* audio playback is done */ | 190 | STATE_ENDED, /* audio playback is done */ |
193 | STATE_USB, /* USB mode, ignore most messages */ | ||
194 | } filling = STATE_IDLE; | 191 | } filling = STATE_IDLE; |
195 | 192 | ||
196 | /* Track info - holds information about each track in the buffer */ | 193 | /* Track info - holds information about each track in the buffer */ |
@@ -330,15 +327,6 @@ static int codec_skip_status; | |||
330 | static bool codec_seeking = false; /* Codec seeking ack expected? */ | 327 | static bool codec_seeking = false; /* Codec seeking ack expected? */ |
331 | static unsigned int position_key = 0; | 328 | static unsigned int position_key = 0; |
332 | 329 | ||
333 | /* Event queues */ | ||
334 | static struct event_queue audio_queue SHAREDBSS_ATTR; | ||
335 | |||
336 | /* Audio thread */ | ||
337 | static struct queue_sender_list audio_queue_sender_list SHAREDBSS_ATTR; | ||
338 | static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)]; | ||
339 | static const char audio_thread_name[] = "audio"; | ||
340 | static unsigned int audio_thread_id = 0; | ||
341 | |||
342 | /* Forward declarations */ | 330 | /* Forward declarations */ |
343 | enum audio_start_playback_flags | 331 | enum audio_start_playback_flags |
344 | { | 332 | { |
@@ -2985,228 +2973,170 @@ static void audio_on_audio_flush(void) | |||
2985 | } | 2973 | } |
2986 | } | 2974 | } |
2987 | 2975 | ||
2988 | #ifdef AUDIO_HAVE_RECORDING | 2976 | /* Called by audio thread when playback is started */ |
2989 | /* Load the requested encoder type | 2977 | void audio_playback_handler(struct queue_event *ev) |
2990 | (Q_AUDIO_LOAD_ENCODER) */ | ||
2991 | static void audio_on_load_encoder(int afmt) | ||
2992 | { | ||
2993 | bool res = true; | ||
2994 | |||
2995 | if (play_status != PLAY_STOPPED) | ||
2996 | audio_stop_playback(); /* Can't load both types at once */ | ||
2997 | else | ||
2998 | codec_unload(); /* Encoder still loaded, stop and unload it */ | ||
2999 | |||
3000 | if (afmt != AFMT_UNKNOWN) | ||
3001 | { | ||
3002 | res = codec_load(-1, afmt | CODEC_TYPE_ENCODER); | ||
3003 | if (res) | ||
3004 | codec_go(); /* These are run immediately */ | ||
3005 | } | ||
3006 | |||
3007 | queue_reply(&audio_queue, res); | ||
3008 | } | ||
3009 | #endif /* AUDIO_HAVE_RECORDING */ | ||
3010 | |||
3011 | static void audio_thread(void) | ||
3012 | { | 2978 | { |
3013 | struct queue_event ev; | ||
3014 | |||
3015 | pcm_postinit(); | ||
3016 | |||
3017 | while (1) | 2979 | while (1) |
3018 | { | 2980 | { |
3019 | switch (filling) | 2981 | switch (ev->id) |
3020 | { | ||
3021 | /* Active states */ | ||
3022 | case STATE_FULL: | ||
3023 | case STATE_END_OF_PLAYLIST: | ||
3024 | if (buf_get_watermark() == 0) | ||
3025 | { | ||
3026 | /* End of buffering for now, let's calculate the watermark, | ||
3027 | register for a low buffer event and unboost */ | ||
3028 | audio_update_filebuf_watermark(0); | ||
3029 | add_event(BUFFER_EVENT_BUFFER_LOW, true, | ||
3030 | buffer_event_buffer_low_callback); | ||
3031 | } | ||
3032 | /* Fall-through */ | ||
3033 | case STATE_FINISHED: | ||
3034 | /* All data was buffered */ | ||
3035 | cancel_cpu_boost(); | ||
3036 | /* Fall-through */ | ||
3037 | case STATE_FILLING: | ||
3038 | case STATE_ENDING: | ||
3039 | if (audio_pcmbuf_track_change_scan()) | ||
3040 | { | ||
3041 | /* Transfer notification to audio queue event */ | ||
3042 | ev.id = Q_AUDIO_TRACK_CHANGED; | ||
3043 | ev.data = 1; | ||
3044 | } | ||
3045 | else | ||
3046 | { | ||
3047 | /* If doing auto skip, poll pcmbuf track notifications a bit | ||
3048 | faster to promply detect the transition */ | ||
3049 | queue_wait_w_tmo(&audio_queue, &ev, | ||
3050 | skip_pending == TRACK_SKIP_NONE ? | ||
3051 | HZ/2 : HZ/10); | ||
3052 | } | ||
3053 | break; | ||
3054 | |||
3055 | /* Idle states */ | ||
3056 | default: | ||
3057 | queue_wait(&audio_queue, &ev); | ||
3058 | |||
3059 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | ||
3060 | switch (ev.id) | ||
3061 | { | ||
3062 | #ifdef AUDIO_HAVE_RECORDING | ||
3063 | /* Must monitor the encoder message for recording so it can remove | ||
3064 | it if we process the insertion before it does. It cannot simply | ||
3065 | be removed from under recording however. */ | ||
3066 | case Q_AUDIO_LOAD_ENCODER: | ||
3067 | break; | ||
3068 | #endif | ||
3069 | case SYS_USB_DISCONNECTED: | ||
3070 | filling = STATE_IDLE; | ||
3071 | break; | ||
3072 | |||
3073 | default: | ||
3074 | if (filling == STATE_USB) | ||
3075 | continue; | ||
3076 | } | ||
3077 | #endif /* CONFIG_PLATFORM */ | ||
3078 | } | ||
3079 | |||
3080 | switch (ev.id) | ||
3081 | { | 2982 | { |
3082 | /** Codec and track change messages **/ | 2983 | /** Codec and track change messages **/ |
3083 | case Q_AUDIO_CODEC_COMPLETE: | 2984 | case Q_AUDIO_CODEC_COMPLETE: |
3084 | /* Codec is done processing track and has gone idle */ | 2985 | /* Codec is done processing track and has gone idle */ |
3085 | LOGFQUEUE("audio < Q_AUDIO_CODEC_COMPLETE: %ld", (long)ev.data); | 2986 | LOGFQUEUE("playback < Q_AUDIO_CODEC_COMPLETE: %ld", |
3086 | audio_on_codec_complete(ev.data); | 2987 | (long)ev->data); |
2988 | audio_on_codec_complete(ev->data); | ||
3087 | break; | 2989 | break; |
3088 | 2990 | ||
3089 | case Q_AUDIO_CODEC_SEEK_COMPLETE: | 2991 | case Q_AUDIO_CODEC_SEEK_COMPLETE: |
3090 | /* Codec is done seeking */ | 2992 | /* Codec is done seeking */ |
3091 | LOGFQUEUE("audio < Q_AUDIO_SEEK_COMPLETE"); | 2993 | LOGFQUEUE("playback < Q_AUDIO_SEEK_COMPLETE"); |
3092 | audio_on_codec_seek_complete(); | 2994 | audio_on_codec_seek_complete(); |
3093 | break; | 2995 | break; |
3094 | 2996 | ||
3095 | case Q_AUDIO_TRACK_CHANGED: | 2997 | case Q_AUDIO_TRACK_CHANGED: |
3096 | /* PCM track change done */ | 2998 | /* PCM track change done */ |
3097 | LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED"); | 2999 | LOGFQUEUE("playback < Q_AUDIO_TRACK_CHANGED"); |
3098 | audio_on_track_changed(); | 3000 | audio_on_track_changed(); |
3099 | break; | 3001 | break; |
3100 | 3002 | ||
3101 | /** Control messages **/ | 3003 | /** Control messages **/ |
3102 | case Q_AUDIO_PLAY: | 3004 | case Q_AUDIO_PLAY: |
3103 | LOGFQUEUE("audio < Q_AUDIO_PLAY"); | 3005 | LOGFQUEUE("playback < Q_AUDIO_PLAY"); |
3104 | audio_start_playback(ev.data, 0); | 3006 | audio_start_playback(ev->data, 0); |
3105 | break; | 3007 | break; |
3106 | 3008 | ||
3009 | #ifdef AUDIO_HAVE_RECORDING | ||
3010 | /* So we can go straight from playback to recording */ | ||
3011 | case Q_AUDIO_INIT_RECORDING: | ||
3012 | #endif | ||
3013 | case SYS_USB_CONNECTED: | ||
3107 | case Q_AUDIO_STOP: | 3014 | case Q_AUDIO_STOP: |
3108 | LOGFQUEUE("audio < Q_AUDIO_STOP"); | 3015 | LOGFQUEUE("playback < Q_AUDIO_STOP"); |
3109 | audio_stop_playback(); | 3016 | audio_stop_playback(); |
3110 | if (ev.data != 0) | 3017 | if (ev->data != 0) |
3111 | queue_clear(&audio_queue); | 3018 | queue_clear(&audio_queue); |
3112 | break; | 3019 | return; /* no more playback */ |
3113 | 3020 | ||
3114 | case Q_AUDIO_PAUSE: | 3021 | case Q_AUDIO_PAUSE: |
3115 | LOGFQUEUE("audio < Q_AUDIO_PAUSE"); | 3022 | LOGFQUEUE("playback < Q_AUDIO_PAUSE"); |
3116 | audio_on_pause(ev.data); | 3023 | audio_on_pause(ev->data); |
3117 | break; | 3024 | break; |
3118 | 3025 | ||
3119 | case Q_AUDIO_SKIP: | 3026 | case Q_AUDIO_SKIP: |
3120 | LOGFQUEUE("audio < Q_AUDIO_SKIP"); | 3027 | LOGFQUEUE("playback < Q_AUDIO_SKIP"); |
3121 | audio_on_skip(); | 3028 | audio_on_skip(); |
3122 | break; | 3029 | break; |
3123 | 3030 | ||
3124 | case Q_AUDIO_DIR_SKIP: | 3031 | case Q_AUDIO_DIR_SKIP: |
3125 | LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP"); | 3032 | LOGFQUEUE("playback < Q_AUDIO_DIR_SKIP"); |
3126 | audio_on_dir_skip(ev.data); | 3033 | audio_on_dir_skip(ev->data); |
3127 | break; | 3034 | break; |
3128 | 3035 | ||
3129 | case Q_AUDIO_PRE_FF_REWIND: | 3036 | case Q_AUDIO_PRE_FF_REWIND: |
3130 | LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND"); | 3037 | LOGFQUEUE("playback < Q_AUDIO_PRE_FF_REWIND"); |
3131 | audio_on_pre_ff_rewind(); | 3038 | audio_on_pre_ff_rewind(); |
3132 | break; | 3039 | break; |
3133 | 3040 | ||
3134 | case Q_AUDIO_FF_REWIND: | 3041 | case Q_AUDIO_FF_REWIND: |
3135 | LOGFQUEUE("audio < Q_AUDIO_FF_REWIND"); | 3042 | LOGFQUEUE("playback < Q_AUDIO_FF_REWIND"); |
3136 | audio_on_ff_rewind(ev.data); | 3043 | audio_on_ff_rewind(ev->data); |
3137 | break; | 3044 | break; |
3138 | 3045 | ||
3139 | case Q_AUDIO_FLUSH: | 3046 | case Q_AUDIO_FLUSH: |
3140 | LOGFQUEUE("audio < Q_AUDIO_FLUSH: %d", (int)ev.data); | 3047 | LOGFQUEUE("playback < Q_AUDIO_FLUSH: %d", (int)ev->data); |
3141 | audio_on_audio_flush(); | 3048 | audio_on_audio_flush(); |
3142 | break; | 3049 | break; |
3143 | 3050 | ||
3144 | /** Buffering messages **/ | 3051 | /** Buffering messages **/ |
3145 | case Q_AUDIO_BUFFERING: | 3052 | case Q_AUDIO_BUFFERING: |
3146 | /* some buffering event */ | 3053 | /* some buffering event */ |
3147 | LOGFQUEUE("audio < Q_AUDIO_BUFFERING: %d", (int)ev.data); | 3054 | LOGFQUEUE("playback < Q_AUDIO_BUFFERING: %d", (int)ev->data); |
3148 | audio_on_buffering(ev.data); | 3055 | audio_on_buffering(ev->data); |
3149 | break; | 3056 | break; |
3150 | 3057 | ||
3151 | case Q_AUDIO_FILL_BUFFER: | 3058 | case Q_AUDIO_FILL_BUFFER: |
3152 | /* continue buffering next track */ | 3059 | /* continue buffering next track */ |
3153 | LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER"); | 3060 | LOGFQUEUE("playback < Q_AUDIO_FILL_BUFFER"); |
3154 | audio_on_fill_buffer(); | 3061 | audio_on_fill_buffer(); |
3155 | break; | 3062 | break; |
3156 | 3063 | ||
3157 | case Q_AUDIO_FINISH_LOAD_TRACK: | 3064 | case Q_AUDIO_FINISH_LOAD_TRACK: |
3158 | /* metadata is buffered */ | 3065 | /* metadata is buffered */ |
3159 | LOGFQUEUE("audio < Q_AUDIO_FINISH_LOAD_TRACK"); | 3066 | LOGFQUEUE("playback < Q_AUDIO_FINISH_LOAD_TRACK"); |
3160 | audio_on_finish_load_track(ev.data); | 3067 | audio_on_finish_load_track(ev->data); |
3161 | break; | 3068 | break; |
3162 | 3069 | ||
3163 | case Q_AUDIO_HANDLE_FINISHED: | 3070 | case Q_AUDIO_HANDLE_FINISHED: |
3164 | /* some other type is buffered */ | 3071 | /* some other type is buffered */ |
3165 | LOGFQUEUE("audio < Q_AUDIO_HANDLE_FINISHED"); | 3072 | LOGFQUEUE("playback < Q_AUDIO_HANDLE_FINISHED"); |
3166 | audio_on_handle_finished(ev.data); | 3073 | audio_on_handle_finished(ev->data); |
3167 | break; | 3074 | break; |
3168 | 3075 | ||
3169 | /** Miscellaneous messages **/ | 3076 | /** Miscellaneous messages **/ |
3170 | case Q_AUDIO_REMAKE_AUDIO_BUFFER: | 3077 | case Q_AUDIO_REMAKE_AUDIO_BUFFER: |
3171 | /* buffer needs to be reinitialized */ | 3078 | /* buffer needs to be reinitialized */ |
3172 | LOGFQUEUE("audio < Q_AUDIO_REMAKE_AUDIO_BUFFER"); | 3079 | LOGFQUEUE("playback < Q_AUDIO_REMAKE_AUDIO_BUFFER"); |
3173 | audio_start_playback(0, AUDIO_START_RESTART | AUDIO_START_NEWBUF); | 3080 | audio_start_playback(0, AUDIO_START_RESTART | AUDIO_START_NEWBUF); |
3174 | break; | 3081 | break; |
3175 | 3082 | ||
3176 | #ifdef HAVE_DISK_STORAGE | 3083 | #ifdef HAVE_DISK_STORAGE |
3177 | case Q_AUDIO_UPDATE_WATERMARK: | 3084 | case Q_AUDIO_UPDATE_WATERMARK: |
3178 | /* buffering watermark needs updating */ | 3085 | /* buffering watermark needs updating */ |
3179 | LOGFQUEUE("audio < Q_AUDIO_UPDATE_WATERMARK: %d", (int)ev.data); | 3086 | LOGFQUEUE("playback < Q_AUDIO_UPDATE_WATERMARK: %d", |
3180 | audio_update_filebuf_watermark(ev.data); | 3087 | (int)ev->data); |
3088 | audio_update_filebuf_watermark(ev->data); | ||
3181 | break; | 3089 | break; |
3182 | #endif /* HAVE_DISK_STORAGE */ | 3090 | #endif /* HAVE_DISK_STORAGE */ |
3183 | 3091 | ||
3184 | #ifdef AUDIO_HAVE_RECORDING | 3092 | case SYS_TIMEOUT: |
3185 | case Q_AUDIO_LOAD_ENCODER: | 3093 | LOGFQUEUE_SYS_TIMEOUT("playback < SYS_TIMEOUT"); |
3186 | /* load an encoder for recording */ | ||
3187 | LOGFQUEUE("audio < Q_AUDIO_LOAD_ENCODER: %d", (int)ev.data); | ||
3188 | audio_on_load_encoder(ev.data); | ||
3189 | break; | 3094 | break; |
3190 | #endif /* AUDIO_HAVE_RECORDING */ | ||
3191 | 3095 | ||
3192 | case SYS_USB_CONNECTED: | 3096 | default: |
3193 | LOGFQUEUE("audio < SYS_USB_CONNECTED"); | 3097 | /* LOGFQUEUE("audio < default : %08lX", ev->id); */ |
3194 | audio_stop_playback(); | ||
3195 | #ifdef PLAYBACK_VOICE | ||
3196 | voice_stop(); | ||
3197 | #endif | ||
3198 | filling = STATE_USB; | ||
3199 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
3200 | break; | 3098 | break; |
3099 | } /* end switch */ | ||
3201 | 3100 | ||
3202 | case SYS_TIMEOUT: | 3101 | switch (filling) |
3203 | LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT"); | 3102 | { |
3103 | /* Active states */ | ||
3104 | case STATE_FULL: | ||
3105 | case STATE_END_OF_PLAYLIST: | ||
3106 | if (buf_get_watermark() == 0) | ||
3107 | { | ||
3108 | /* End of buffering for now, let's calculate the watermark, | ||
3109 | register for a low buffer event and unboost */ | ||
3110 | audio_update_filebuf_watermark(0); | ||
3111 | add_event(BUFFER_EVENT_BUFFER_LOW, true, | ||
3112 | buffer_event_buffer_low_callback); | ||
3113 | } | ||
3114 | /* Fall-through */ | ||
3115 | case STATE_FINISHED: | ||
3116 | /* All data was buffered */ | ||
3117 | cancel_cpu_boost(); | ||
3118 | /* Fall-through */ | ||
3119 | case STATE_FILLING: | ||
3120 | case STATE_ENDING: | ||
3121 | if (audio_pcmbuf_track_change_scan()) | ||
3122 | { | ||
3123 | /* Transfer notification to audio queue event */ | ||
3124 | ev->id = Q_AUDIO_TRACK_CHANGED; | ||
3125 | ev->data = 1; | ||
3126 | } | ||
3127 | else | ||
3128 | { | ||
3129 | /* If doing auto skip, poll pcmbuf track notifications a bit | ||
3130 | faster to promply detect the transition */ | ||
3131 | queue_wait_w_tmo(&audio_queue, ev, | ||
3132 | skip_pending == TRACK_SKIP_NONE ? HZ/2 : HZ/10); | ||
3133 | } | ||
3204 | break; | 3134 | break; |
3205 | 3135 | ||
3136 | /* Idle states */ | ||
3206 | default: | 3137 | default: |
3207 | /* LOGFQUEUE("audio < default : %08lX", ev.id); */ | 3138 | queue_wait(&audio_queue, ev); |
3208 | break; | 3139 | } |
3209 | } /* end switch */ | ||
3210 | } /* end while */ | 3140 | } /* end while */ |
3211 | } | 3141 | } |
3212 | 3142 | ||
@@ -3356,27 +3286,6 @@ bool audio_pcmbuf_may_play(void) | |||
3356 | 3286 | ||
3357 | /** -- External interfaces -- **/ | 3287 | /** -- External interfaces -- **/ |
3358 | 3288 | ||
3359 | /* Return the playback and recording status */ | ||
3360 | int audio_status(void) | ||
3361 | { | ||
3362 | unsigned int ret = play_status; | ||
3363 | |||
3364 | #ifdef AUDIO_HAVE_RECORDING | ||
3365 | /* Do this here for constitency with mpeg.c version */ | ||
3366 | ret |= pcm_rec_status(); | ||
3367 | #endif | ||
3368 | |||
3369 | return (int)ret; | ||
3370 | } | ||
3371 | |||
3372 | /* Clear all accumulated audio errors for playback and recording */ | ||
3373 | void audio_error_clear(void) | ||
3374 | { | ||
3375 | #ifdef AUDIO_HAVE_RECORDING | ||
3376 | pcm_rec_error_clear(); | ||
3377 | #endif | ||
3378 | } | ||
3379 | |||
3380 | /* Get a copy of the id3 data for the for current track + offset + skip delta */ | 3289 | /* Get a copy of the id3 data for the for current track + offset + skip delta */ |
3381 | bool audio_peek_track(struct mp3entry *id3, int offset) | 3290 | bool audio_peek_track(struct mp3entry *id3, int offset) |
3382 | { | 3291 | { |
@@ -3599,7 +3508,7 @@ unsigned char * audio_get_buffer(bool talk_buf, size_t *buffer_size) | |||
3599 | { | 3508 | { |
3600 | unsigned char *buf; | 3509 | unsigned char *buf; |
3601 | 3510 | ||
3602 | if (audio_is_initialized) | 3511 | if (audio_is_initialized && thread_self() != audio_thread_id) |
3603 | { | 3512 | { |
3604 | audio_hard_stop(); | 3513 | audio_hard_stop(); |
3605 | } | 3514 | } |
@@ -3656,15 +3565,6 @@ unsigned char * audio_get_buffer(bool talk_buf, size_t *buffer_size) | |||
3656 | return buf; | 3565 | return buf; |
3657 | } | 3566 | } |
3658 | 3567 | ||
3659 | #ifdef HAVE_RECORDING | ||
3660 | /* Stop audio, voice and obtain all available buffer space */ | ||
3661 | unsigned char * audio_get_recording_buffer(size_t *buffer_size) | ||
3662 | { | ||
3663 | audio_hard_stop(); | ||
3664 | return audio_get_buffer(true, buffer_size); | ||
3665 | } | ||
3666 | #endif /* HAVE_RECORDING */ | ||
3667 | |||
3668 | /* Restore audio buffer to a particular state (promoting status) */ | 3568 | /* Restore audio buffer to a particular state (promoting status) */ |
3669 | bool audio_restore_playback(int type) | 3569 | bool audio_restore_playback(int type) |
3670 | { | 3570 | { |
@@ -3755,30 +3655,6 @@ void playback_release_aa_slot(int slot) | |||
3755 | } | 3655 | } |
3756 | #endif /* HAVE_ALBUMART */ | 3656 | #endif /* HAVE_ALBUMART */ |
3757 | 3657 | ||
3758 | |||
3759 | #ifdef HAVE_RECORDING | ||
3760 | /* Load an encoder and run it */ | ||
3761 | bool audio_load_encoder(int afmt) | ||
3762 | { | ||
3763 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | ||
3764 | LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: %d", afmt); | ||
3765 | return audio_queue_send(Q_AUDIO_LOAD_ENCODER, afmt) != 0; | ||
3766 | #else | ||
3767 | (void)afmt; | ||
3768 | return true; | ||
3769 | #endif | ||
3770 | } | ||
3771 | |||
3772 | /* Stop an encoder and unload it */ | ||
3773 | void audio_remove_encoder(void) | ||
3774 | { | ||
3775 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | ||
3776 | LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: NULL"); | ||
3777 | audio_queue_send(Q_AUDIO_LOAD_ENCODER, AFMT_UNKNOWN); | ||
3778 | #endif | ||
3779 | } | ||
3780 | #endif /* HAVE_RECORDING */ | ||
3781 | |||
3782 | /* Is an automatic skip in progress? If called outside transition callbacks, | 3658 | /* Is an automatic skip in progress? If called outside transition callbacks, |
3783 | indicates the last skip type at the time it was processed and isn't very | 3659 | indicates the last skip type at the time it was processed and isn't very |
3784 | meaningful. */ | 3660 | meaningful. */ |
@@ -3866,58 +3742,24 @@ void audio_set_crossfade(int enable) | |||
3866 | } | 3742 | } |
3867 | #endif /* HAVE_CROSSFADE */ | 3743 | #endif /* HAVE_CROSSFADE */ |
3868 | 3744 | ||
3745 | unsigned int playback_status(void) | ||
3746 | { | ||
3747 | return play_status; | ||
3748 | } | ||
3869 | 3749 | ||
3870 | /** -- Startup -- **/ | 3750 | /** -- Startup -- **/ |
3871 | 3751 | void playback_init(void) | |
3872 | /* Initialize the audio system - called from init() in main.c */ | ||
3873 | void audio_init(void) | ||
3874 | { | 3752 | { |
3875 | /* Can never do this twice */ | 3753 | logf("playback: initializing"); |
3876 | if (audio_is_initialized) | ||
3877 | { | ||
3878 | logf("audio: already initialized"); | ||
3879 | return; | ||
3880 | } | ||
3881 | |||
3882 | logf("audio: initializing"); | ||
3883 | |||
3884 | /* Initialize queues before giving control elsewhere in case it likes | ||
3885 | to send messages. Thread creation will be delayed however so nothing | ||
3886 | starts running until ready if something yields such as talk_init. */ | ||
3887 | queue_init(&audio_queue, true); | ||
3888 | |||
3889 | mutex_init(&id3_mutex); | ||
3890 | |||
3891 | pcm_init(); | ||
3892 | |||
3893 | codec_thread_init(); | ||
3894 | |||
3895 | /* This thread does buffer, so match its priority */ | ||
3896 | audio_thread_id = create_thread(audio_thread, audio_stack, | ||
3897 | sizeof(audio_stack), 0, audio_thread_name | ||
3898 | IF_PRIO(, MIN(PRIORITY_BUFFERING, PRIORITY_USER_INTERFACE)) | ||
3899 | IF_COP(, CPU)); | ||
3900 | |||
3901 | queue_enable_queue_send(&audio_queue, &audio_queue_sender_list, | ||
3902 | audio_thread_id); | ||
3903 | 3754 | ||
3904 | /* Initialize the track buffering system */ | 3755 | /* Initialize the track buffering system */ |
3756 | mutex_init(&id3_mutex); | ||
3905 | track_list_init(); | 3757 | track_list_init(); |
3906 | buffering_init(); | 3758 | buffering_init(); |
3907 | |||
3908 | #ifdef HAVE_CROSSFADE | 3759 | #ifdef HAVE_CROSSFADE |
3909 | /* Set crossfade setting for next buffer init which should be about... */ | 3760 | /* Set crossfade setting for next buffer init which should be about... */ |
3910 | pcmbuf_request_crossfade_enable(global_settings.crossfade); | 3761 | pcmbuf_request_crossfade_enable(global_settings.crossfade); |
3911 | #endif | 3762 | #endif |
3912 | |||
3913 | /* ...now...audio_reset_buffer must know the size of voicefile buffer so | ||
3914 | init talk first which will init the buffers */ | ||
3915 | talk_init(); | ||
3916 | |||
3917 | /* Probably safe to say */ | ||
3918 | audio_is_initialized = true; | ||
3919 | |||
3920 | sound_settings_apply(); | ||
3921 | #ifdef HAVE_DISK_STORAGE | 3763 | #ifdef HAVE_DISK_STORAGE |
3922 | audio_set_buffer_margin(global_settings.buffer_margin); | 3764 | audio_set_buffer_margin(global_settings.buffer_margin); |
3923 | #endif | 3765 | #endif |