diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/appevents.h | 1 | ||||
-rw-r--r-- | apps/gui/gwps-common.c | 39 | ||||
-rw-r--r-- | apps/gui/gwps.c | 51 | ||||
-rw-r--r-- | apps/gui/gwps.h | 1 | ||||
-rw-r--r-- | apps/gui/wps_parser.c | 44 | ||||
-rw-r--r-- | apps/iap.c | 6 | ||||
-rw-r--r-- | apps/mpeg.c | 5 | ||||
-rw-r--r-- | apps/playback.c | 210 | ||||
-rw-r--r-- | apps/plugin.c | 1 | ||||
-rw-r--r-- | apps/plugin.h | 5 |
10 files changed, 189 insertions, 174 deletions
diff --git a/apps/appevents.h b/apps/appevents.h index 8cbc301ed7..e3c4a92ff8 100644 --- a/apps/appevents.h +++ b/apps/appevents.h | |||
@@ -34,6 +34,7 @@ enum { | |||
34 | PLAYBACK_EVENT_TRACK_BUFFER = (EVENT_CLASS_PLAYBACK|1), | 34 | PLAYBACK_EVENT_TRACK_BUFFER = (EVENT_CLASS_PLAYBACK|1), |
35 | PLAYBACK_EVENT_TRACK_FINISH, | 35 | PLAYBACK_EVENT_TRACK_FINISH, |
36 | PLAYBACK_EVENT_TRACK_CHANGE, | 36 | PLAYBACK_EVENT_TRACK_CHANGE, |
37 | PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, | ||
37 | }; | 38 | }; |
38 | 39 | ||
39 | /** Buffering events **/ | 40 | /** Buffering events **/ |
diff --git a/apps/gui/gwps-common.c b/apps/gui/gwps-common.c index f32b002f69..189fc6fa31 100644 --- a/apps/gui/gwps-common.c +++ b/apps/gui/gwps-common.c | |||
@@ -348,33 +348,8 @@ bool gui_wps_display(struct gui_wps *gwps) | |||
348 | 348 | ||
349 | bool gui_wps_update(struct gui_wps *gwps) | 349 | bool gui_wps_update(struct gui_wps *gwps) |
350 | { | 350 | { |
351 | bool track_changed = audio_has_changed_track(); | ||
352 | struct mp3entry *id3 = gwps->state->id3; | 351 | struct mp3entry *id3 = gwps->state->id3; |
353 | 352 | bool retval; | |
354 | gwps->state->nid3 = audio_next_track(); | ||
355 | if (track_changed) | ||
356 | { | ||
357 | gwps->state->id3 = id3 = audio_current_track(); | ||
358 | |||
359 | if (cuesheet_is_enabled() && id3->cuesheet_type | ||
360 | && strcmp(id3->path, curr_cue->audio_filename)) | ||
361 | { | ||
362 | /* the current cuesheet isn't the right one any more */ | ||
363 | /* We need to parse the new cuesheet */ | ||
364 | |||
365 | char cuepath[MAX_PATH]; | ||
366 | |||
367 | if (look_for_cuesheet_file(id3->path, cuepath) && | ||
368 | parse_cuesheet(cuepath, curr_cue)) | ||
369 | { | ||
370 | id3->cuesheet_type = 1; | ||
371 | strcpy(curr_cue->audio_filename, id3->path); | ||
372 | } | ||
373 | |||
374 | cue_spoof_id3(curr_cue, id3); | ||
375 | } | ||
376 | } | ||
377 | |||
378 | if (cuesheet_is_enabled() && id3->cuesheet_type | 353 | if (cuesheet_is_enabled() && id3->cuesheet_type |
379 | && (id3->elapsed < curr_cue->curr_track->offset | 354 | && (id3->elapsed < curr_cue->curr_track->offset |
380 | || (curr_cue->curr_track_idx < curr_cue->track_count - 1 | 355 | || (curr_cue->curr_track_idx < curr_cue->track_count - 1 |
@@ -382,17 +357,15 @@ bool gui_wps_update(struct gui_wps *gwps) | |||
382 | { | 357 | { |
383 | /* We've changed tracks within the cuesheet : | 358 | /* We've changed tracks within the cuesheet : |
384 | we need to update the ID3 info and refresh the WPS */ | 359 | we need to update the ID3 info and refresh the WPS */ |
385 | 360 | gwps->state->do_full_update = true; | |
386 | track_changed = true; | ||
387 | cue_find_current_track(curr_cue, id3->elapsed); | 361 | cue_find_current_track(curr_cue, id3->elapsed); |
388 | cue_spoof_id3(curr_cue, id3); | 362 | cue_spoof_id3(curr_cue, id3); |
389 | } | 363 | } |
390 | 364 | ||
391 | if (track_changed) | 365 | retval = gui_wps_redraw(gwps, 0, |
392 | gwps->display->stop_scroll(); | 366 | gwps->state->do_full_update ? |
393 | 367 | WPS_REFRESH_ALL : WPS_REFRESH_NON_STATIC); | |
394 | return gui_wps_redraw(gwps, 0, | 368 | return retval; |
395 | track_changed ? WPS_REFRESH_ALL : WPS_REFRESH_NON_STATIC); | ||
396 | } | 369 | } |
397 | 370 | ||
398 | 371 | ||
diff --git a/apps/gui/gwps.c b/apps/gui/gwps.c index 32a27212a4..5474b302f0 100644 --- a/apps/gui/gwps.c +++ b/apps/gui/gwps.c | |||
@@ -78,6 +78,8 @@ static struct wps_data wps_datas[NB_SCREENS]; | |||
78 | 78 | ||
79 | /* initial setup of wps_data */ | 79 | /* initial setup of wps_data */ |
80 | static void wps_state_init(void); | 80 | static void wps_state_init(void); |
81 | static void track_changed_callback(void *param); | ||
82 | static void nextid3available_callback(void* param); | ||
81 | 83 | ||
82 | static void change_dir(int direction) | 84 | static void change_dir(int direction) |
83 | { | 85 | { |
@@ -246,7 +248,7 @@ long gui_wps_show(void) | |||
246 | long restoretimer = RESTORE_WPS_INSTANTLY; /* timer to delay screen redraw temporarily */ | 248 | long restoretimer = RESTORE_WPS_INSTANTLY; /* timer to delay screen redraw temporarily */ |
247 | bool exit = false; | 249 | bool exit = false; |
248 | bool bookmark = false; | 250 | bool bookmark = false; |
249 | bool update_track = false; | 251 | bool update_track = false, partial_update = false; |
250 | int i; | 252 | int i; |
251 | long last_left = 0, last_right = 0; | 253 | long last_left = 0, last_right = 0; |
252 | wps_state_init(); | 254 | wps_state_init(); |
@@ -651,7 +653,7 @@ long gui_wps_show(void) | |||
651 | restore = true; | 653 | restore = true; |
652 | break; | 654 | break; |
653 | case ACTION_NONE: /* Timeout */ | 655 | case ACTION_NONE: /* Timeout */ |
654 | update_track = true; | 656 | partial_update = true; |
655 | ffwd_rew(button); /* hopefully fix the ffw/rwd bug */ | 657 | ffwd_rew(button); /* hopefully fix the ffw/rwd bug */ |
656 | break; | 658 | break; |
657 | #ifdef HAVE_RECORDING | 659 | #ifdef HAVE_RECORDING |
@@ -671,13 +673,21 @@ long gui_wps_show(void) | |||
671 | break; | 673 | break; |
672 | } | 674 | } |
673 | 675 | ||
674 | if (update_track) | 676 | if (wps_state.do_full_update || partial_update || update_track) |
675 | { | 677 | { |
678 | if (update_track) | ||
679 | { | ||
680 | wps_state.do_full_update = true; | ||
681 | wps_state.id3 = audio_current_track(); | ||
682 | wps_state.nid3 = audio_next_track(); | ||
683 | } | ||
676 | FOR_NB_SCREENS(i) | 684 | FOR_NB_SCREENS(i) |
677 | { | 685 | { |
678 | gui_wps_update(&gui_wps[i]); | 686 | gui_wps_update(&gui_wps[i]); |
679 | } | 687 | } |
688 | wps_state.do_full_update = false; | ||
680 | update_track = false; | 689 | update_track = false; |
690 | partial_update = false; | ||
681 | } | 691 | } |
682 | 692 | ||
683 | if (restore && wps_state.id3 && | 693 | if (restore && wps_state.id3 && |
@@ -723,7 +733,36 @@ long gui_wps_show(void) | |||
723 | return GO_TO_ROOT; /* unreachable - just to reduce compiler warnings */ | 733 | return GO_TO_ROOT; /* unreachable - just to reduce compiler warnings */ |
724 | } | 734 | } |
725 | 735 | ||
726 | /* needs checking if needed end*/ | 736 | /* this is called from the playback thread so NO DRAWING! */ |
737 | static void track_changed_callback(void *param) | ||
738 | { | ||
739 | wps_state.id3 = (struct mp3entry*)param; | ||
740 | wps_state.nid3 = audio_next_track(); | ||
741 | |||
742 | if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type | ||
743 | && strcmp(wps_state.id3->path, curr_cue->audio_filename)) | ||
744 | { | ||
745 | /* the current cuesheet isn't the right one any more */ | ||
746 | /* We need to parse the new cuesheet */ | ||
747 | char cuepath[MAX_PATH]; | ||
748 | |||
749 | if (look_for_cuesheet_file(wps_state.id3->path, cuepath) && | ||
750 | parse_cuesheet(cuepath, curr_cue)) | ||
751 | { | ||
752 | wps_state.id3->cuesheet_type = 1; | ||
753 | strcpy(curr_cue->audio_filename, wps_state.id3->path); | ||
754 | } | ||
755 | |||
756 | cue_spoof_id3(curr_cue, wps_state.id3); | ||
757 | } | ||
758 | wps_state.do_full_update = true; | ||
759 | } | ||
760 | static void nextid3available_callback(void* param) | ||
761 | { | ||
762 | (void)param; | ||
763 | wps_state.nid3 = audio_next_track(); | ||
764 | wps_state.do_full_update = true; | ||
765 | } | ||
727 | 766 | ||
728 | /* wps_state */ | 767 | /* wps_state */ |
729 | 768 | ||
@@ -733,6 +772,10 @@ static void wps_state_init(void) | |||
733 | wps_state.paused = false; | 772 | wps_state.paused = false; |
734 | wps_state.id3 = NULL; | 773 | wps_state.id3 = NULL; |
735 | wps_state.nid3 = NULL; | 774 | wps_state.nid3 = NULL; |
775 | wps_state.do_full_update = true; | ||
776 | /* add the WPS track event callbacks */ | ||
777 | add_event(PLAYBACK_EVENT_TRACK_CHANGE, false, track_changed_callback); | ||
778 | add_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, false, nextid3available_callback); | ||
736 | } | 779 | } |
737 | 780 | ||
738 | /* wps_state end*/ | 781 | /* wps_state end*/ |
diff --git a/apps/gui/gwps.h b/apps/gui/gwps.h index 7888c3944c..1042e1a795 100644 --- a/apps/gui/gwps.h +++ b/apps/gui/gwps.h | |||
@@ -478,6 +478,7 @@ struct wps_state | |||
478 | bool wps_time_countup; | 478 | bool wps_time_countup; |
479 | struct mp3entry* id3; | 479 | struct mp3entry* id3; |
480 | struct mp3entry* nid3; | 480 | struct mp3entry* nid3; |
481 | bool do_full_update; | ||
481 | }; | 482 | }; |
482 | 483 | ||
483 | 484 | ||
diff --git a/apps/gui/wps_parser.c b/apps/gui/wps_parser.c index ba2e2173f1..390df56cbb 100644 --- a/apps/gui/wps_parser.c +++ b/apps/gui/wps_parser.c | |||
@@ -215,16 +215,16 @@ static const struct wps_tag all_tags[] = { | |||
215 | parse_dir_level }, | 215 | parse_dir_level }, |
216 | 216 | ||
217 | /* next file */ | 217 | /* next file */ |
218 | { WPS_TOKEN_FILE_BITRATE, "Fb", WPS_REFRESH_DYNAMIC, NULL }, | 218 | { WPS_TOKEN_FILE_BITRATE, "Fb", WPS_REFRESH_STATIC, NULL }, |
219 | { WPS_TOKEN_FILE_CODEC, "Fc", WPS_REFRESH_DYNAMIC, NULL }, | 219 | { WPS_TOKEN_FILE_CODEC, "Fc", WPS_REFRESH_STATIC, NULL }, |
220 | { WPS_TOKEN_FILE_FREQUENCY, "Ff", WPS_REFRESH_DYNAMIC, NULL }, | 220 | { WPS_TOKEN_FILE_FREQUENCY, "Ff", WPS_REFRESH_STATIC, NULL }, |
221 | { WPS_TOKEN_FILE_FREQUENCY_KHZ, "Fk", WPS_REFRESH_DYNAMIC, NULL }, | 221 | { WPS_TOKEN_FILE_FREQUENCY_KHZ, "Fk", WPS_REFRESH_STATIC, NULL }, |
222 | { WPS_TOKEN_FILE_NAME_WITH_EXTENSION, "Fm", WPS_REFRESH_DYNAMIC, NULL }, | 222 | { WPS_TOKEN_FILE_NAME_WITH_EXTENSION, "Fm", WPS_REFRESH_STATIC, NULL }, |
223 | { WPS_TOKEN_FILE_NAME, "Fn", WPS_REFRESH_DYNAMIC, NULL }, | 223 | { WPS_TOKEN_FILE_NAME, "Fn", WPS_REFRESH_STATIC, NULL }, |
224 | { WPS_TOKEN_FILE_PATH, "Fp", WPS_REFRESH_DYNAMIC, NULL }, | 224 | { WPS_TOKEN_FILE_PATH, "Fp", WPS_REFRESH_STATIC, NULL }, |
225 | { WPS_TOKEN_FILE_SIZE, "Fs", WPS_REFRESH_DYNAMIC, NULL }, | 225 | { WPS_TOKEN_FILE_SIZE, "Fs", WPS_REFRESH_STATIC, NULL }, |
226 | { WPS_TOKEN_FILE_VBR, "Fv", WPS_REFRESH_DYNAMIC, NULL }, | 226 | { WPS_TOKEN_FILE_VBR, "Fv", WPS_REFRESH_STATIC, NULL }, |
227 | { WPS_TOKEN_FILE_DIRECTORY, "D", WPS_REFRESH_DYNAMIC, | 227 | { WPS_TOKEN_FILE_DIRECTORY, "D", WPS_REFRESH_STATIC, |
228 | parse_dir_level }, | 228 | parse_dir_level }, |
229 | 229 | ||
230 | /* current metadata */ | 230 | /* current metadata */ |
@@ -242,18 +242,18 @@ static const struct wps_tag all_tags[] = { | |||
242 | { WPS_TOKEN_METADATA_COMMENT, "iC", WPS_REFRESH_STATIC, NULL }, | 242 | { WPS_TOKEN_METADATA_COMMENT, "iC", WPS_REFRESH_STATIC, NULL }, |
243 | 243 | ||
244 | /* next metadata */ | 244 | /* next metadata */ |
245 | { WPS_TOKEN_METADATA_ARTIST, "Ia", WPS_REFRESH_DYNAMIC, NULL }, | 245 | { WPS_TOKEN_METADATA_ARTIST, "Ia", WPS_REFRESH_STATIC, NULL }, |
246 | { WPS_TOKEN_METADATA_COMPOSER, "Ic", WPS_REFRESH_DYNAMIC, NULL }, | 246 | { WPS_TOKEN_METADATA_COMPOSER, "Ic", WPS_REFRESH_STATIC, NULL }, |
247 | { WPS_TOKEN_METADATA_ALBUM, "Id", WPS_REFRESH_DYNAMIC, NULL }, | 247 | { WPS_TOKEN_METADATA_ALBUM, "Id", WPS_REFRESH_STATIC, NULL }, |
248 | { WPS_TOKEN_METADATA_ALBUM_ARTIST, "IA", WPS_REFRESH_DYNAMIC, NULL }, | 248 | { WPS_TOKEN_METADATA_ALBUM_ARTIST, "IA", WPS_REFRESH_STATIC, NULL }, |
249 | { WPS_TOKEN_METADATA_GROUPING, "IG", WPS_REFRESH_DYNAMIC, NULL }, | 249 | { WPS_TOKEN_METADATA_GROUPING, "IG", WPS_REFRESH_STATIC, NULL }, |
250 | { WPS_TOKEN_METADATA_GENRE, "Ig", WPS_REFRESH_DYNAMIC, NULL }, | 250 | { WPS_TOKEN_METADATA_GENRE, "Ig", WPS_REFRESH_STATIC, NULL }, |
251 | { WPS_TOKEN_METADATA_DISC_NUMBER, "Ik", WPS_REFRESH_DYNAMIC, NULL }, | 251 | { WPS_TOKEN_METADATA_DISC_NUMBER, "Ik", WPS_REFRESH_STATIC, NULL }, |
252 | { WPS_TOKEN_METADATA_TRACK_NUMBER, "In", WPS_REFRESH_DYNAMIC, NULL }, | 252 | { WPS_TOKEN_METADATA_TRACK_NUMBER, "In", WPS_REFRESH_STATIC, NULL }, |
253 | { WPS_TOKEN_METADATA_TRACK_TITLE, "It", WPS_REFRESH_DYNAMIC, NULL }, | 253 | { WPS_TOKEN_METADATA_TRACK_TITLE, "It", WPS_REFRESH_STATIC, NULL }, |
254 | { WPS_TOKEN_METADATA_VERSION, "Iv", WPS_REFRESH_DYNAMIC, NULL }, | 254 | { WPS_TOKEN_METADATA_VERSION, "Iv", WPS_REFRESH_STATIC, NULL }, |
255 | { WPS_TOKEN_METADATA_YEAR, "Iy", WPS_REFRESH_DYNAMIC, NULL }, | 255 | { WPS_TOKEN_METADATA_YEAR, "Iy", WPS_REFRESH_STATIC, NULL }, |
256 | { WPS_TOKEN_METADATA_COMMENT, "IC", WPS_REFRESH_DYNAMIC, NULL }, | 256 | { WPS_TOKEN_METADATA_COMMENT, "IC", WPS_REFRESH_STATIC, NULL }, |
257 | 257 | ||
258 | #if (CONFIG_CODEC != MAS3507D) | 258 | #if (CONFIG_CODEC != MAS3507D) |
259 | { WPS_TOKEN_SOUND_PITCH, "Sp", WPS_REFRESH_DYNAMIC, NULL }, | 259 | { WPS_TOKEN_SOUND_PITCH, "Sp", WPS_REFRESH_DYNAMIC, NULL }, |
diff --git a/apps/iap.c b/apps/iap.c index dd29563b1e..4d0c473800 100644 --- a/apps/iap.c +++ b/apps/iap.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "system.h" | 29 | #include "system.h" |
30 | #include "kernel.h" | 30 | #include "kernel.h" |
31 | #include "serial.h" | 31 | #include "serial.h" |
32 | #include "appevents.h" | ||
32 | 33 | ||
33 | #include "playlist.h" | 34 | #include "playlist.h" |
34 | #include "playback.h" | 35 | #include "playback.h" |
@@ -80,6 +81,7 @@ void iap_setup(int ratenum) | |||
80 | iap_setupflag = true; | 81 | iap_setupflag = true; |
81 | iap_remotebtn = BUTTON_NONE; | 82 | iap_remotebtn = BUTTON_NONE; |
82 | tick_add_task(iap_task); | 83 | tick_add_task(iap_task); |
84 | add_event(PLAYBACK_EVENT_TRACK_CHANGE, false, iap_track_changed); | ||
83 | } | 85 | } |
84 | 86 | ||
85 | void iap_bitrate_set(int ratenum) | 87 | void iap_bitrate_set(int ratenum) |
@@ -175,8 +177,10 @@ int iap_getc(unsigned char x) | |||
175 | return newpkt; | 177 | return newpkt; |
176 | } | 178 | } |
177 | 179 | ||
178 | void iap_track_changed(void) | 180 | /* called by playback when the next track starts */ |
181 | void iap_track_changed(void *ignored) | ||
179 | { | 182 | { |
183 | (void)ignored; | ||
180 | iap_changedctr = 1; | 184 | iap_changedctr = 1; |
181 | } | 185 | } |
182 | 186 | ||
diff --git a/apps/mpeg.c b/apps/mpeg.c index cde72ab54f..5ebf58fcf0 100644 --- a/apps/mpeg.c +++ b/apps/mpeg.c | |||
@@ -852,6 +852,7 @@ static void transfer_end(unsigned char** ppbuf, size_t* psize) | |||
852 | static struct trackdata *add_track_to_tag_list(const char *filename) | 852 | static struct trackdata *add_track_to_tag_list(const char *filename) |
853 | { | 853 | { |
854 | struct trackdata *track; | 854 | struct trackdata *track; |
855 | bool send_nid3_event; | ||
855 | 856 | ||
856 | if(num_tracks_in_memory() >= MAX_TRACK_ENTRIES) | 857 | if(num_tracks_in_memory() >= MAX_TRACK_ENTRIES) |
857 | { | 858 | { |
@@ -882,7 +883,11 @@ static struct trackdata *add_track_to_tag_list(const char *filename) | |||
882 | if (cuesheet_callback(filename)) | 883 | if (cuesheet_callback(filename)) |
883 | track->id3.cuesheet_type = 1; | 884 | track->id3.cuesheet_type = 1; |
884 | 885 | ||
886 | /* if this track is the next track then let the UI know it can get it */ | ||
887 | send_nid3_event = (track_write_idx == track_read_idx + 1); | ||
885 | track_write_idx = (track_write_idx+1) & MAX_TRACK_ENTRIES_MASK; | 888 | track_write_idx = (track_write_idx+1) & MAX_TRACK_ENTRIES_MASK; |
889 | if (send_nid3_event) | ||
890 | send_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, NULL); | ||
886 | debug_tags(); | 891 | debug_tags(); |
887 | return track; | 892 | return track; |
888 | } | 893 | } |
diff --git a/apps/playback.c b/apps/playback.c index 11f76d4db8..3709b407fa 100644 --- a/apps/playback.c +++ b/apps/playback.c | |||
@@ -201,14 +201,15 @@ size_t filebuflen = 0; /* Size of buffer (A/C-) */ | |||
201 | /* Possible arrangements of the buffer */ | 201 | /* Possible arrangements of the buffer */ |
202 | static int buffer_state = AUDIOBUF_STATE_TRASHED; /* Buffer state */ | 202 | static int buffer_state = AUDIOBUF_STATE_TRASHED; /* Buffer state */ |
203 | 203 | ||
204 | /* Used to keep the WPS up-to-date during track transtition */ | 204 | /* These are used to store the current and next (or prev if the current is the last) |
205 | static struct mp3entry prevtrack_id3; | 205 | * mp3entry's in a round-robin system. This guarentees that the pointer returned |
206 | 206 | * by audio_current/next_track will be valid for the full duration of the | |
207 | /* Used to provide the codec with a pointer */ | 207 | * currently playing track */ |
208 | static struct mp3entry curtrack_id3; | 208 | static struct mp3entry mp3entry_buf[2]; |
209 | 209 | static struct mp3entry *thistrack_id3, /* the currently playing track */ | |
210 | /* Used to make next track info available while playing last track on buffer */ | 210 | *othertrack_id3; /* prev track during track-change-transition, or end of playlist, |
211 | static struct mp3entry lasttrack_id3; | 211 | * next track otherwise */ |
212 | static struct mp3entry unbuffered_id3; /* the id3 for the first unbuffered track */ | ||
212 | 213 | ||
213 | /* Track info structure about songs in the file buffer (A/C-) */ | 214 | /* Track info structure about songs in the file buffer (A/C-) */ |
214 | struct track_info { | 215 | struct track_info { |
@@ -232,10 +233,6 @@ static int track_widx = 0; /* Track being buffered (A) */ | |||
232 | static struct track_info *prev_ti = NULL; /* Pointer to the previously played | 233 | static struct track_info *prev_ti = NULL; /* Pointer to the previously played |
233 | track */ | 234 | track */ |
234 | 235 | ||
235 | /* Set by the audio thread when the current track information has updated | ||
236 | * and the WPS may need to update its cached information */ | ||
237 | static bool track_changed = false; | ||
238 | |||
239 | /* Information used only for filling the buffer */ | 236 | /* Information used only for filling the buffer */ |
240 | /* Playlist steps from playing track to next track to be buffered (A) */ | 237 | /* Playlist steps from playing track to next track to be buffered (A) */ |
241 | static int last_peek_offset = 0; | 238 | static int last_peek_offset = 0; |
@@ -567,24 +564,25 @@ struct mp3entry* audio_current_track(void) | |||
567 | 564 | ||
568 | cur_idx = (track_ridx + offset) & MAX_TRACK_MASK; | 565 | cur_idx = (track_ridx + offset) & MAX_TRACK_MASK; |
569 | 566 | ||
570 | if (cur_idx == track_ridx && *curtrack_id3.path) | 567 | if (cur_idx == track_ridx && *thistrack_id3->path) |
571 | { | 568 | { |
572 | /* The usual case */ | 569 | /* The usual case */ |
573 | return &curtrack_id3; | 570 | return thistrack_id3; |
574 | } | 571 | } |
575 | else if (automatic_skip && offset == -1 && *prevtrack_id3.path) | 572 | else if (automatic_skip && offset == -1 && *othertrack_id3->path) |
576 | { | 573 | { |
577 | /* We're in a track transition. The codec has moved on to the nex track, | 574 | /* We're in a track transition. The codec has moved on to the next track, |
578 | but the audio being played is still the same (now previous) track. | 575 | but the audio being played is still the same (now previous) track. |
579 | prevtrack_id3.elapsed is being updated in an ISR by | 576 | othertrack_id3.elapsed is being updated in an ISR by |
580 | codec_pcmbuf_position_callback */ | 577 | codec_pcmbuf_position_callback */ |
581 | return &prevtrack_id3; | 578 | return othertrack_id3; |
582 | } | 579 | } |
583 | else if (tracks[cur_idx].id3_hid >= 0) | 580 | else if (tracks[cur_idx].id3_hid >= 0) |
584 | { | 581 | { |
585 | /* Get the ID3 metadata from the main buffer */ | 582 | /* The current track's info has been buffered but not read yet, so get it */ |
586 | struct mp3entry *ret = bufgetid3(tracks[cur_idx].id3_hid); | 583 | if (bufread(tracks[cur_idx].id3_hid, sizeof(struct mp3entry), &temp_id3) |
587 | if (ret) return ret; | 584 | == sizeof(struct mp3entry)) |
585 | return &temp_id3; | ||
588 | } | 586 | } |
589 | 587 | ||
590 | /* We didn't find the ID3 metadata, so we fill temp_id3 with the little info | 588 | /* We didn't find the ID3 metadata, so we fill temp_id3 with the little info |
@@ -620,42 +618,34 @@ struct mp3entry* audio_next_track(void) | |||
620 | if (!audio_have_tracks()) | 618 | if (!audio_have_tracks()) |
621 | return NULL; | 619 | return NULL; |
622 | 620 | ||
623 | if (wps_offset == -1 && *prevtrack_id3.path) | 621 | if (wps_offset == -1 && *thistrack_id3->path) |
624 | { | 622 | { |
625 | /* We're in a track transition. The next track for the WPS is the one | 623 | /* We're in a track transition. The next track for the WPS is the one |
626 | currently being decoded. */ | 624 | currently being decoded. */ |
627 | return &curtrack_id3; | 625 | return thistrack_id3; |
628 | } | 626 | } |
629 | 627 | ||
630 | next_idx = (track_ridx + offset + 1) & MAX_TRACK_MASK; | 628 | next_idx = (track_ridx + offset + 1) & MAX_TRACK_MASK; |
631 | 629 | ||
632 | if (tracks[next_idx].id3_hid >= 0) | 630 | if (tracks[next_idx].id3_hid >= 0) |
633 | return bufgetid3(tracks[next_idx].id3_hid); | 631 | { |
632 | if (bufread(tracks[next_idx].id3_hid, sizeof(struct mp3entry), othertrack_id3) | ||
633 | == sizeof(struct mp3entry)) | ||
634 | return othertrack_id3; | ||
635 | else | ||
636 | return NULL; | ||
637 | } | ||
634 | 638 | ||
635 | if (next_idx == track_widx) | 639 | if (next_idx == track_widx) |
636 | { | 640 | { |
637 | /* The next track hasn't been buffered yet, so we return the static | 641 | /* The next track hasn't been buffered yet, so we return the static |
638 | version of its metadata. */ | 642 | version of its metadata. */ |
639 | return &lasttrack_id3; | 643 | return &unbuffered_id3; |
640 | } | 644 | } |
641 | 645 | ||
642 | return NULL; | 646 | return NULL; |
643 | } | 647 | } |
644 | 648 | ||
645 | bool audio_has_changed_track(void) | ||
646 | { | ||
647 | if (track_changed) | ||
648 | { | ||
649 | #ifdef IPOD_ACCESSORY_PROTOCOL | ||
650 | iap_track_changed(); | ||
651 | #endif | ||
652 | track_changed = false; | ||
653 | return true; | ||
654 | } | ||
655 | |||
656 | return false; | ||
657 | } | ||
658 | |||
659 | void audio_play(long offset) | 649 | void audio_play(long offset) |
660 | { | 650 | { |
661 | logf("audio_play"); | 651 | logf("audio_play"); |
@@ -705,7 +695,6 @@ void audio_skip(int direction) | |||
705 | queue_post(&audio_queue, Q_AUDIO_SKIP, direction); | 695 | queue_post(&audio_queue, Q_AUDIO_SKIP, direction); |
706 | /* Update wps while our message travels inside deep playback queues. */ | 696 | /* Update wps while our message travels inside deep playback queues. */ |
707 | wps_offset += direction; | 697 | wps_offset += direction; |
708 | track_changed = true; | ||
709 | } | 698 | } |
710 | else | 699 | else |
711 | { | 700 | { |
@@ -823,7 +812,7 @@ void audio_set_crossfade(int enable) | |||
823 | if (was_playing) | 812 | if (was_playing) |
824 | { | 813 | { |
825 | /* Store the track resume position */ | 814 | /* Store the track resume position */ |
826 | offset = curtrack_id3.offset; | 815 | offset = thistrack_id3->offset; |
827 | } | 816 | } |
828 | 817 | ||
829 | /* Blast it - audio buffer will have to be setup again next time | 818 | /* Blast it - audio buffer will have to be setup again next time |
@@ -963,15 +952,15 @@ static void codec_pcmbuf_position_callback(size_t size) | |||
963 | { | 952 | { |
964 | /* This is called from an ISR, so be quick */ | 953 | /* This is called from an ISR, so be quick */ |
965 | unsigned int time = size * 1000 / 4 / NATIVE_FREQUENCY + | 954 | unsigned int time = size * 1000 / 4 / NATIVE_FREQUENCY + |
966 | prevtrack_id3.elapsed; | 955 | othertrack_id3->elapsed; |
967 | 956 | ||
968 | if (time >= prevtrack_id3.length) | 957 | if (time >= othertrack_id3->length) |
969 | { | 958 | { |
970 | pcmbuf_set_position_callback(NULL); | 959 | pcmbuf_set_position_callback(NULL); |
971 | prevtrack_id3.elapsed = prevtrack_id3.length; | 960 | othertrack_id3->elapsed = othertrack_id3->length; |
972 | } | 961 | } |
973 | else | 962 | else |
974 | prevtrack_id3.elapsed = time; | 963 | othertrack_id3->elapsed = time; |
975 | } | 964 | } |
976 | 965 | ||
977 | static void codec_set_elapsed_callback(unsigned int value) | 966 | static void codec_set_elapsed_callback(unsigned int value) |
@@ -986,11 +975,11 @@ static void codec_set_elapsed_callback(unsigned int value) | |||
986 | 975 | ||
987 | latency = pcmbuf_get_latency(); | 976 | latency = pcmbuf_get_latency(); |
988 | if (value < latency) | 977 | if (value < latency) |
989 | curtrack_id3.elapsed = 0; | 978 | thistrack_id3->elapsed = 0; |
990 | else if (value - latency > curtrack_id3.elapsed || | 979 | else if (value - latency > thistrack_id3->elapsed || |
991 | value - latency < curtrack_id3.elapsed - 2) | 980 | value - latency < thistrack_id3->elapsed - 2) |
992 | { | 981 | { |
993 | curtrack_id3.elapsed = value - latency; | 982 | thistrack_id3->elapsed = value - latency; |
994 | } | 983 | } |
995 | } | 984 | } |
996 | 985 | ||
@@ -1001,11 +990,11 @@ static void codec_set_offset_callback(size_t value) | |||
1001 | if (ci.seek_time) | 990 | if (ci.seek_time) |
1002 | return; | 991 | return; |
1003 | 992 | ||
1004 | latency = pcmbuf_get_latency() * curtrack_id3.bitrate / 8; | 993 | latency = pcmbuf_get_latency() * thistrack_id3->bitrate / 8; |
1005 | if (value < latency) | 994 | if (value < latency) |
1006 | curtrack_id3.offset = 0; | 995 | thistrack_id3->offset = 0; |
1007 | else | 996 | else |
1008 | curtrack_id3.offset = value - latency; | 997 | thistrack_id3->offset = value - latency; |
1009 | } | 998 | } |
1010 | 999 | ||
1011 | static void codec_advance_buffer_counters(size_t amount) | 1000 | static void codec_advance_buffer_counters(size_t amount) |
@@ -1197,7 +1186,7 @@ static bool codec_load_next_track(void) | |||
1197 | { | 1186 | { |
1198 | intptr_t result = Q_CODEC_REQUEST_FAILED; | 1187 | intptr_t result = Q_CODEC_REQUEST_FAILED; |
1199 | 1188 | ||
1200 | prev_track_elapsed = curtrack_id3.elapsed; | 1189 | prev_track_elapsed = thistrack_id3->elapsed; |
1201 | 1190 | ||
1202 | #ifdef AB_REPEAT_ENABLE | 1191 | #ifdef AB_REPEAT_ENABLE |
1203 | ab_end_of_track_report(); | 1192 | ab_end_of_track_report(); |
@@ -1247,18 +1236,16 @@ static bool codec_request_next_track_callback(void) | |||
1247 | if (ci.stop_codec || !playing) | 1236 | if (ci.stop_codec || !playing) |
1248 | return false; | 1237 | return false; |
1249 | 1238 | ||
1250 | prev_codectype = get_codec_base_type(curtrack_id3.codectype); | 1239 | prev_codectype = get_codec_base_type(thistrack_id3->codectype); |
1251 | |||
1252 | if (!codec_load_next_track()) | 1240 | if (!codec_load_next_track()) |
1253 | return false; | 1241 | return false; |
1254 | 1242 | ||
1255 | /* Seek to the beginning of the new track because if the struct | 1243 | /* Seek to the beginning of the new track because if the struct |
1256 | mp3entry was buffered, "elapsed" might not be zero (if the track has | 1244 | mp3entry was buffered, "elapsed" might not be zero (if the track has |
1257 | been played already but not unbuffered) */ | 1245 | been played already but not unbuffered) */ |
1258 | codec_seek_buffer_callback(curtrack_id3.first_frame_offset); | 1246 | codec_seek_buffer_callback(thistrack_id3->first_frame_offset); |
1259 | |||
1260 | /* Check if the next codec is the same file. */ | 1247 | /* Check if the next codec is the same file. */ |
1261 | if (prev_codectype == get_codec_base_type(curtrack_id3.codectype)) | 1248 | if (prev_codectype == get_codec_base_type(thistrack_id3->codectype)) |
1262 | { | 1249 | { |
1263 | logf("New track loaded"); | 1250 | logf("New track loaded"); |
1264 | codec_discard_codec_callback(); | 1251 | codec_discard_codec_callback(); |
@@ -1266,7 +1253,7 @@ static bool codec_request_next_track_callback(void) | |||
1266 | } | 1253 | } |
1267 | else | 1254 | else |
1268 | { | 1255 | { |
1269 | logf("New codec:%d/%d", curtrack_id3.codectype, prev_codectype); | 1256 | logf("New codec:%d/%d", thistrack_id3->codectype, prev_codectype); |
1270 | return false; | 1257 | return false; |
1271 | } | 1258 | } |
1272 | } | 1259 | } |
@@ -1293,6 +1280,7 @@ static void codec_thread(void) | |||
1293 | audio_codec_loaded = true; | 1280 | audio_codec_loaded = true; |
1294 | ci.stop_codec = false; | 1281 | ci.stop_codec = false; |
1295 | status = codec_load_file((const char *)ev.data, &ci); | 1282 | status = codec_load_file((const char *)ev.data, &ci); |
1283 | LOGFQUEUE("codec_load_file %s %d\n", (const char *)ev.data, status); | ||
1296 | break; | 1284 | break; |
1297 | 1285 | ||
1298 | case Q_CODEC_LOAD: | 1286 | case Q_CODEC_LOAD: |
@@ -1312,6 +1300,7 @@ static void codec_thread(void) | |||
1312 | audio_codec_loaded = true; | 1300 | audio_codec_loaded = true; |
1313 | ci.stop_codec = false; | 1301 | ci.stop_codec = false; |
1314 | status = codec_load_buf(CUR_TI->codec_hid, &ci); | 1302 | status = codec_load_buf(CUR_TI->codec_hid, &ci); |
1303 | LOGFQUEUE("codec_load_buf %d\n", status); | ||
1315 | break; | 1304 | break; |
1316 | 1305 | ||
1317 | case Q_CODEC_DO_CALLBACK: | 1306 | case Q_CODEC_DO_CALLBACK: |
@@ -1362,7 +1351,7 @@ static void codec_thread(void) | |||
1362 | { | 1351 | { |
1363 | if (!ci.new_track) | 1352 | if (!ci.new_track) |
1364 | { | 1353 | { |
1365 | logf("Codec failure"); | 1354 | logf("Codec failure, %d %d", ci.new_track, status); |
1366 | splash(HZ*2, "Codec failure"); | 1355 | splash(HZ*2, "Codec failure"); |
1367 | } | 1356 | } |
1368 | 1357 | ||
@@ -1383,8 +1372,10 @@ static void codec_thread(void) | |||
1383 | * triggering the WPS exit */ | 1372 | * triggering the WPS exit */ |
1384 | while(pcm_is_playing()) | 1373 | while(pcm_is_playing()) |
1385 | { | 1374 | { |
1386 | curtrack_id3.elapsed = | 1375 | /* There has been one too many struct pointer swaps by now |
1387 | curtrack_id3.length - pcmbuf_get_latency(); | 1376 | * so even though it says othertrack_id3, its the correct one! */ |
1377 | othertrack_id3->elapsed = | ||
1378 | othertrack_id3->length - pcmbuf_get_latency(); | ||
1388 | sleep(1); | 1379 | sleep(1); |
1389 | } | 1380 | } |
1390 | 1381 | ||
@@ -1405,7 +1396,7 @@ static void codec_thread(void) | |||
1405 | else | 1396 | else |
1406 | { | 1397 | { |
1407 | const char *codec_fn = | 1398 | const char *codec_fn = |
1408 | get_codec_filename(curtrack_id3.codectype); | 1399 | get_codec_filename(thistrack_id3->codectype); |
1409 | if (codec_fn) | 1400 | if (codec_fn) |
1410 | { | 1401 | { |
1411 | LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK"); | 1402 | LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK"); |
@@ -1481,10 +1472,14 @@ static void buffering_handle_finished_callback(int *data) | |||
1481 | 1472 | ||
1482 | if (*data == tracks[track_widx].id3_hid) | 1473 | if (*data == tracks[track_widx].id3_hid) |
1483 | { | 1474 | { |
1475 | int offset = ci.new_track + wps_offset; | ||
1476 | int next_idx = (track_ridx + offset + 1) & MAX_TRACK_MASK; | ||
1484 | /* The metadata handle for the last loaded track has been buffered. | 1477 | /* The metadata handle for the last loaded track has been buffered. |
1485 | We can ask the audio thread to load the rest of the track's data. */ | 1478 | We can ask the audio thread to load the rest of the track's data. */ |
1486 | LOGFQUEUE("audio >| audio Q_AUDIO_FINISH_LOAD"); | 1479 | LOGFQUEUE("audio >| audio Q_AUDIO_FINISH_LOAD"); |
1487 | queue_post(&audio_queue, Q_AUDIO_FINISH_LOAD, 0); | 1480 | queue_post(&audio_queue, Q_AUDIO_FINISH_LOAD, 0); |
1481 | if (tracks[next_idx].id3_hid == *data) | ||
1482 | send_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, NULL); | ||
1488 | } | 1483 | } |
1489 | else | 1484 | else |
1490 | { | 1485 | { |
@@ -1534,15 +1529,15 @@ static void audio_update_trackinfo(void) | |||
1534 | { | 1529 | { |
1535 | /* Load the curent track's metadata into curtrack_id3 */ | 1530 | /* Load the curent track's metadata into curtrack_id3 */ |
1536 | if (CUR_TI->id3_hid >= 0) | 1531 | if (CUR_TI->id3_hid >= 0) |
1537 | copy_mp3entry(&curtrack_id3, bufgetid3(CUR_TI->id3_hid)); | 1532 | copy_mp3entry(thistrack_id3, bufgetid3(CUR_TI->id3_hid)); |
1538 | 1533 | ||
1539 | /* Reset current position */ | 1534 | /* Reset current position */ |
1540 | curtrack_id3.elapsed = 0; | 1535 | thistrack_id3->elapsed = 0; |
1541 | curtrack_id3.offset = 0; | 1536 | thistrack_id3->offset = 0; |
1542 | 1537 | ||
1543 | /* Update the codec API */ | 1538 | /* Update the codec API */ |
1544 | ci.filesize = CUR_TI->filesize; | 1539 | ci.filesize = CUR_TI->filesize; |
1545 | ci.id3 = &curtrack_id3; | 1540 | ci.id3 = thistrack_id3; |
1546 | ci.curpos = 0; | 1541 | ci.curpos = 0; |
1547 | ci.taginfo_ready = &CUR_TI->taginfo_ready; | 1542 | ci.taginfo_ready = &CUR_TI->taginfo_ready; |
1548 | } | 1543 | } |
@@ -1608,7 +1603,7 @@ static bool audio_loadcodec(bool start_play) | |||
1608 | /* Load the codec directly from disk and save some memory. */ | 1603 | /* Load the codec directly from disk and save some memory. */ |
1609 | track_ridx = track_widx; | 1604 | track_ridx = track_widx; |
1610 | ci.filesize = CUR_TI->filesize; | 1605 | ci.filesize = CUR_TI->filesize; |
1611 | ci.id3 = &curtrack_id3; | 1606 | ci.id3 = thistrack_id3; |
1612 | ci.taginfo_ready = &CUR_TI->taginfo_ready; | 1607 | ci.taginfo_ready = &CUR_TI->taginfo_ready; |
1613 | ci.curpos = 0; | 1608 | ci.curpos = 0; |
1614 | LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK"); | 1609 | LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK"); |
@@ -1698,10 +1693,10 @@ static bool audio_load_track(size_t offset, bool start_play) | |||
1698 | if (!trackname) | 1693 | if (!trackname) |
1699 | { | 1694 | { |
1700 | logf("End-of-playlist"); | 1695 | logf("End-of-playlist"); |
1701 | memset(&lasttrack_id3, 0, sizeof(struct mp3entry)); | 1696 | memset(&unbuffered_id3, 0, sizeof(struct mp3entry)); |
1702 | filling = STATE_END_OF_PLAYLIST; | 1697 | filling = STATE_END_OF_PLAYLIST; |
1703 | 1698 | ||
1704 | if (curtrack_id3.length == 0 && curtrack_id3.filesize == 0) | 1699 | if (thistrack_id3->length == 0 && thistrack_id3->filesize == 0) |
1705 | { | 1700 | { |
1706 | /* Stop playback if no valid track was found. */ | 1701 | /* Stop playback if no valid track was found. */ |
1707 | audio_stop_playback(); | 1702 | audio_stop_playback(); |
@@ -1720,7 +1715,6 @@ static bool audio_load_track(size_t offset, bool start_play) | |||
1720 | { | 1715 | { |
1721 | buf_set_watermark(filebuflen/2); | 1716 | buf_set_watermark(filebuflen/2); |
1722 | dsp_configure(ci.dsp, DSP_RESET, 0); | 1717 | dsp_configure(ci.dsp, DSP_RESET, 0); |
1723 | track_changed = true; | ||
1724 | playlist_update_resume_info(audio_current_track()); | 1718 | playlist_update_resume_info(audio_current_track()); |
1725 | } | 1719 | } |
1726 | 1720 | ||
@@ -1732,7 +1726,7 @@ static bool audio_load_track(size_t offset, bool start_play) | |||
1732 | if (tracks[track_widx].id3_hid < 0) | 1726 | if (tracks[track_widx].id3_hid < 0) |
1733 | { | 1727 | { |
1734 | /* Buffer is full. */ | 1728 | /* Buffer is full. */ |
1735 | get_metadata(&lasttrack_id3, fd, trackname); | 1729 | get_metadata(&unbuffered_id3, fd, trackname); |
1736 | last_peek_offset--; | 1730 | last_peek_offset--; |
1737 | close(fd); | 1731 | close(fd); |
1738 | logf("buffer is full for now"); | 1732 | logf("buffer is full for now"); |
@@ -1744,13 +1738,18 @@ static bool audio_load_track(size_t offset, bool start_play) | |||
1744 | { | 1738 | { |
1745 | /* TODO: Superfluos buffering call? */ | 1739 | /* TODO: Superfluos buffering call? */ |
1746 | buf_request_buffer_handle(tracks[track_widx].id3_hid); | 1740 | buf_request_buffer_handle(tracks[track_widx].id3_hid); |
1747 | copy_mp3entry(&curtrack_id3, bufgetid3(tracks[track_widx].id3_hid)); | 1741 | struct mp3entry *id3 = bufgetid3(tracks[track_widx].id3_hid); |
1748 | curtrack_id3.offset = offset; | 1742 | if (id3) |
1743 | { | ||
1744 | copy_mp3entry(thistrack_id3, id3); | ||
1745 | thistrack_id3->offset = offset; | ||
1746 | } | ||
1747 | else | ||
1748 | memset(thistrack_id3, 0, sizeof(struct mp3entry)); | ||
1749 | } | 1749 | } |
1750 | 1750 | ||
1751 | if (start_play) | 1751 | if (start_play) |
1752 | { | 1752 | { |
1753 | track_changed = true; | ||
1754 | playlist_update_resume_info(audio_current_track()); | 1753 | playlist_update_resume_info(audio_current_track()); |
1755 | } | 1754 | } |
1756 | } | 1755 | } |
@@ -1780,7 +1779,7 @@ static void audio_finish_load_track(void) | |||
1780 | struct mp3entry *track_id3; | 1779 | struct mp3entry *track_id3; |
1781 | 1780 | ||
1782 | if (track_widx == track_ridx) | 1781 | if (track_widx == track_ridx) |
1783 | track_id3 = &curtrack_id3; | 1782 | track_id3 = thistrack_id3; |
1784 | else | 1783 | else |
1785 | track_id3 = bufgetid3(tracks[track_widx].id3_hid); | 1784 | track_id3 = bufgetid3(tracks[track_widx].id3_hid); |
1786 | 1785 | ||
@@ -1935,8 +1934,6 @@ static void audio_finish_load_track(void) | |||
1935 | 1934 | ||
1936 | static void audio_fill_file_buffer(bool start_play, size_t offset) | 1935 | static void audio_fill_file_buffer(bool start_play, size_t offset) |
1937 | { | 1936 | { |
1938 | bool had_next_track = audio_next_track() != NULL; | ||
1939 | |||
1940 | filling = STATE_FILLING; | 1937 | filling = STATE_FILLING; |
1941 | trigger_cpu_boost(); | 1938 | trigger_cpu_boost(); |
1942 | 1939 | ||
@@ -1959,9 +1956,6 @@ static void audio_fill_file_buffer(bool start_play, size_t offset) | |||
1959 | playlist_update_resume_info(audio_current_track()); | 1956 | playlist_update_resume_info(audio_current_track()); |
1960 | 1957 | ||
1961 | audio_load_track(offset, start_play); | 1958 | audio_load_track(offset, start_play); |
1962 | |||
1963 | if (!had_next_track && audio_next_track()) | ||
1964 | track_changed = true; | ||
1965 | } | 1959 | } |
1966 | 1960 | ||
1967 | static void audio_rebuffer(void) | 1961 | static void audio_rebuffer(void) |
@@ -1982,7 +1976,7 @@ static void audio_rebuffer(void) | |||
1982 | ci.curpos = 0; | 1976 | ci.curpos = 0; |
1983 | 1977 | ||
1984 | if (!CUR_TI->taginfo_ready) | 1978 | if (!CUR_TI->taginfo_ready) |
1985 | memset(&curtrack_id3, 0, sizeof(struct mp3entry)); | 1979 | memset(thistrack_id3, 0, sizeof(struct mp3entry)); |
1986 | 1980 | ||
1987 | audio_fill_file_buffer(false, 0); | 1981 | audio_fill_file_buffer(false, 0); |
1988 | } | 1982 | } |
@@ -1995,9 +1989,16 @@ static int audio_check_new_track(void) | |||
1995 | int old_track_ridx = track_ridx; | 1989 | int old_track_ridx = track_ridx; |
1996 | int i, idx; | 1990 | int i, idx; |
1997 | bool forward; | 1991 | bool forward; |
1992 | struct mp3entry *temp = thistrack_id3; | ||
1998 | 1993 | ||
1999 | /* Now it's good time to send track finish events. */ | 1994 | /* Now it's good time to send track finish events. */ |
2000 | send_event(PLAYBACK_EVENT_TRACK_FINISH, &curtrack_id3); | 1995 | send_event(PLAYBACK_EVENT_TRACK_FINISH, thistrack_id3); |
1996 | /* swap the mp3entry pointers */ | ||
1997 | thistrack_id3 = othertrack_id3; | ||
1998 | othertrack_id3 = temp; | ||
1999 | ci.id3 = thistrack_id3; | ||
2000 | memset(thistrack_id3, 0, sizeof(struct mp3entry)); | ||
2001 | |||
2001 | if (dir_skip) | 2002 | if (dir_skip) |
2002 | { | 2003 | { |
2003 | dir_skip = false; | 2004 | dir_skip = false; |
@@ -2035,22 +2036,23 @@ static int audio_check_new_track(void) | |||
2035 | LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED"); | 2036 | LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED"); |
2036 | return Q_CODEC_REQUEST_FAILED; | 2037 | return Q_CODEC_REQUEST_FAILED; |
2037 | } | 2038 | } |
2038 | 2039 | ||
2039 | if (new_playlist) | 2040 | if (new_playlist) |
2040 | { | 2041 | { |
2041 | ci.new_track = 1; | 2042 | ci.new_track = 1; |
2042 | new_playlist = false; | 2043 | new_playlist = false; |
2043 | } | 2044 | } |
2044 | 2045 | ||
2045 | /* Save the track metadata to allow the WPS to display it | 2046 | /* FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME |
2046 | while PCM finishes playing that track */ | 2047 | * 1) why are we doing this? |
2047 | copy_mp3entry(&prevtrack_id3, &curtrack_id3); | 2048 | * 2) thistrack_id3 has already been cleared anyway */ |
2048 | |||
2049 | /* Update the main buffer copy of the track metadata with the one | 2049 | /* Update the main buffer copy of the track metadata with the one |
2050 | the codec has been using (for the unbuffer callbacks) */ | 2050 | the codec has been using (for the unbuffer callbacks) */ |
2051 | if (CUR_TI->id3_hid >= 0) | 2051 | if (CUR_TI->id3_hid >= 0) |
2052 | copy_mp3entry(bufgetid3(CUR_TI->id3_hid), &curtrack_id3); | 2052 | copy_mp3entry(bufgetid3(CUR_TI->id3_hid), thistrack_id3); |
2053 | 2053 | /* FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME */ | |
2054 | |||
2055 | |||
2054 | /* Save a pointer to the old track to allow later clearing */ | 2056 | /* Save a pointer to the old track to allow later clearing */ |
2055 | prev_ti = CUR_TI; | 2057 | prev_ti = CUR_TI; |
2056 | 2058 | ||
@@ -2079,7 +2081,6 @@ static int audio_check_new_track(void) | |||
2079 | if (automatic_skip) | 2081 | if (automatic_skip) |
2080 | { | 2082 | { |
2081 | wps_offset = -ci.new_track; | 2083 | wps_offset = -ci.new_track; |
2082 | track_changed = true; | ||
2083 | } | 2084 | } |
2084 | 2085 | ||
2085 | /* If it is not safe to even skip this many track entries */ | 2086 | /* If it is not safe to even skip this many track entries */ |
@@ -2185,7 +2186,7 @@ static void audio_stop_playback(void) | |||
2185 | 2186 | ||
2186 | /* TODO: Create auto bookmark too? */ | 2187 | /* TODO: Create auto bookmark too? */ |
2187 | 2188 | ||
2188 | prev_track_elapsed = curtrack_id3.elapsed; | 2189 | prev_track_elapsed = othertrack_id3->elapsed; |
2189 | 2190 | ||
2190 | remove_event(BUFFER_EVENT_BUFFER_LOW, buffering_low_buffer_callback); | 2191 | remove_event(BUFFER_EVENT_BUFFER_LOW, buffering_low_buffer_callback); |
2191 | } | 2192 | } |
@@ -2202,8 +2203,6 @@ static void audio_stop_playback(void) | |||
2202 | 2203 | ||
2203 | /* Close all tracks */ | 2204 | /* Close all tracks */ |
2204 | audio_release_tracks(); | 2205 | audio_release_tracks(); |
2205 | |||
2206 | memset(&curtrack_id3, 0, sizeof(struct mp3entry)); | ||
2207 | } | 2206 | } |
2208 | 2207 | ||
2209 | static void audio_play_start(size_t offset) | 2208 | static void audio_play_start(size_t offset) |
@@ -2219,8 +2218,6 @@ static void audio_play_start(size_t offset) | |||
2219 | paused = false; | 2218 | paused = false; |
2220 | audio_stop_codec_flush(); | 2219 | audio_stop_codec_flush(); |
2221 | 2220 | ||
2222 | track_changed = true; | ||
2223 | |||
2224 | playing = true; | 2221 | playing = true; |
2225 | track_load_started = false; | 2222 | track_load_started = false; |
2226 | 2223 | ||
@@ -2325,25 +2322,15 @@ static void audio_finalise_track_change(void) | |||
2325 | automatic_skip = false; | 2322 | automatic_skip = false; |
2326 | 2323 | ||
2327 | /* Invalidate prevtrack_id3 */ | 2324 | /* Invalidate prevtrack_id3 */ |
2328 | prevtrack_id3.path[0] = 0; | 2325 | memset(othertrack_id3, 0, sizeof(struct mp3entry)); |
2329 | 2326 | ||
2330 | if (prev_ti && prev_ti->audio_hid < 0) | 2327 | if (prev_ti && prev_ti->audio_hid < 0) |
2331 | { | 2328 | { |
2332 | /* No audio left so we clear all the track info. */ | 2329 | /* No audio left so we clear all the track info. */ |
2333 | clear_track_info(prev_ti); | 2330 | clear_track_info(prev_ti); |
2334 | } | 2331 | } |
2335 | |||
2336 | if (prev_ti && prev_ti->id3_hid >= 0) | ||
2337 | { | ||
2338 | /* Reset the elapsed time to force the progressbar to be empty if | ||
2339 | the user skips back to this track */ | ||
2340 | bufgetid3(prev_ti->id3_hid)->elapsed = 0; | ||
2341 | } | ||
2342 | } | 2332 | } |
2343 | 2333 | send_event(PLAYBACK_EVENT_TRACK_CHANGE, thistrack_id3); | |
2344 | send_event(PLAYBACK_EVENT_TRACK_CHANGE, &curtrack_id3); | ||
2345 | |||
2346 | track_changed = true; | ||
2347 | playlist_update_resume_info(audio_current_track()); | 2334 | playlist_update_resume_info(audio_current_track()); |
2348 | } | 2335 | } |
2349 | 2336 | ||
@@ -2588,6 +2575,9 @@ void audio_init(void) | |||
2588 | ci.dsp = (struct dsp_config *)dsp_configure(NULL, DSP_MYDSP, | 2575 | ci.dsp = (struct dsp_config *)dsp_configure(NULL, DSP_MYDSP, |
2589 | CODEC_IDX_AUDIO); | 2576 | CODEC_IDX_AUDIO); |
2590 | 2577 | ||
2578 | thistrack_id3 = &mp3entry_buf[0]; | ||
2579 | othertrack_id3 = &mp3entry_buf[1]; | ||
2580 | |||
2591 | /* initialize the buffer */ | 2581 | /* initialize the buffer */ |
2592 | filebuf = audiobuf; | 2582 | filebuf = audiobuf; |
2593 | 2583 | ||
diff --git a/apps/plugin.c b/apps/plugin.c index 2126641572..17e9ac670b 100644 --- a/apps/plugin.c +++ b/apps/plugin.c | |||
@@ -463,7 +463,6 @@ static const struct plugin_api rockbox_api = { | |||
463 | audio_ff_rewind, | 463 | audio_ff_rewind, |
464 | audio_next_track, | 464 | audio_next_track, |
465 | audio_status, | 465 | audio_status, |
466 | audio_has_changed_track, | ||
467 | audio_current_track, | 466 | audio_current_track, |
468 | audio_flush_and_reload_tracks, | 467 | audio_flush_and_reload_tracks, |
469 | audio_get_file_pos, | 468 | audio_get_file_pos, |
diff --git a/apps/plugin.h b/apps/plugin.h index 8954373d23..fdcf3c2afa 100644 --- a/apps/plugin.h +++ b/apps/plugin.h | |||
@@ -128,12 +128,12 @@ void* plugin_get_buffer(size_t *buffer_size); | |||
128 | #define PLUGIN_MAGIC 0x526F634B /* RocK */ | 128 | #define PLUGIN_MAGIC 0x526F634B /* RocK */ |
129 | 129 | ||
130 | /* increase this every time the api struct changes */ | 130 | /* increase this every time the api struct changes */ |
131 | #define PLUGIN_API_VERSION 146 | 131 | #define PLUGIN_API_VERSION 147 |
132 | 132 | ||
133 | /* update this to latest version if a change to the api struct breaks | 133 | /* update this to latest version if a change to the api struct breaks |
134 | backwards compatibility (and please take the opportunity to sort in any | 134 | backwards compatibility (and please take the opportunity to sort in any |
135 | new function which are "waiting" at the end of the function table) */ | 135 | new function which are "waiting" at the end of the function table) */ |
136 | #define PLUGIN_MIN_API_VERSION 146 | 136 | #define PLUGIN_MIN_API_VERSION 147 |
137 | 137 | ||
138 | /* plugin return codes */ | 138 | /* plugin return codes */ |
139 | enum plugin_status { | 139 | enum plugin_status { |
@@ -588,7 +588,6 @@ struct plugin_api { | |||
588 | void (*audio_ff_rewind)(long newtime); | 588 | void (*audio_ff_rewind)(long newtime); |
589 | struct mp3entry* (*audio_next_track)(void); | 589 | struct mp3entry* (*audio_next_track)(void); |
590 | int (*audio_status)(void); | 590 | int (*audio_status)(void); |
591 | bool (*audio_has_changed_track)(void); | ||
592 | struct mp3entry* (*audio_current_track)(void); | 591 | struct mp3entry* (*audio_current_track)(void); |
593 | void (*audio_flush_and_reload_tracks)(void); | 592 | void (*audio_flush_and_reload_tracks)(void); |
594 | int (*audio_get_file_pos)(void); | 593 | int (*audio_get_file_pos)(void); |