diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/bookmark.c | 2 | ||||
-rw-r--r-- | apps/filetree.c | 5 | ||||
-rw-r--r-- | apps/gui/skin_engine/skin_parser.c | 6 | ||||
-rw-r--r-- | apps/gui/skin_engine/skin_touchsupport.c | 1 | ||||
-rw-r--r-- | apps/misc.c | 2 | ||||
-rw-r--r-- | apps/mpeg.c | 60 | ||||
-rw-r--r-- | apps/onplay.c | 2 | ||||
-rw-r--r-- | apps/playback.c | 137 | ||||
-rwxr-xr-x | apps/playlist.c | 21 | ||||
-rw-r--r-- | apps/playlist.h | 6 | ||||
-rw-r--r-- | apps/playlist_viewer.c | 10 | ||||
-rw-r--r-- | apps/plugin.h | 12 | ||||
-rw-r--r-- | apps/plugins/alarmclock.c | 1 | ||||
-rw-r--r-- | apps/plugins/alpine_cdc.c | 4 | ||||
-rw-r--r-- | apps/plugins/lib/playback_control.c | 1 | ||||
-rw-r--r-- | apps/plugins/lrcplayer.c | 1 | ||||
-rw-r--r-- | apps/plugins/pictureflow/pictureflow.c | 2 | ||||
-rw-r--r-- | apps/plugins/random_folder_advance_config.c | 2 | ||||
-rw-r--r-- | apps/root_menu.c | 1 | ||||
-rw-r--r-- | apps/settings.c | 11 | ||||
-rw-r--r-- | apps/settings.h | 2 | ||||
-rw-r--r-- | apps/settings_list.c | 1 | ||||
-rw-r--r-- | apps/settings_list.h | 2 | ||||
-rw-r--r-- | apps/tagcache.c | 12 | ||||
-rw-r--r-- | apps/tagcache.h | 14 | ||||
-rw-r--r-- | apps/tagtree.c | 20 | ||||
-rw-r--r-- | apps/tree.c | 8 | ||||
-rw-r--r-- | apps/tree.h | 4 |
28 files changed, 241 insertions, 109 deletions
diff --git a/apps/bookmark.c b/apps/bookmark.c index 543e89331a..3234e77d9b 100644 --- a/apps/bookmark.c +++ b/apps/bookmark.c | |||
@@ -972,7 +972,7 @@ static bool play_bookmark(const char* bookmark) | |||
972 | if (!warn_on_pl_erase()) | 972 | if (!warn_on_pl_erase()) |
973 | return false; | 973 | return false; |
974 | return bookmark_play(global_temp_buffer, bm.resume_index, | 974 | return bookmark_play(global_temp_buffer, bm.resume_index, |
975 | bm.resume_offset, bm.resume_seed, global_filename); | 975 | bm.resume_time, bm.resume_offset, bm.resume_seed, global_filename); |
976 | } | 976 | } |
977 | 977 | ||
978 | return false; | 978 | return false; |
diff --git a/apps/filetree.c b/apps/filetree.c index 2edcaf3a03..319b5f4a77 100644 --- a/apps/filetree.c +++ b/apps/filetree.c | |||
@@ -118,7 +118,7 @@ bool ft_play_playlist(char* pathname, char* dirname, char* filename) | |||
118 | playlist_shuffle(current_tick, -1); | 118 | playlist_shuffle(current_tick, -1); |
119 | } | 119 | } |
120 | 120 | ||
121 | playlist_start(0, 0); | 121 | playlist_start(0, 0, 0); |
122 | return true; | 122 | return true; |
123 | } | 123 | } |
124 | 124 | ||
@@ -498,7 +498,7 @@ int ft_enter(struct tree_context* c) | |||
498 | start_index = 0; | 498 | start_index = 0; |
499 | } | 499 | } |
500 | 500 | ||
501 | playlist_start(start_index, 0); | 501 | playlist_start(start_index, 0, 0); |
502 | play = true; | 502 | play = true; |
503 | } | 503 | } |
504 | break; | 504 | break; |
@@ -705,6 +705,7 @@ int ft_enter(struct tree_context* c) | |||
705 | global_status.resume_index = start_index; | 705 | global_status.resume_index = start_index; |
706 | global_status.resume_crc32 = | 706 | global_status.resume_crc32 = |
707 | playlist_get_filename_crc32(NULL, start_index); | 707 | playlist_get_filename_crc32(NULL, start_index); |
708 | global_status.resume_elapsed = 0; | ||
708 | global_status.resume_offset = 0; | 709 | global_status.resume_offset = 0; |
709 | status_save(); | 710 | status_save(); |
710 | rc = GO_TO_WPS; | 711 | rc = GO_TO_WPS; |
diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c index a76a06ac61..57153ed602 100644 --- a/apps/gui/skin_engine/skin_parser.c +++ b/apps/gui/skin_engine/skin_parser.c | |||
@@ -2414,10 +2414,12 @@ bool skin_data_load(enum screen_type screen, struct wps_data *wps_data, | |||
2414 | (((wps_data->last_albumart_height != aa->height) || | 2414 | (((wps_data->last_albumart_height != aa->height) || |
2415 | (wps_data->last_albumart_width != aa->width))))) | 2415 | (wps_data->last_albumart_width != aa->width))))) |
2416 | { | 2416 | { |
2417 | long offset = audio_current_track()->offset; | 2417 | struct mp3entry *id3 = audio_current_track(); |
2418 | unsigned long elapsed = id3->elapsed; | ||
2419 | unsigned long offset = id3->offset; | ||
2418 | audio_stop(); | 2420 | audio_stop(); |
2419 | if (!(status & AUDIO_STATUS_PAUSE)) | 2421 | if (!(status & AUDIO_STATUS_PAUSE)) |
2420 | audio_play(offset); | 2422 | audio_play(elapsed, offset); |
2421 | } | 2423 | } |
2422 | } | 2424 | } |
2423 | #endif | 2425 | #endif |
diff --git a/apps/gui/skin_engine/skin_touchsupport.c b/apps/gui/skin_engine/skin_touchsupport.c index dbc561500a..7a03e83c36 100644 --- a/apps/gui/skin_engine/skin_touchsupport.c +++ b/apps/gui/skin_engine/skin_touchsupport.c | |||
@@ -177,6 +177,7 @@ int skin_get_touchaction(struct wps_data *data, int* edge_offset, | |||
177 | if (playlist_resume() != -1) | 177 | if (playlist_resume() != -1) |
178 | { | 178 | { |
179 | playlist_start(global_status.resume_index, | 179 | playlist_start(global_status.resume_index, |
180 | global_status.resume_elapsed, | ||
180 | global_status.resume_offset); | 181 | global_status.resume_offset); |
181 | } | 182 | } |
182 | } | 183 | } |
diff --git a/apps/misc.c b/apps/misc.c index fdbc1fb831..6c589b99e4 100644 --- a/apps/misc.c +++ b/apps/misc.c | |||
@@ -618,6 +618,7 @@ long default_event_handler_ex(long event, void (*callback)(void *), void *parame | |||
618 | if (resume && playlist_resume() != -1) | 618 | if (resume && playlist_resume() != -1) |
619 | { | 619 | { |
620 | playlist_start(global_status.resume_index, | 620 | playlist_start(global_status.resume_index, |
621 | global_status.resume_elapsed, | ||
621 | global_status.resume_offset); | 622 | global_status.resume_offset); |
622 | } | 623 | } |
623 | resume = false; | 624 | resume = false; |
@@ -657,6 +658,7 @@ long default_event_handler_ex(long event, void (*callback)(void *), void *parame | |||
657 | if (playlist_resume() != -1) | 658 | if (playlist_resume() != -1) |
658 | { | 659 | { |
659 | playlist_start(global_status.resume_index, | 660 | playlist_start(global_status.resume_index, |
661 | global_status.resume_elapsed, | ||
660 | global_status.resume_offset); | 662 | global_status.resume_offset); |
661 | } | 663 | } |
662 | return event; | 664 | return event; |
diff --git a/apps/mpeg.c b/apps/mpeg.c index c0b2ae0c0e..d3e0e5c137 100644 --- a/apps/mpeg.c +++ b/apps/mpeg.c | |||
@@ -177,6 +177,13 @@ static long low_watermark; /* Dynamic low watermark level */ | |||
177 | static long low_watermark_margin = 0; /* Extra time in seconds for watermark */ | 177 | static long low_watermark_margin = 0; /* Extra time in seconds for watermark */ |
178 | static long lowest_watermark_level; /* Debug value to observe the buffer | 178 | static long lowest_watermark_level; /* Debug value to observe the buffer |
179 | usage */ | 179 | usage */ |
180 | |||
181 | struct audio_resume_info | ||
182 | { | ||
183 | unsigned long elapsed; | ||
184 | unsigned long offset; | ||
185 | }; | ||
186 | |||
180 | #if CONFIG_CODEC == MAS3587F | 187 | #if CONFIG_CODEC == MAS3587F |
181 | static char recording_filename[MAX_PATH]; /* argument to thread */ | 188 | static char recording_filename[MAX_PATH]; /* argument to thread */ |
182 | static char delayed_filename[MAX_PATH]; /* internal copy of above */ | 189 | static char delayed_filename[MAX_PATH]; /* internal copy of above */ |
@@ -430,10 +437,9 @@ static void set_elapsed(struct mp3entry* id3) | |||
430 | id3->elapsed = id3->offset / (id3->bitrate / 8); | 437 | id3->elapsed = id3->offset / (id3->bitrate / 8); |
431 | } | 438 | } |
432 | 439 | ||
433 | int audio_get_file_pos(void) | 440 | static int audio_get_file_pos_int(struct mp3entry *id3) |
434 | { | 441 | { |
435 | int pos = -1; | 442 | int pos = -1; |
436 | struct mp3entry *id3 = audio_current_track(); | ||
437 | 443 | ||
438 | if (id3->vbr) | 444 | if (id3->vbr) |
439 | { | 445 | { |
@@ -490,6 +496,12 @@ int audio_get_file_pos(void) | |||
490 | return pos; | 496 | return pos; |
491 | } | 497 | } |
492 | 498 | ||
499 | int audio_get_file_pos(void) | ||
500 | { | ||
501 | struct mp3entry *id3 = audio_current_track(); | ||
502 | return id3 ? audio_get_file_pos_int(id3) : 0; | ||
503 | } | ||
504 | |||
493 | unsigned long mpeg_get_last_header(void) | 505 | unsigned long mpeg_get_last_header(void) |
494 | { | 506 | { |
495 | #ifdef SIMULATOR | 507 | #ifdef SIMULATOR |
@@ -545,7 +557,13 @@ static int shrink_callback(int handle, unsigned hints, void* start, size_t old_s | |||
545 | } | 557 | } |
546 | /* TODO: Do it without stopping playback, if possible */ | 558 | /* TODO: Do it without stopping playback, if possible */ |
547 | bool playing = (audio_status() & AUDIO_STATUS_PLAY) == AUDIO_STATUS_PLAY; | 559 | bool playing = (audio_status() & AUDIO_STATUS_PLAY) == AUDIO_STATUS_PLAY; |
548 | long offset = audio_current_track()->offset; | 560 | struct mp3entry *id3 = audio_current_track(); |
561 | unsigned long elapsed = 0, offset = 0; | ||
562 | if (id3) | ||
563 | { | ||
564 | elapsed = id3->elapsed; | ||
565 | offset = id3->offset; | ||
566 | } | ||
549 | /* don't call audio_hard_stop() as it frees this handle */ | 567 | /* don't call audio_hard_stop() as it frees this handle */ |
550 | if (thread_self() == audio_thread_id) | 568 | if (thread_self() == audio_thread_id) |
551 | { /* inline case MPEG_STOP (audio_stop()) response | 569 | { /* inline case MPEG_STOP (audio_stop()) response |
@@ -574,7 +592,7 @@ static int shrink_callback(int handle, unsigned hints, void* start, size_t old_s | |||
574 | } | 592 | } |
575 | if (playing) | 593 | if (playing) |
576 | { /* safe to call even from the audio thread (due to queue_post()) */ | 594 | { /* safe to call even from the audio thread (due to queue_post()) */ |
577 | audio_play(offset); | 595 | audio_play(elapsed, offset); |
578 | } | 596 | } |
579 | 597 | ||
580 | return BUFLIB_CB_OK; | 598 | return BUFLIB_CB_OK; |
@@ -1274,7 +1292,7 @@ static void mpeg_thread(void) | |||
1274 | int unplayed_space_left; | 1292 | int unplayed_space_left; |
1275 | int amount_to_read; | 1293 | int amount_to_read; |
1276 | int t1, t2; | 1294 | int t1, t2; |
1277 | int start_offset; | 1295 | unsigned long start_elapsed, start_offset; |
1278 | #if CONFIG_CODEC == MAS3587F | 1296 | #if CONFIG_CODEC == MAS3587F |
1279 | int amount_to_save; | 1297 | int amount_to_save; |
1280 | int save_endpos = 0; | 1298 | int save_endpos = 0; |
@@ -1337,9 +1355,16 @@ static void mpeg_thread(void) | |||
1337 | break; | 1355 | break; |
1338 | } | 1356 | } |
1339 | 1357 | ||
1340 | start_offset = (int)ev.data; | 1358 | start_elapsed = ((struct audio_resume_info *)ev.data)->elapsed; |
1359 | start_offset = ((struct audio_resume_info *)ev.data)->offset; | ||
1341 | 1360 | ||
1342 | /* mid-song resume? */ | 1361 | /* mid-song resume? */ |
1362 | if (!start_offset && start_elapsed) { | ||
1363 | struct mp3entry *id3 = &get_trackdata(0)->id3; | ||
1364 | id3->elapsed = start_elapsed; | ||
1365 | start_offset = audio_get_file_pos_int(id3); | ||
1366 | } | ||
1367 | |||
1343 | if (start_offset) { | 1368 | if (start_offset) { |
1344 | struct mp3entry* id3 = &get_trackdata(0)->id3; | 1369 | struct mp3entry* id3 = &get_trackdata(0)->id3; |
1345 | lseek(mpeg_file, start_offset, SEEK_SET); | 1370 | lseek(mpeg_file, start_offset, SEEK_SET); |
@@ -1506,7 +1531,7 @@ static void mpeg_thread(void) | |||
1506 | 1531 | ||
1507 | id3->elapsed = newtime; | 1532 | id3->elapsed = newtime; |
1508 | 1533 | ||
1509 | newpos = audio_get_file_pos(); | 1534 | newpos = audio_get_file_pos_int(id3); |
1510 | if(newpos < 0) | 1535 | if(newpos < 0) |
1511 | { | 1536 | { |
1512 | id3->elapsed = oldtime; | 1537 | id3->elapsed = oldtime; |
@@ -2765,7 +2790,7 @@ static void audio_reset_buffer(void) | |||
2765 | audio_reset_buffer_noalloc(core_get_data(audiobuf_handle), bufsize); | 2790 | audio_reset_buffer_noalloc(core_get_data(audiobuf_handle), bufsize); |
2766 | } | 2791 | } |
2767 | 2792 | ||
2768 | void audio_play(long offset) | 2793 | void audio_play(unsigned long elapsed, unsigned long offset) |
2769 | { | 2794 | { |
2770 | audio_reset_buffer(); | 2795 | audio_reset_buffer(); |
2771 | #ifdef SIMULATOR | 2796 | #ifdef SIMULATOR |
@@ -2789,15 +2814,28 @@ void audio_play(long offset) | |||
2789 | real_mpeg_play(trackname); | 2814 | real_mpeg_play(trackname); |
2790 | #endif | 2815 | #endif |
2791 | playlist_next(steps); | 2816 | playlist_next(steps); |
2792 | taginfo.offset = offset; | 2817 | if (!offset && elapsed) |
2793 | set_elapsed(&taginfo); | 2818 | { |
2819 | /* has an elapsed time but no offset; elapsed may take | ||
2820 | precedence in this case */ | ||
2821 | taginfo.elapsed = elapsed; | ||
2822 | taginfo.offset = audio_get_file_pos_int(&taginfo); | ||
2823 | } | ||
2824 | else | ||
2825 | { | ||
2826 | taginfo.offset = offset; | ||
2827 | set_elapsed(&taginfo); | ||
2828 | } | ||
2794 | is_playing = true; | 2829 | is_playing = true; |
2795 | playing = true; | 2830 | playing = true; |
2796 | break; | 2831 | break; |
2797 | } while(1); | 2832 | } while(1); |
2798 | #else /* !SIMULATOR */ | 2833 | #else /* !SIMULATOR */ |
2834 | static struct audio_resume_info resume; | ||
2799 | is_playing = true; | 2835 | is_playing = true; |
2800 | queue_post(&mpeg_queue, MPEG_PLAY, offset); | 2836 | resume.elapsed = elapsed; |
2837 | resume.offset = offset; | ||
2838 | queue_post(&mpeg_queue, MPEG_PLAY, (intptr_t)&resume); | ||
2801 | #endif /* !SIMULATOR */ | 2839 | #endif /* !SIMULATOR */ |
2802 | 2840 | ||
2803 | mpeg_errno = 0; | 2841 | mpeg_errno = 0; |
diff --git a/apps/onplay.c b/apps/onplay.c index 9152d87bf5..7c5f517090 100644 --- a/apps/onplay.c +++ b/apps/onplay.c | |||
@@ -223,7 +223,7 @@ static bool add_to_playlist(int position, bool queue) | |||
223 | inserted */ | 223 | inserted */ |
224 | if (global_settings.playlist_shuffle) | 224 | if (global_settings.playlist_shuffle) |
225 | playlist_shuffle(current_tick, -1); | 225 | playlist_shuffle(current_tick, -1); |
226 | playlist_start(0,0); | 226 | playlist_start(0, 0, 0); |
227 | onplay_result = ONPLAY_START_PLAY; | 227 | onplay_result = ONPLAY_START_PLAY; |
228 | } | 228 | } |
229 | 229 | ||
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 | }; |
152 | static struct mp3entry static_id3_entries[ID3_TYPE_NUM_STATIC]; /* (A,O) */ | 152 | static struct mp3entry static_id3_entries[ID3_TYPE_NUM_STATIC]; /* (A,O) */ |
153 | 153 | ||
154 | struct 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 */ |
155 | static struct mutex id3_mutex SHAREDBSS_ATTR; /* (A,O)*/ | 161 | static 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 | ||
328 | static void audio_start_playback(size_t offset, unsigned int flags); | 334 | static void audio_start_playback(const struct audio_resume_info *resume_info, |
335 | unsigned int flags); | ||
329 | static void audio_stop_playback(void); | 336 | static void audio_stop_playback(void); |
330 | static void buffer_event_buffer_low_callback(void *data); | 337 | static void buffer_event_buffer_low_callback(void *data); |
331 | static void buffer_event_rebuffer_callback(void *data); | 338 | static 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 */ |
1102 | static void playing_id3_sync(struct track_info *user_info, off_t offset) | 1125 | static 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 */ |
1303 | static unsigned long resume_rewind_adjusted_offset(const struct mp3entry *id3) | 1335 | static 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) */ |
2458 | static void audio_start_playback(size_t offset, unsigned int flags) | 2497 | static 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 */ |
3372 | void audio_play(long offset) | 3419 | void 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 */ | ||
3587 | int audio_get_file_pos(void) | 3634 | int 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 */ |
diff --git a/apps/playlist.c b/apps/playlist.c index 9c895bfd67..0e73781238 100755 --- a/apps/playlist.c +++ b/apps/playlist.c | |||
@@ -621,7 +621,7 @@ static int create_and_play_dir(int direction, bool play_last) | |||
621 | #if (CONFIG_CODEC == SWCODEC) | 621 | #if (CONFIG_CODEC == SWCODEC) |
622 | current_playlist.started = true; | 622 | current_playlist.started = true; |
623 | #else | 623 | #else |
624 | playlist_start(index, 0); | 624 | playlist_start(index, 0, 0); |
625 | #endif | 625 | #endif |
626 | } | 626 | } |
627 | 627 | ||
@@ -2565,7 +2565,8 @@ unsigned int playlist_get_filename_crc32(struct playlist_info *playlist, | |||
2565 | } | 2565 | } |
2566 | 2566 | ||
2567 | /* resume a playlist track with the given crc_32 of the track name. */ | 2567 | /* resume a playlist track with the given crc_32 of the track name. */ |
2568 | void playlist_resume_track(int start_index, unsigned int crc, int offset) | 2568 | void playlist_resume_track(int start_index, unsigned int crc, |
2569 | unsigned long elapsed, unsigned long offset) | ||
2569 | { | 2570 | { |
2570 | int i; | 2571 | int i; |
2571 | unsigned int tmp_crc; | 2572 | unsigned int tmp_crc; |
@@ -2573,7 +2574,7 @@ void playlist_resume_track(int start_index, unsigned int crc, int offset) | |||
2573 | tmp_crc = playlist_get_filename_crc32(playlist, start_index); | 2574 | tmp_crc = playlist_get_filename_crc32(playlist, start_index); |
2574 | if (tmp_crc == crc) | 2575 | if (tmp_crc == crc) |
2575 | { | 2576 | { |
2576 | playlist_start(start_index, offset); | 2577 | playlist_start(start_index, elapsed, offset); |
2577 | return; | 2578 | return; |
2578 | } | 2579 | } |
2579 | 2580 | ||
@@ -2582,17 +2583,18 @@ void playlist_resume_track(int start_index, unsigned int crc, int offset) | |||
2582 | tmp_crc = playlist_get_filename_crc32(playlist, i); | 2583 | tmp_crc = playlist_get_filename_crc32(playlist, i); |
2583 | if (tmp_crc == crc) | 2584 | if (tmp_crc == crc) |
2584 | { | 2585 | { |
2585 | playlist_start(i, offset); | 2586 | playlist_start(i, elapsed, offset); |
2586 | return; | 2587 | return; |
2587 | } | 2588 | } |
2588 | } | 2589 | } |
2589 | 2590 | ||
2590 | /* If we got here the file wasnt found, so start from the beginning */ | 2591 | /* If we got here the file wasnt found, so start from the beginning */ |
2591 | playlist_start(0,0); | 2592 | playlist_start(0, 0, 0); |
2592 | } | 2593 | } |
2593 | 2594 | ||
2594 | /* start playing current playlist at specified index/offset */ | 2595 | /* start playing current playlist at specified index/offset */ |
2595 | void playlist_start(int start_index, int offset) | 2596 | void playlist_start(int start_index, unsigned long elapsed, |
2597 | unsigned long offset) | ||
2596 | { | 2598 | { |
2597 | struct playlist_info* playlist = ¤t_playlist; | 2599 | struct playlist_info* playlist = ¤t_playlist; |
2598 | 2600 | ||
@@ -2605,7 +2607,7 @@ void playlist_start(int start_index, int offset) | |||
2605 | 2607 | ||
2606 | playlist->started = true; | 2608 | playlist->started = true; |
2607 | sync_control(playlist, false); | 2609 | sync_control(playlist, false); |
2608 | audio_play(offset); | 2610 | audio_play(elapsed, offset); |
2609 | } | 2611 | } |
2610 | 2612 | ||
2611 | /* Returns false if 'steps' is out of bounds, else true */ | 2613 | /* Returns false if 'steps' is out of bounds, else true */ |
@@ -2723,7 +2725,7 @@ int playlist_next(int steps) | |||
2723 | #if CONFIG_CODEC == SWCODEC | 2725 | #if CONFIG_CODEC == SWCODEC |
2724 | playlist->started = true; | 2726 | playlist->started = true; |
2725 | #else | 2727 | #else |
2726 | playlist_start(0, 0); | 2728 | playlist_start(0, 0, 0); |
2727 | #endif | 2729 | #endif |
2728 | playlist->index = 0; | 2730 | playlist->index = 0; |
2729 | index = 0; | 2731 | index = 0; |
@@ -2801,11 +2803,13 @@ int playlist_update_resume_info(const struct mp3entry* id3) | |||
2801 | if (id3) | 2803 | if (id3) |
2802 | { | 2804 | { |
2803 | if (global_status.resume_index != playlist->index || | 2805 | if (global_status.resume_index != playlist->index || |
2806 | global_status.resume_elapsed != id3->elapsed || | ||
2804 | global_status.resume_offset != id3->offset) | 2807 | global_status.resume_offset != id3->offset) |
2805 | { | 2808 | { |
2806 | unsigned int crc = crc_32(id3->path, strlen(id3->path), -1); | 2809 | unsigned int crc = crc_32(id3->path, strlen(id3->path), -1); |
2807 | global_status.resume_index = playlist->index; | 2810 | global_status.resume_index = playlist->index; |
2808 | global_status.resume_crc32 = crc; | 2811 | global_status.resume_crc32 = crc; |
2812 | global_status.resume_elapsed = id3->elapsed; | ||
2809 | global_status.resume_offset = id3->offset; | 2813 | global_status.resume_offset = id3->offset; |
2810 | status_save(); | 2814 | status_save(); |
2811 | } | 2815 | } |
@@ -2814,6 +2818,7 @@ int playlist_update_resume_info(const struct mp3entry* id3) | |||
2814 | { | 2818 | { |
2815 | global_status.resume_index = -1; | 2819 | global_status.resume_index = -1; |
2816 | global_status.resume_crc32 = -1; | 2820 | global_status.resume_crc32 = -1; |
2821 | global_status.resume_elapsed = -1; | ||
2817 | global_status.resume_offset = -1; | 2822 | global_status.resume_offset = -1; |
2818 | status_save(); | 2823 | status_save(); |
2819 | } | 2824 | } |
diff --git a/apps/playlist.h b/apps/playlist.h index d80d8aa2ee..6314e9a6ee 100644 --- a/apps/playlist.h +++ b/apps/playlist.h | |||
@@ -133,8 +133,10 @@ int playlist_add(const char *filename); | |||
133 | int playlist_shuffle(int random_seed, int start_index); | 133 | int playlist_shuffle(int random_seed, int start_index); |
134 | unsigned int playlist_get_filename_crc32(struct playlist_info *playlist, | 134 | unsigned int playlist_get_filename_crc32(struct playlist_info *playlist, |
135 | int index); | 135 | int index); |
136 | void playlist_resume_track(int start_index, unsigned int crc, int offset); | 136 | void playlist_resume_track(int start_index, unsigned int crc, |
137 | void playlist_start(int start_index, int offset); | 137 | unsigned long elapsed, unsigned long offset); |
138 | void playlist_start(int start_index, unsigned long elapsed, | ||
139 | unsigned long offset); | ||
138 | bool playlist_check(int steps); | 140 | bool playlist_check(int steps); |
139 | const char *playlist_peek(int steps, char* buf, size_t buf_size); | 141 | const char *playlist_peek(int steps, char* buf, size_t buf_size); |
140 | int playlist_next(int steps); | 142 | int playlist_next(int steps); |
diff --git a/apps/playlist_viewer.c b/apps/playlist_viewer.c index 6a20bf1aac..d28643ab20 100644 --- a/apps/playlist_viewer.c +++ b/apps/playlist_viewer.c | |||
@@ -458,6 +458,7 @@ static bool update_playlist(bool force) | |||
458 | { | 458 | { |
459 | global_status.resume_index = -1; | 459 | global_status.resume_index = -1; |
460 | global_status.resume_offset = -1; | 460 | global_status.resume_offset = -1; |
461 | global_status.resume_elapsed = -1; | ||
461 | return false; | 462 | return false; |
462 | } | 463 | } |
463 | playlist_buffer_load_entries_screen(&viewer.buffer, FORWARD, | 464 | playlist_buffer_load_entries_screen(&viewer.buffer, FORWARD, |
@@ -466,6 +467,7 @@ static bool update_playlist(bool force) | |||
466 | { | 467 | { |
467 | global_status.resume_index = -1; | 468 | global_status.resume_index = -1; |
468 | global_status.resume_offset = -1; | 469 | global_status.resume_offset = -1; |
470 | global_status.resume_elapsed = -1; | ||
469 | return false; | 471 | return false; |
470 | } | 472 | } |
471 | } | 473 | } |
@@ -526,7 +528,7 @@ static int onplay_menu(int index) | |||
526 | if (current_track->display_index!=viewer.num_tracks || | 528 | if (current_track->display_index!=viewer.num_tracks || |
527 | global_settings.repeat_mode == REPEAT_ALL) | 529 | global_settings.repeat_mode == REPEAT_ALL) |
528 | { | 530 | { |
529 | audio_play(0); | 531 | audio_play(0, 0); |
530 | viewer.current_playing_track = -1; | 532 | viewer.current_playing_track = -1; |
531 | } | 533 | } |
532 | } | 534 | } |
@@ -773,7 +775,7 @@ enum playlist_viewer_result playlist_viewer_ex(const char* filename) | |||
773 | /* play new track */ | 775 | /* play new track */ |
774 | if (!global_settings.party_mode) | 776 | if (!global_settings.party_mode) |
775 | { | 777 | { |
776 | playlist_start(current_track->index, 0); | 778 | playlist_start(current_track->index, 0, 0); |
777 | update_playlist(false); | 779 | update_playlist(false); |
778 | } | 780 | } |
779 | } | 781 | } |
@@ -790,7 +792,7 @@ enum playlist_viewer_result playlist_viewer_ex(const char* filename) | |||
790 | goto exit; | 792 | goto exit; |
791 | if (global_settings.playlist_shuffle) | 793 | if (global_settings.playlist_shuffle) |
792 | start_index = playlist_shuffle(current_tick, start_index); | 794 | start_index = playlist_shuffle(current_tick, start_index); |
793 | playlist_start(start_index, 0); | 795 | playlist_start(start_index, 0, 0); |
794 | 796 | ||
795 | /* Our playlist is now the current list */ | 797 | /* Our playlist is now the current list */ |
796 | if (!playlist_viewer_init(&viewer, NULL, true)) | 798 | if (!playlist_viewer_init(&viewer, NULL, true)) |
@@ -937,7 +939,7 @@ bool search_playlist(void) | |||
937 | case ACTION_STD_OK: | 939 | case ACTION_STD_OK: |
938 | { | 940 | { |
939 | int sel = gui_synclist_get_sel_pos(&playlist_lists); | 941 | int sel = gui_synclist_get_sel_pos(&playlist_lists); |
940 | playlist_start(found_indicies[sel], 0); | 942 | playlist_start(found_indicies[sel], 0, 0); |
941 | exit = 1; | 943 | exit = 1; |
942 | } | 944 | } |
943 | break; | 945 | break; |
diff --git a/apps/plugin.h b/apps/plugin.h index 764af4a6b7..ffdfa8fb77 100644 --- a/apps/plugin.h +++ b/apps/plugin.h | |||
@@ -160,12 +160,12 @@ void* plugin_get_buffer(size_t *buffer_size); | |||
160 | #define PLUGIN_MAGIC 0x526F634B /* RocK */ | 160 | #define PLUGIN_MAGIC 0x526F634B /* RocK */ |
161 | 161 | ||
162 | /* increase this every time the api struct changes */ | 162 | /* increase this every time the api struct changes */ |
163 | #define PLUGIN_API_VERSION 226 | 163 | #define PLUGIN_API_VERSION 227 |
164 | 164 | ||
165 | /* update this to latest version if a change to the api struct breaks | 165 | /* update this to latest version if a change to the api struct breaks |
166 | backwards compatibility (and please take the opportunity to sort in any | 166 | backwards compatibility (and please take the opportunity to sort in any |
167 | new function which are "waiting" at the end of the function table) */ | 167 | new function which are "waiting" at the end of the function table) */ |
168 | #define PLUGIN_MIN_API_VERSION 226 | 168 | #define PLUGIN_MIN_API_VERSION 227 |
169 | 169 | ||
170 | /* plugin return codes */ | 170 | /* plugin return codes */ |
171 | /* internal returns start at 0x100 to make exit(1..255) work */ | 171 | /* internal returns start at 0x100 to make exit(1..255) work */ |
@@ -723,8 +723,10 @@ struct plugin_api { | |||
723 | /* playback control */ | 723 | /* playback control */ |
724 | int (*playlist_amount)(void); | 724 | int (*playlist_amount)(void); |
725 | int (*playlist_resume)(void); | 725 | int (*playlist_resume)(void); |
726 | void (*playlist_resume_track)(int start_index, unsigned int crc, int offset); | 726 | void (*playlist_resume_track)(int start_index, unsigned int crc, |
727 | void (*playlist_start)(int start_index, int offset); | 727 | unsigned long elapsed, unsigned long offset); |
728 | void (*playlist_start)(int start_index, unsigned long elapsed, | ||
729 | unsigned long offset); | ||
728 | int (*playlist_add)(const char *filename); | 730 | int (*playlist_add)(const char *filename); |
729 | void (*playlist_sync)(struct playlist_info* playlist); | 731 | void (*playlist_sync)(struct playlist_info* playlist); |
730 | int (*playlist_remove_all_tracks)(struct playlist_info *playlist); | 732 | int (*playlist_remove_all_tracks)(struct playlist_info *playlist); |
@@ -735,7 +737,7 @@ struct plugin_api { | |||
735 | const char *dirname, int position, bool queue, | 737 | const char *dirname, int position, bool queue, |
736 | bool recurse); | 738 | bool recurse); |
737 | int (*playlist_shuffle)(int random_seed, int start_index); | 739 | int (*playlist_shuffle)(int random_seed, int start_index); |
738 | void (*audio_play)(long offset); | 740 | void (*audio_play)(unsigned long elapsed, unsigned long offset); |
739 | void (*audio_stop)(void); | 741 | void (*audio_stop)(void); |
740 | void (*audio_pause)(void); | 742 | void (*audio_pause)(void); |
741 | void (*audio_resume)(void); | 743 | void (*audio_resume)(void); |
diff --git a/apps/plugins/alarmclock.c b/apps/plugins/alarmclock.c index 79a676003a..ecafceddc7 100644 --- a/apps/plugins/alarmclock.c +++ b/apps/plugins/alarmclock.c | |||
@@ -109,6 +109,7 @@ static void resume_audio(void) | |||
109 | if (rb->playlist_resume() != -1) { | 109 | if (rb->playlist_resume() != -1) { |
110 | rb->playlist_resume_track(rb->global_status->resume_index, | 110 | rb->playlist_resume_track(rb->global_status->resume_index, |
111 | rb->global_status->resume_crc32, | 111 | rb->global_status->resume_crc32, |
112 | rb->global_status->resume_elapsed, | ||
112 | rb->global_status->resume_offset); | 113 | rb->global_status->resume_offset); |
113 | } | 114 | } |
114 | } | 115 | } |
diff --git a/apps/plugins/alpine_cdc.c b/apps/plugins/alpine_cdc.c index 653c968ffa..28bb8d8b7f 100644 --- a/apps/plugins/alpine_cdc.c +++ b/apps/plugins/alpine_cdc.c | |||
@@ -997,8 +997,8 @@ void set_play(void) | |||
997 | } | 997 | } |
998 | else | 998 | else |
999 | { | 999 | { |
1000 | print_scroll("audio_play(0)"); | 1000 | print_scroll("audio_play(0, 0)"); |
1001 | rb->audio_play(0); | 1001 | rb->audio_play(0, 0); |
1002 | } | 1002 | } |
1003 | } | 1003 | } |
1004 | 1004 | ||
diff --git a/apps/plugins/lib/playback_control.c b/apps/plugins/lib/playback_control.c index 47921e52f2..1be234f70f 100644 --- a/apps/plugins/lib/playback_control.c +++ b/apps/plugins/lib/playback_control.c | |||
@@ -39,6 +39,7 @@ static bool play(void) | |||
39 | { | 39 | { |
40 | rb->playlist_resume_track(rb->global_status->resume_index, | 40 | rb->playlist_resume_track(rb->global_status->resume_index, |
41 | rb->global_status->resume_crc32, | 41 | rb->global_status->resume_crc32, |
42 | rb->global_status->resume_elapsed, | ||
42 | rb->global_status->resume_offset); | 43 | rb->global_status->resume_offset); |
43 | } | 44 | } |
44 | } | 45 | } |
diff --git a/apps/plugins/lrcplayer.c b/apps/plugins/lrcplayer.c index 6e0394fa51..392e78e77f 100644 --- a/apps/plugins/lrcplayer.c +++ b/apps/plugins/lrcplayer.c | |||
@@ -2684,6 +2684,7 @@ static int handle_button(void) | |||
2684 | { | 2684 | { |
2685 | rb->playlist_resume_track(rb->global_status->resume_index, | 2685 | rb->playlist_resume_track(rb->global_status->resume_index, |
2686 | rb->global_status->resume_crc32, | 2686 | rb->global_status->resume_crc32, |
2687 | rb->global_status->resume_elapsed, | ||
2687 | rb->global_status->resume_offset); | 2688 | rb->global_status->resume_offset); |
2688 | } | 2689 | } |
2689 | } | 2690 | } |
diff --git a/apps/plugins/pictureflow/pictureflow.c b/apps/plugins/pictureflow/pictureflow.c index 51fe5ebfc5..bb7cec888f 100644 --- a/apps/plugins/pictureflow/pictureflow.c +++ b/apps/plugins/pictureflow/pictureflow.c | |||
@@ -2580,7 +2580,7 @@ play: | |||
2580 | * if shuffle, we can't predict the playing track easily, and for either | 2580 | * if shuffle, we can't predict the playing track easily, and for either |
2581 | * case the track list doesn't get auto scrolled*/ | 2581 | * case the track list doesn't get auto scrolled*/ |
2582 | if(!append) | 2582 | if(!append) |
2583 | rb->playlist_start(position, 0); | 2583 | rb->playlist_start(position, 0, 0); |
2584 | old_playlist = center_slide.slide_index; | 2584 | old_playlist = center_slide.slide_index; |
2585 | old_shuffle = shuffle; | 2585 | old_shuffle = shuffle; |
2586 | } | 2586 | } |
diff --git a/apps/plugins/random_folder_advance_config.c b/apps/plugins/random_folder_advance_config.c index 7f6018df4e..0b3532dde0 100644 --- a/apps/plugins/random_folder_advance_config.c +++ b/apps/plugins/random_folder_advance_config.c | |||
@@ -541,7 +541,7 @@ static int start_shuffled_play(void) | |||
541 | } | 541 | } |
542 | } | 542 | } |
543 | rb->splash(HZ, "Done"); | 543 | rb->splash(HZ, "Done"); |
544 | rb->playlist_start(0,0); | 544 | rb->playlist_start(0, 0, 0); |
545 | return 1; | 545 | return 1; |
546 | } | 546 | } |
547 | 547 | ||
diff --git a/apps/root_menu.c b/apps/root_menu.c index 259d9bf69c..09c7efad9d 100644 --- a/apps/root_menu.c +++ b/apps/root_menu.c | |||
@@ -306,6 +306,7 @@ static int wpsscrn(void* param) | |||
306 | { | 306 | { |
307 | playlist_resume_track(global_status.resume_index, | 307 | playlist_resume_track(global_status.resume_index, |
308 | global_status.resume_crc32, | 308 | global_status.resume_crc32, |
309 | global_status.resume_elapsed, | ||
309 | global_status.resume_offset); | 310 | global_status.resume_offset); |
310 | ret_val = gui_wps_show(); | 311 | ret_val = gui_wps_show(); |
311 | } | 312 | } |
diff --git a/apps/settings.c b/apps/settings.c index 13dcb5cca9..58d58788be 100644 --- a/apps/settings.c +++ b/apps/settings.c | |||
@@ -738,12 +738,17 @@ void settings_apply_play_freq(int value, bool playback) | |||
738 | bool changed = value != prev_setting; | 738 | bool changed = value != prev_setting; |
739 | prev_setting = value; | 739 | prev_setting = value; |
740 | 740 | ||
741 | long offset = 0; | 741 | unsigned long elapsed = 0; |
742 | unsigned long offset = 0; | ||
742 | bool playing = changed && !playback && | 743 | bool playing = changed && !playback && |
743 | audio_status() == AUDIO_STATUS_PLAY; | 744 | audio_status() == AUDIO_STATUS_PLAY; |
744 | 745 | ||
745 | if (playing) | 746 | if (playing) |
746 | offset = audio_current_track()->offset; | 747 | { |
748 | struct mp3entry *id3 = audio_current_track(); | ||
749 | elapsed = id3->elapsed; | ||
750 | offset = id3->offset; | ||
751 | } | ||
747 | 752 | ||
748 | if (changed && !playback) | 753 | if (changed && !playback) |
749 | audio_hard_stop(); | 754 | audio_hard_stop(); |
@@ -752,7 +757,7 @@ void settings_apply_play_freq(int value, bool playback) | |||
752 | mixer_set_frequency(play_sampr[value]); | 757 | mixer_set_frequency(play_sampr[value]); |
753 | 758 | ||
754 | if (playing) | 759 | if (playing) |
755 | audio_play(offset); | 760 | audio_play(elapsed, offset); |
756 | } | 761 | } |
757 | #endif /* HAVE_PLAY_FREQ */ | 762 | #endif /* HAVE_PLAY_FREQ */ |
758 | 763 | ||
diff --git a/apps/settings.h b/apps/settings.h index 5b876d3e67..60658f6857 100644 --- a/apps/settings.h +++ b/apps/settings.h | |||
@@ -266,6 +266,7 @@ struct system_status | |||
266 | { | 266 | { |
267 | int resume_index; /* index in playlist (-1 for no active resume) */ | 267 | int resume_index; /* index in playlist (-1 for no active resume) */ |
268 | uint32_t resume_crc32; /* crc32 of the name of the file */ | 268 | uint32_t resume_crc32; /* crc32 of the name of the file */ |
269 | uint32_t resume_elapsed; /* elapsed time in last file */ | ||
269 | uint32_t resume_offset; /* byte offset in mp3 file */ | 270 | uint32_t resume_offset; /* byte offset in mp3 file */ |
270 | int runtime; /* current runtime since last charge */ | 271 | int runtime; /* current runtime since last charge */ |
271 | int topruntime; /* top known runtime */ | 272 | int topruntime; /* top known runtime */ |
@@ -282,6 +283,7 @@ struct system_status | |||
282 | #ifdef HAVE_LCD_BITMAP | 283 | #ifdef HAVE_LCD_BITMAP |
283 | int font_id[NB_SCREENS]; /* font id of the settings font for each screen */ | 284 | int font_id[NB_SCREENS]; /* font id of the settings font for each screen */ |
284 | #endif | 285 | #endif |
286 | |||
285 | }; | 287 | }; |
286 | 288 | ||
287 | struct user_settings | 289 | struct user_settings |
diff --git a/apps/settings_list.c b/apps/settings_list.c index 39258dff8f..1ef9c62bf0 100644 --- a/apps/settings_list.c +++ b/apps/settings_list.c | |||
@@ -818,6 +818,7 @@ const struct settings_list settings[] = { | |||
818 | OFFON_SETTING(0, playlist_shuffle, LANG_SHUFFLE, false, "shuffle", NULL), | 818 | OFFON_SETTING(0, playlist_shuffle, LANG_SHUFFLE, false, "shuffle", NULL), |
819 | SYSTEM_SETTING(NVRAM(4), resume_index, -1), | 819 | SYSTEM_SETTING(NVRAM(4), resume_index, -1), |
820 | SYSTEM_SETTING(NVRAM(4), resume_crc32, -1), | 820 | SYSTEM_SETTING(NVRAM(4), resume_crc32, -1), |
821 | SYSTEM_SETTING(NVRAM(4), resume_elapsed, -1), | ||
821 | SYSTEM_SETTING(NVRAM(4), resume_offset, -1), | 822 | SYSTEM_SETTING(NVRAM(4), resume_offset, -1), |
822 | CHOICE_SETTING(0, repeat_mode, LANG_REPEAT, REPEAT_OFF, "repeat", | 823 | CHOICE_SETTING(0, repeat_mode, LANG_REPEAT, REPEAT_OFF, "repeat", |
823 | "off,all,one,shuffle" | 824 | "off,all,one,shuffle" |
diff --git a/apps/settings_list.h b/apps/settings_list.h index 66b20ca6ca..2e63220da1 100644 --- a/apps/settings_list.h +++ b/apps/settings_list.h | |||
@@ -142,7 +142,7 @@ struct custom_setting { | |||
142 | 142 | ||
143 | #define F_NVRAM_BYTES_MASK 0xE0000 /*0-4 bytes can be stored */ | 143 | #define F_NVRAM_BYTES_MASK 0xE0000 /*0-4 bytes can be stored */ |
144 | #define F_NVRAM_MASK_SHIFT 17 | 144 | #define F_NVRAM_MASK_SHIFT 17 |
145 | #define NVRAM_CONFIG_VERSION 7 | 145 | #define NVRAM_CONFIG_VERSION 8 |
146 | /* Above define should be bumped if | 146 | /* Above define should be bumped if |
147 | - a new NVRAM setting is added between 2 other NVRAM settings | 147 | - a new NVRAM setting is added between 2 other NVRAM settings |
148 | - number of bytes for a NVRAM setting is changed | 148 | - number of bytes for a NVRAM setting is changed |
diff --git a/apps/tagcache.c b/apps/tagcache.c index 07d8d1d7a2..3ce0247188 100644 --- a/apps/tagcache.c +++ b/apps/tagcache.c | |||
@@ -130,7 +130,7 @@ static long tempbuf_pos; | |||
130 | static const char *tags_str[] = { "artist", "album", "genre", "title", | 130 | static const char *tags_str[] = { "artist", "album", "genre", "title", |
131 | "filename", "composer", "comment", "albumartist", "grouping", "year", | 131 | "filename", "composer", "comment", "albumartist", "grouping", "year", |
132 | "discnumber", "tracknumber", "bitrate", "length", "playcount", "rating", | 132 | "discnumber", "tracknumber", "bitrate", "length", "playcount", "rating", |
133 | "playtime", "lastplayed", "commitid", "mtime", "lastoffset" }; | 133 | "playtime", "lastplayed", "commitid", "mtime", "lastelapsed", "lastoffset" }; |
134 | 134 | ||
135 | /* Status information of the tagcache. */ | 135 | /* Status information of the tagcache. */ |
136 | static struct tagcache_stat tc_stat; | 136 | static struct tagcache_stat tc_stat; |
@@ -196,7 +196,7 @@ static const char * const tagfile_entry_ec = "ll"; | |||
196 | /** | 196 | /** |
197 | Note: This should be (1 + TAG_COUNT) amount of l's. | 197 | Note: This should be (1 + TAG_COUNT) amount of l's. |
198 | */ | 198 | */ |
199 | static const char * const index_entry_ec = "llllllllllllllllllllll"; | 199 | static const char * const index_entry_ec = "lllllllllllllllllllllll"; |
200 | 200 | ||
201 | static const char * const tagcache_header_ec = "lll"; | 201 | static const char * const tagcache_header_ec = "lll"; |
202 | static const char * const master_header_ec = "llllll"; | 202 | static const char * const master_header_ec = "llllll"; |
@@ -1752,6 +1752,10 @@ bool tagcache_fill_tags(struct mp3entry *id3, const char *filename) | |||
1752 | #if CONFIG_CODEC == SWCODEC | 1752 | #if CONFIG_CODEC == SWCODEC |
1753 | if (global_settings.autoresume_enable) | 1753 | if (global_settings.autoresume_enable) |
1754 | { | 1754 | { |
1755 | id3->elapsed = get_tag_numeric(entry, tag_lastelapsed, idx_id); | ||
1756 | logf("tagcache_fill_tags: Set elapsed for %s to %lX\n", | ||
1757 | id3->title, id3->elapsed); | ||
1758 | |||
1755 | id3->offset = get_tag_numeric(entry, tag_lastoffset, idx_id); | 1759 | id3->offset = get_tag_numeric(entry, tag_lastoffset, idx_id); |
1756 | logf("tagcache_fill_tags: Set offset for %s to %lX\n", | 1760 | logf("tagcache_fill_tags: Set offset for %s to %lX\n", |
1757 | id3->title, id3->offset); | 1761 | id3->title, id3->offset); |
@@ -2348,6 +2352,7 @@ static bool build_numeric_indices(struct tagcache_header *h, int tmpfd) | |||
2348 | tmpdb_copy_tag(tag_playtime); | 2352 | tmpdb_copy_tag(tag_playtime); |
2349 | tmpdb_copy_tag(tag_lastplayed); | 2353 | tmpdb_copy_tag(tag_lastplayed); |
2350 | tmpdb_copy_tag(tag_commitid); | 2354 | tmpdb_copy_tag(tag_commitid); |
2355 | tmpdb_copy_tag(tag_lastelapsed); | ||
2351 | tmpdb_copy_tag(tag_lastoffset); | 2356 | tmpdb_copy_tag(tag_lastoffset); |
2352 | 2357 | ||
2353 | /* Avoid processing this entry again. */ | 2358 | /* Avoid processing this entry again. */ |
@@ -3419,7 +3424,8 @@ static int parse_changelog_line(int line_n, char *buf, void *parameters) | |||
3419 | int idx_id; | 3424 | int idx_id; |
3420 | long masterfd = (long)parameters; | 3425 | long masterfd = (long)parameters; |
3421 | const int import_tags[] = { tag_playcount, tag_rating, tag_playtime, | 3426 | const int import_tags[] = { tag_playcount, tag_rating, tag_playtime, |
3422 | tag_lastplayed, tag_commitid, tag_lastoffset }; | 3427 | tag_lastplayed, tag_commitid, tag_lastelapsed, |
3428 | tag_lastoffset }; | ||
3423 | int i; | 3429 | int i; |
3424 | (void)line_n; | 3430 | (void)line_n; |
3425 | 3431 | ||
diff --git a/apps/tagcache.h b/apps/tagcache.h index dbe1c92d39..e358cc26e0 100644 --- a/apps/tagcache.h +++ b/apps/tagcache.h | |||
@@ -33,7 +33,8 @@ | |||
33 | enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title, | 33 | enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title, |
34 | tag_filename, tag_composer, tag_comment, tag_albumartist, tag_grouping, tag_year, | 34 | tag_filename, tag_composer, tag_comment, tag_albumartist, tag_grouping, tag_year, |
35 | tag_discnumber, tag_tracknumber, tag_bitrate, tag_length, tag_playcount, tag_rating, | 35 | tag_discnumber, tag_tracknumber, tag_bitrate, tag_length, tag_playcount, tag_rating, |
36 | tag_playtime, tag_lastplayed, tag_commitid, tag_mtime, tag_lastoffset, | 36 | tag_playtime, tag_lastplayed, tag_commitid, tag_mtime, tag_lastelapsed, |
37 | tag_lastoffset, | ||
37 | /* Real tags end here, count them. */ | 38 | /* Real tags end here, count them. */ |
38 | TAG_COUNT, | 39 | TAG_COUNT, |
39 | /* Virtual tags */ | 40 | /* Virtual tags */ |
@@ -51,7 +52,7 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title, | |||
51 | #define IDX_BUF_DEPTH 64 | 52 | #define IDX_BUF_DEPTH 64 |
52 | 53 | ||
53 | /* Tag Cache Header version 'TCHxx'. Increment when changing internal structures. */ | 54 | /* Tag Cache Header version 'TCHxx'. Increment when changing internal structures. */ |
54 | #define TAGCACHE_MAGIC 0x5443480e | 55 | #define TAGCACHE_MAGIC 0x5443480f |
55 | 56 | ||
56 | /* Dump store/restore header version 'TCSxx'. */ | 57 | /* Dump store/restore header version 'TCSxx'. */ |
57 | #define TAGCACHE_STATEFILE_MAGIC 0x54435301 | 58 | #define TAGCACHE_STATEFILE_MAGIC 0x54435301 |
@@ -107,10 +108,11 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title, | |||
107 | (1LU << tag_tracknumber) | (1LU << tag_length) | (1LU << tag_bitrate) | \ | 108 | (1LU << tag_tracknumber) | (1LU << tag_length) | (1LU << tag_bitrate) | \ |
108 | (1LU << tag_playcount) | (1LU << tag_rating) | (1LU << tag_playtime) | \ | 109 | (1LU << tag_playcount) | (1LU << tag_rating) | (1LU << tag_playtime) | \ |
109 | (1LU << tag_lastplayed) | (1LU << tag_commitid) | (1LU << tag_mtime) | \ | 110 | (1LU << tag_lastplayed) | (1LU << tag_commitid) | (1LU << tag_mtime) | \ |
110 | (1LU << tag_lastoffset) | (1LU << tag_virt_basename) | \ | 111 | (1LU << tag_lastelapsed) | (1LU << tag_lastoffset) | \ |
111 | (1LU << tag_virt_length_min) | (1LU << tag_virt_length_sec) | \ | 112 | (1LU << tag_virt_basename) | (1LU << tag_virt_length_min) | \ |
112 | (1LU << tag_virt_playtime_min) | (1LU << tag_virt_playtime_sec) | \ | 113 | (1LU << tag_virt_length_sec) | (1LU << tag_virt_playtime_min) | \ |
113 | (1LU << tag_virt_entryage) | (1LU << tag_virt_autoscore)) | 114 | (1LU << tag_virt_playtime_sec) | (1LU << tag_virt_entryage) | \ |
115 | (1LU << tag_virt_autoscore)) | ||
114 | 116 | ||
115 | #define TAGCACHE_IS_NUMERIC(tag) (BIT_N(tag) & TAGCACHE_NUMERIC_TAGS) | 117 | #define TAGCACHE_IS_NUMERIC(tag) (BIT_N(tag) & TAGCACHE_NUMERIC_TAGS) |
116 | 118 | ||
diff --git a/apps/tagtree.c b/apps/tagtree.c index 9eef38b5e6..ff364ec5e4 100644 --- a/apps/tagtree.c +++ b/apps/tagtree.c | |||
@@ -330,6 +330,7 @@ static int get_tag(int *tag) | |||
330 | {"playcount", tag_playcount}, | 330 | {"playcount", tag_playcount}, |
331 | {"rating", tag_rating}, | 331 | {"rating", tag_rating}, |
332 | {"lastplayed", tag_lastplayed}, | 332 | {"lastplayed", tag_lastplayed}, |
333 | {"lastelapsed", tag_lastelapsed}, | ||
333 | {"lastoffset", tag_lastoffset}, | 334 | {"lastoffset", tag_lastoffset}, |
334 | {"commitid", tag_commitid}, | 335 | {"commitid", tag_commitid}, |
335 | {"entryage", tag_virt_entryage}, | 336 | {"entryage", tag_virt_entryage}, |
@@ -841,8 +842,16 @@ static void tagtree_buffer_event(void *data) | |||
841 | #if CONFIG_CODEC == SWCODEC | 842 | #if CONFIG_CODEC == SWCODEC |
842 | if (autoresume) | 843 | if (autoresume) |
843 | { | 844 | { |
844 | /* Load current file resume offset if not already defined (by | 845 | /* Load current file resume info if not already defined (by |
845 | another resume mechanism) */ | 846 | another resume mechanism) */ |
847 | if (id3->elapsed == 0) | ||
848 | { | ||
849 | id3->elapsed = tagcache_get_numeric(&tcs, tag_lastelapsed); | ||
850 | |||
851 | logf("tagtree_buffer_event: Set elapsed for %s to %lX\n", | ||
852 | str_or_empty(id3->title), id3->elapsed); | ||
853 | } | ||
854 | |||
846 | if (id3->offset == 0) | 855 | if (id3->offset == 0) |
847 | { | 856 | { |
848 | id3->offset = tagcache_get_numeric(&tcs, tag_lastoffset); | 857 | id3->offset = tagcache_get_numeric(&tcs, tag_lastoffset); |
@@ -940,12 +949,13 @@ static void tagtree_track_finish_event(void *data) | |||
940 | #if CONFIG_CODEC == SWCODEC | 949 | #if CONFIG_CODEC == SWCODEC |
941 | if (autoresume) | 950 | if (autoresume) |
942 | { | 951 | { |
952 | unsigned long elapsed = auto_skip ? 0 : id3->elapsed; | ||
943 | unsigned long offset = auto_skip ? 0 : id3->offset; | 953 | unsigned long offset = auto_skip ? 0 : id3->offset; |
944 | 954 | tagcache_update_numeric(tagcache_idx, tag_lastelapsed, elapsed); | |
945 | tagcache_update_numeric(tagcache_idx, tag_lastoffset, offset); | 955 | tagcache_update_numeric(tagcache_idx, tag_lastoffset, offset); |
946 | 956 | ||
947 | logf("tagtree_track_finish_event: Save offset for %s: %lX", | 957 | logf("tagtree_track_finish_event: Save resume for %s: %lX %lX", |
948 | str_or_empty(id3->title), offset); | 958 | str_or_empty(id3->title), elapsed, offset); |
949 | } | 959 | } |
950 | #endif | 960 | #endif |
951 | } | 961 | } |
@@ -2034,7 +2044,7 @@ static int tagtree_play_folder(struct tree_context* c) | |||
2034 | c->selected_item = 0; | 2044 | c->selected_item = 0; |
2035 | gui_synclist_select_item(&tree_lists, c->selected_item); | 2045 | gui_synclist_select_item(&tree_lists, c->selected_item); |
2036 | 2046 | ||
2037 | playlist_start(c->selected_item,0); | 2047 | playlist_start(c->selected_item, 0, 0); |
2038 | playlist_get_current()->num_inserted_tracks = 0; /* make warn on playlist erase work */ | 2048 | playlist_get_current()->num_inserted_tracks = 0; /* make warn on playlist erase work */ |
2039 | return 0; | 2049 | return 0; |
2040 | } | 2050 | } |
diff --git a/apps/tree.c b/apps/tree.c index cc080ac7fa..f72774fe1e 100644 --- a/apps/tree.c +++ b/apps/tree.c | |||
@@ -1052,8 +1052,8 @@ void tree_mem_init(void) | |||
1052 | tree_get_filetypes(&filetypes, &filetypes_count); | 1052 | tree_get_filetypes(&filetypes, &filetypes_count); |
1053 | } | 1053 | } |
1054 | 1054 | ||
1055 | bool bookmark_play(char *resume_file, int index, int offset, int seed, | 1055 | bool bookmark_play(char *resume_file, int index, unsigned long elapsed, |
1056 | char *filename) | 1056 | unsigned long offset, int seed, char *filename) |
1057 | { | 1057 | { |
1058 | int i; | 1058 | int i; |
1059 | char* suffix = strrchr(resume_file, '.'); | 1059 | char* suffix = strrchr(resume_file, '.'); |
@@ -1082,7 +1082,7 @@ bool bookmark_play(char *resume_file, int index, int offset, int seed, | |||
1082 | { | 1082 | { |
1083 | if (global_settings.playlist_shuffle) | 1083 | if (global_settings.playlist_shuffle) |
1084 | playlist_shuffle(seed, -1); | 1084 | playlist_shuffle(seed, -1); |
1085 | playlist_start(index,offset); | 1085 | playlist_start(index, elapsed, offset); |
1086 | started = true; | 1086 | started = true; |
1087 | } | 1087 | } |
1088 | *slash='/'; | 1088 | *slash='/'; |
@@ -1133,7 +1133,7 @@ bool bookmark_play(char *resume_file, int index, int offset, int seed, | |||
1133 | else | 1133 | else |
1134 | return false; | 1134 | return false; |
1135 | } | 1135 | } |
1136 | playlist_start(index,offset); | 1136 | playlist_start(index, elapsed, offset); |
1137 | started = true; | 1137 | started = true; |
1138 | } | 1138 | } |
1139 | } | 1139 | } |
diff --git a/apps/tree.h b/apps/tree.h index 70494f8a88..1601447b58 100644 --- a/apps/tree.h +++ b/apps/tree.h | |||
@@ -139,8 +139,8 @@ struct tree_context* tree_get_context(void); | |||
139 | void tree_flush(void); | 139 | void tree_flush(void); |
140 | void tree_restore(void); | 140 | void tree_restore(void); |
141 | 141 | ||
142 | bool bookmark_play(char* resume_file, int index, int offset, int seed, | 142 | bool bookmark_play(char* resume_file, int index, unsigned long elapsed, |
143 | char *filename); | 143 | unsigned long offset, int seed, char *filename); |
144 | 144 | ||
145 | extern struct gui_synclist tree_lists; | 145 | extern struct gui_synclist tree_lists; |
146 | #endif | 146 | #endif |