summaryrefslogtreecommitdiff
path: root/apps/playback.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/playback.c')
-rw-r--r--apps/playback.c137
1 files changed, 92 insertions, 45 deletions
diff --git a/apps/playback.c b/apps/playback.c
index 5e234beb36..80a0585b17 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -151,6 +151,12 @@ enum audio_id3_types
151}; 151};
152static struct mp3entry static_id3_entries[ID3_TYPE_NUM_STATIC]; /* (A,O) */ 152static struct mp3entry static_id3_entries[ID3_TYPE_NUM_STATIC]; /* (A,O) */
153 153
154struct audio_resume_info
155{
156 unsigned long elapsed;
157 unsigned long offset;
158};
159
154/* Peeking functions can yield and mess us up */ 160/* Peeking functions can yield and mess us up */
155static struct mutex id3_mutex SHAREDBSS_ATTR; /* (A,O)*/ 161static struct mutex id3_mutex SHAREDBSS_ATTR; /* (A,O)*/
156 162
@@ -325,7 +331,8 @@ enum audio_start_playback_flags
325 AUDIO_START_NEWBUF = 0x2, /* Mark the audiobuffer as invalid */ 331 AUDIO_START_NEWBUF = 0x2, /* Mark the audiobuffer as invalid */
326}; 332};
327 333
328static void audio_start_playback(size_t offset, unsigned int flags); 334static void audio_start_playback(const struct audio_resume_info *resume_info,
335 unsigned int flags);
329static void audio_stop_playback(void); 336static void audio_stop_playback(void);
330static void buffer_event_buffer_low_callback(void *data); 337static void buffer_event_buffer_low_callback(void *data);
331static void buffer_event_rebuffer_callback(void *data); 338static void buffer_event_rebuffer_callback(void *data);
@@ -792,7 +799,11 @@ static int shrink_callback(int handle, unsigned hints, void* start, size_t old_s
792 /* codec messages */ 799 /* codec messages */
793 { Q_AUDIO_PLAY, Q_AUDIO_PLAY }, 800 { Q_AUDIO_PLAY, Q_AUDIO_PLAY },
794 }; 801 };
802
803 static struct audio_resume_info resume;
804
795 bool give_up = false; 805 bool give_up = false;
806
796 /* filebuflen is, at this point, the buffering.c buffer size, 807 /* filebuflen is, at this point, the buffering.c buffer size,
797 * i.e. the audiobuf except voice, scratch mem, pcm, ... */ 808 * i.e. the audiobuf except voice, scratch mem, pcm, ... */
798 ssize_t extradata_size = old_size - filebuflen; 809 ssize_t extradata_size = old_size - filebuflen;
@@ -813,7 +824,9 @@ static int shrink_callback(int handle, unsigned hints, void* start, size_t old_s
813 824
814 825
815 /* TODO: Do it without stopping playback, if possible */ 826 /* TODO: Do it without stopping playback, if possible */
816 long offset = audio_current_track()->offset; 827 struct mp3entry *id3 = audio_current_track();
828 unsigned long elapsed = id3->elapsed;
829 unsigned long offset = id3->offset;
817 /* resume if playing */ 830 /* resume if playing */
818 bool playing = (audio_status() == AUDIO_STATUS_PLAY); 831 bool playing = (audio_status() == AUDIO_STATUS_PLAY);
819 /* There's one problem with stoping and resuming: If it happens in a too 832 /* There's one problem with stoping and resuming: If it happens in a too
@@ -825,10 +838,20 @@ static int shrink_callback(int handle, unsigned hints, void* start, size_t old_s
825 * queue_post from the last call to get the correct offset. This also 838 * queue_post from the last call to get the correct offset. This also
826 * lets us conviniently remove the queue event so Q_AUDIO_PLAY is only 839 * lets us conviniently remove the queue event so Q_AUDIO_PLAY is only
827 * processed once. */ 840 * processed once. */
828 bool play_queued = queue_peek_ex(&audio_queue, &ev, QPEEK_REMOVE_EVENTS, filter_list); 841 bool play_queued = queue_peek_ex(&audio_queue, &ev, QPEEK_REMOVE_EVENTS,
842 filter_list);
829 843
830 if (playing && offset > 0) /* current id3->offset is king */ 844 if (playing && ev.data != (intptr_t)&resume)
831 ev.data = offset; 845 {
846 resume = *(struct audio_resume_info *)ev.data;
847
848 /* current id3->elapsed/offset are king */
849 if (elapsed > 0)
850 resume.elapsed = elapsed;
851
852 if (offset > 0)
853 resume.offset = offset;
854 }
832 855
833 /* don't call audio_hard_stop() as it frees this handle */ 856 /* don't call audio_hard_stop() as it frees this handle */
834 if (thread_self() == audio_thread_id) 857 if (thread_self() == audio_thread_id)
@@ -867,7 +890,7 @@ static int shrink_callback(int handle, unsigned hints, void* start, size_t old_s
867 if (playing || play_queued) 890 if (playing || play_queued)
868 { 891 {
869 /* post, to make subsequent calls not break the resume position */ 892 /* post, to make subsequent calls not break the resume position */
870 audio_queue_post(Q_AUDIO_PLAY, ev.data); 893 audio_queue_post(Q_AUDIO_PLAY, (intptr_t)&resume);
871 } 894 }
872 895
873 return BUFLIB_CB_OK; 896 return BUFLIB_CB_OK;
@@ -1099,7 +1122,8 @@ static void audio_update_and_announce_next_track(const struct mp3entry *id3_next
1099 1122
1100/* Bring the user current mp3entry up to date and set a new offset for the 1123/* Bring the user current mp3entry up to date and set a new offset for the
1101 buffered metadata */ 1124 buffered metadata */
1102static void playing_id3_sync(struct track_info *user_info, off_t offset) 1125static void playing_id3_sync(struct track_info *user_info,
1126 unsigned long elapsed, unsigned long offset)
1103{ 1127{
1104 id3_mutex_lock(); 1128 id3_mutex_lock();
1105 1129
@@ -1113,9 +1137,14 @@ static void playing_id3_sync(struct track_info *user_info, off_t offset)
1113 1137
1114 id3_write(PLAYING_ID3, id3); 1138 id3_write(PLAYING_ID3, id3);
1115 1139
1116 if (offset < 0) 1140 if (elapsed == (unsigned long)-1)
1117 { 1141 {
1118 playing_id3->elapsed = e; 1142 playing_id3->elapsed = e;
1143 elapsed = 0;
1144 }
1145
1146 if (offset == (unsigned long)-1)
1147 {
1119 playing_id3->offset = o; 1148 playing_id3->offset = o;
1120 offset = 0; 1149 offset = 0;
1121 } 1150 }
@@ -1123,7 +1152,10 @@ static void playing_id3_sync(struct track_info *user_info, off_t offset)
1123 pcm_play_unlock(); 1152 pcm_play_unlock();
1124 1153
1125 if (id3) 1154 if (id3)
1155 {
1156 id3->elapsed = elapsed;
1126 id3->offset = offset; 1157 id3->offset = offset;
1158 }
1127 1159
1128 id3_mutex_unlock(); 1160 id3_mutex_unlock();
1129} 1161}
@@ -1299,19 +1331,16 @@ static bool audio_get_track_metadata(int offset, struct mp3entry *id3)
1299 return false; 1331 return false;
1300} 1332}
1301 1333
1302/* Get a resume rewind adjusted offset from the ID3 */ 1334/* Get resume rewind adjusted progress from the ID3 */
1303static unsigned long resume_rewind_adjusted_offset(const struct mp3entry *id3) 1335static void resume_rewind_adjust_progress(const struct mp3entry *id3,
1336 unsigned long *elapsed,
1337 unsigned long *offset)
1304{ 1338{
1305 unsigned long offset = id3->offset; 1339 unsigned int rewind = MAX(global_settings.resume_rewind, 0);
1306 size_t resume_rewind = global_settings.resume_rewind * 1340 unsigned long d_e = rewind*1000;
1307 id3->bitrate * (1000/8); 1341 *elapsed = id3->elapsed - MIN(id3->elapsed, d_e);
1308 1342 unsigned long d_o = rewind * id3->bitrate * (1000/8);
1309 if (offset < resume_rewind) 1343 *offset = id3->offset - MIN(id3->offset, d_o);
1310 offset = 0;
1311 else
1312 offset -= resume_rewind;
1313
1314 return offset;
1315} 1344}
1316 1345
1317/* Get the codec into ram and initialize it - keep it if it's ready */ 1346/* Get the codec into ram and initialize it - keep it if it's ready */
@@ -1436,7 +1465,7 @@ static bool audio_start_codec(bool auto_skip)
1436#ifdef HAVE_TAGCACHE 1465#ifdef HAVE_TAGCACHE
1437 bool autoresume_enable = global_settings.autoresume_enable; 1466 bool autoresume_enable = global_settings.autoresume_enable;
1438 1467
1439 if (autoresume_enable && !cur_id3->offset) 1468 if (autoresume_enable && !(cur_id3->elapsed || cur_id3->offset))
1440 { 1469 {
1441 /* Resume all manually selected tracks */ 1470 /* Resume all manually selected tracks */
1442 bool resume = !auto_skip; 1471 bool resume = !auto_skip;
@@ -1466,10 +1495,13 @@ static bool audio_start_codec(bool auto_skip)
1466 } 1495 }
1467 1496
1468 if (!resume) 1497 if (!resume)
1498 {
1499 cur_id3->elapsed = 0;
1469 cur_id3->offset = 0; 1500 cur_id3->offset = 0;
1501 }
1470 1502
1471 logf("%s: Set offset for %s to %lX\n", __func__, 1503 logf("%s: Set resume for %s to %lu %lX", __func__,
1472 cur_id3->title, cur_id3->offset); 1504 cur_id3->title, cur_id3->elapsed, cur_id3->offset);
1473 } 1505 }
1474#endif /* HAVE_TAGCACHE */ 1506#endif /* HAVE_TAGCACHE */
1475 1507
@@ -1481,7 +1513,8 @@ static bool audio_start_codec(bool auto_skip)
1481 and back again will cause accumulation of silent rewinds - that's not 1513 and back again will cause accumulation of silent rewinds - that's not
1482 our job to track directly nor could it be in any reasonable way 1514 our job to track directly nor could it be in any reasonable way
1483 */ 1515 */
1484 cur_id3->offset = resume_rewind_adjusted_offset(cur_id3); 1516 resume_rewind_adjust_progress(cur_id3, &cur_id3->elapsed,
1517 &cur_id3->offset);
1485 1518
1486 /* Update the codec API with the metadata and track info */ 1519 /* Update the codec API with the metadata and track info */
1487 id3_write(CODEC_ID3, cur_id3); 1520 id3_write(CODEC_ID3, cur_id3);
@@ -1494,7 +1527,7 @@ static bool audio_start_codec(bool auto_skip)
1494 codec_go(); 1527 codec_go();
1495 1528
1496#ifdef HAVE_TAGCACHE 1529#ifdef HAVE_TAGCACHE
1497 if (!autoresume_enable || cur_id3->offset) 1530 if (!autoresume_enable || cur_id3->elapsed || cur_id3->offset)
1498#endif 1531#endif
1499 { 1532 {
1500 /* Send the "buffer" event now */ 1533 /* Send the "buffer" event now */
@@ -1923,7 +1956,9 @@ static int audio_finish_load_track(struct track_info *info)
1923 1956
1924 /** Finally, load the audio **/ 1957 /** Finally, load the audio **/
1925 size_t file_offset = 0; 1958 size_t file_offset = 0;
1926 track_id3->elapsed = 0; 1959
1960 if (track_id3->elapsed > track_id3->length)
1961 track_id3->elapsed = 0;
1927 1962
1928 if (track_id3->offset >= info->filesize) 1963 if (track_id3->offset >= info->filesize)
1929 track_id3->offset = 0; 1964 track_id3->offset = 0;
@@ -1933,7 +1968,11 @@ static int audio_finish_load_track(struct track_info *info)
1933 1968
1934 /* Adjust for resume rewind so we know what to buffer - starting the codec 1969 /* Adjust for resume rewind so we know what to buffer - starting the codec
1935 calls it again, so we don't save it (and they shouldn't accumulate) */ 1970 calls it again, so we don't save it (and they shouldn't accumulate) */
1936 size_t offset = resume_rewind_adjusted_offset(track_id3); 1971 unsigned long elapsed, offset;
1972 resume_rewind_adjust_progress(track_id3, &elapsed, &offset);
1973
1974 logf("%s: Set resume for %s to %lu %lX", __func__,
1975 id3->title, elapsed, offset);
1937 1976
1938 enum data_type audiotype = rbcodec_format_is_atomic(track_id3->codectype) ? 1977 enum data_type audiotype = rbcodec_format_is_atomic(track_id3->codectype) ?
1939 TYPE_ATOMIC_AUDIO : TYPE_PACKET_AUDIO; 1978 TYPE_ATOMIC_AUDIO : TYPE_PACKET_AUDIO;
@@ -2168,7 +2207,7 @@ static void audio_on_finish_load_track(int id3_hid)
2168 change otherwise */ 2207 change otherwise */
2169 bool was_valid = valid_mp3entry(id3_get(PLAYING_ID3)); 2208 bool was_valid = valid_mp3entry(id3_get(PLAYING_ID3));
2170 2209
2171 playing_id3_sync(info, -1); 2210 playing_id3_sync(info, -1, -1);
2172 2211
2173 if (!was_valid) 2212 if (!was_valid)
2174 { 2213 {
@@ -2306,7 +2345,7 @@ static void audio_begin_track_change(enum pcm_track_change_type type,
2306 if (audio_start_codec(auto_skip)) 2345 if (audio_start_codec(auto_skip))
2307 { 2346 {
2308 if (!auto_skip) 2347 if (!auto_skip)
2309 playing_id3_sync(info, -1); 2348 playing_id3_sync(info, -1, -1);
2310 return; 2349 return;
2311 } 2350 }
2312 2351
@@ -2455,8 +2494,11 @@ static void audio_on_track_changed(void)
2455/* Begin playback from an idle state, transition to a new playlist or 2494/* Begin playback from an idle state, transition to a new playlist or
2456 invalidate the buffer and resume (if playing). 2495 invalidate the buffer and resume (if playing).
2457 (usually Q_AUDIO_PLAY, Q_AUDIO_REMAKE_AUDIO_BUFFER) */ 2496 (usually Q_AUDIO_PLAY, Q_AUDIO_REMAKE_AUDIO_BUFFER) */
2458static void audio_start_playback(size_t offset, unsigned int flags) 2497static void audio_start_playback(const struct audio_resume_info *resume_info,
2498 unsigned int flags)
2459{ 2499{
2500 struct audio_resume_info resume =
2501 *(resume_info ?: &(struct audio_resume_info){ 0, 0 } );
2460 enum play_status old_status = play_status; 2502 enum play_status old_status = play_status;
2461 2503
2462 if (flags & AUDIO_START_NEWBUF) 2504 if (flags & AUDIO_START_NEWBUF)
@@ -2469,7 +2511,8 @@ static void audio_start_playback(size_t offset, unsigned int flags)
2469 2511
2470 if (old_status != PLAY_STOPPED) 2512 if (old_status != PLAY_STOPPED)
2471 { 2513 {
2472 logf("%s(%lu): skipping", __func__, (unsigned long)offset); 2514 logf("%s(%lu, %lu): skipping", __func__, resume.elapsed,
2515 resume.offset);
2473 2516
2474 halt_decoding_track(true); 2517 halt_decoding_track(true);
2475 2518
@@ -2481,7 +2524,8 @@ static void audio_start_playback(size_t offset, unsigned int flags)
2481 /* Clear out some stuff to resume the current track where it 2524 /* Clear out some stuff to resume the current track where it
2482 left off */ 2525 left off */
2483 pcmbuf_play_stop(); 2526 pcmbuf_play_stop();
2484 offset = id3_get(PLAYING_ID3)->offset; 2527 resume.elapsed = id3_get(PLAYING_ID3)->elapsed;
2528 resume.offset = id3_get(PLAYING_ID3)->offset;
2485 track_list_clear(TRACK_LIST_CLEAR_ALL); 2529 track_list_clear(TRACK_LIST_CLEAR_ALL);
2486 } 2530 }
2487 else 2531 else
@@ -2505,7 +2549,8 @@ static void audio_start_playback(size_t offset, unsigned int flags)
2505 return; /* Must already be playing */ 2549 return; /* Must already be playing */
2506 2550
2507 /* Cold playback start from a stopped state */ 2551 /* Cold playback start from a stopped state */
2508 logf("%s(%lu): starting", __func__, offset); 2552 logf("%s(%lu, %lu): starting", __func__, resume.elapsed,
2553 resume.offset);
2509 2554
2510 /* Set audio parameters */ 2555 /* Set audio parameters */
2511#if INPUT_SRC_CAPS != 0 2556#if INPUT_SRC_CAPS != 0
@@ -2555,7 +2600,7 @@ static void audio_start_playback(size_t offset, unsigned int flags)
2555 if (trackstat >= LOAD_TRACK_OK) 2600 if (trackstat >= LOAD_TRACK_OK)
2556 { 2601 {
2557 /* This is the currently playing track - get metadata, stat */ 2602 /* This is the currently playing track - get metadata, stat */
2558 playing_id3_sync(track_list_current(0), offset); 2603 playing_id3_sync(track_list_current(0), resume.elapsed, resume.offset);
2559 2604
2560 if (valid_mp3entry(id3_get(PLAYING_ID3))) 2605 if (valid_mp3entry(id3_get(PLAYING_ID3)))
2561 { 2606 {
@@ -2892,7 +2937,9 @@ static void audio_on_ff_rewind(long time)
2892 2937
2893 if (!haltres) 2938 if (!haltres)
2894 { 2939 {
2895 /* If codec must be (re)started, reset the offset */ 2940 /* If codec must be (re)started, reset the resume info so that
2941 it doesn't execute resume procedures */
2942 ci_id3->elapsed = 0;
2896 ci_id3->offset = 0; 2943 ci_id3->offset = 0;
2897 } 2944 }
2898 2945
@@ -2970,7 +3017,7 @@ static void audio_on_audio_flush(void)
2970 not possible so a restart is required in order to continue the 3017 not possible so a restart is required in order to continue the
2971 currently playing track without the now invalid future track 3018 currently playing track without the now invalid future track
2972 playing */ 3019 playing */
2973 audio_start_playback(0, AUDIO_START_RESTART); 3020 audio_start_playback(NULL, AUDIO_START_RESTART);
2974 break; 3021 break;
2975 3022
2976 default: /* Nothing else is a state */ 3023 default: /* Nothing else is a state */
@@ -3008,7 +3055,7 @@ void audio_playback_handler(struct queue_event *ev)
3008 /** Control messages **/ 3055 /** Control messages **/
3009 case Q_AUDIO_PLAY: 3056 case Q_AUDIO_PLAY:
3010 LOGFQUEUE("playback < Q_AUDIO_PLAY"); 3057 LOGFQUEUE("playback < Q_AUDIO_PLAY");
3011 audio_start_playback(ev->data, 0); 3058 audio_start_playback((struct audio_resume_info *)ev->data, 0);
3012 break; 3059 break;
3013 3060
3014#ifdef HAVE_RECORDING 3061#ifdef HAVE_RECORDING
@@ -3082,7 +3129,7 @@ void audio_playback_handler(struct queue_event *ev)
3082 case Q_AUDIO_REMAKE_AUDIO_BUFFER: 3129 case Q_AUDIO_REMAKE_AUDIO_BUFFER:
3083 /* buffer needs to be reinitialized */ 3130 /* buffer needs to be reinitialized */
3084 LOGFQUEUE("playback < Q_AUDIO_REMAKE_AUDIO_BUFFER"); 3131 LOGFQUEUE("playback < Q_AUDIO_REMAKE_AUDIO_BUFFER");
3085 audio_start_playback(0, AUDIO_START_RESTART | AUDIO_START_NEWBUF); 3132 audio_start_playback(NULL, AUDIO_START_RESTART | AUDIO_START_NEWBUF);
3086 if (play_status == PLAY_STOPPED) 3133 if (play_status == PLAY_STOPPED)
3087 return; /* just need to change buffer state */ 3134 return; /* just need to change buffer state */
3088 break; 3135 break;
@@ -3368,8 +3415,8 @@ struct mp3entry * audio_next_track(void)
3368 return id3; 3415 return id3;
3369} 3416}
3370 3417
3371/* Start playback at the specified offset */ 3418/* Start playback at the specified elapsed time or offset */
3372void audio_play(long offset) 3419void audio_play(unsigned long elapsed, unsigned long offset)
3373{ 3420{
3374 logf("audio_play"); 3421 logf("audio_play");
3375 3422
@@ -3379,8 +3426,9 @@ void audio_play(long offset)
3379 talk_force_shutup(); 3426 talk_force_shutup();
3380#endif 3427#endif
3381 3428
3382 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset); 3429 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %lu %lX", elapsed, offset);
3383 audio_queue_send(Q_AUDIO_PLAY, offset); 3430 audio_queue_send(Q_AUDIO_PLAY,
3431 (intptr_t)&(struct audio_resume_info){ elapsed, offset });
3384} 3432}
3385 3433
3386/* Stop playback if playing */ 3434/* Stop playback if playing */
@@ -3582,11 +3630,10 @@ void playback_release_aa_slot(int slot)
3582} 3630}
3583#endif /* HAVE_ALBUMART */ 3631#endif /* HAVE_ALBUMART */
3584 3632
3585/* Would normally calculate byte offset from an elapsed time but is not 3633/* Return file byte offset */
3586 used on SWCODEC */
3587int audio_get_file_pos(void) 3634int audio_get_file_pos(void)
3588{ 3635{
3589 return 0; 3636 return id3_get(PLAYING_ID3)->offset;
3590} 3637}
3591 3638
3592/* Return total file buffer length after accounting for the talk buf */ 3639/* Return total file buffer length after accounting for the talk buf */