diff options
author | Jonathan Gordon <rockbox@jdgordon.info> | 2009-04-06 00:39:43 +0000 |
---|---|---|
committer | Jonathan Gordon <rockbox@jdgordon.info> | 2009-04-06 00:39:43 +0000 |
commit | 843c7efaf8c953fc3bec40a7da0be3a5da9950df (patch) | |
tree | cb27e411394f716d26193433c66132072730ea70 /apps | |
parent | 9188f0ffd7ce97101a5b2d697cc43072cd63b502 (diff) | |
download | rockbox-843c7efaf8c953fc3bec40a7da0be3a5da9950df.tar.gz rockbox-843c7efaf8c953fc3bec40a7da0be3a5da9950df.zip |
FS9795 - some playback cleanup.
* Use events to notify things when the track has changed instead of the nasty has_track_changed()
* Event for when the mp3entry for the next track is avilable (which allows alot more tags to be static which means less redrawing in the WPS)
* virtually guarentee that the mp3entry sturct returned by audio_current/next_track() is going to be valid for the duration of the current track. The only time it wont be now is during the time between the codec finishing the previous track and the next track actually starting (~2s), but this is not an issue as long as it is called again when the TRACK_CHANGED event happens (or just use the pointer that gives)
It is still possible to confuse the WPS with the next tracks id3 info being displayed but this should fix itself up faster than it used to (and be harder to do)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20633 a1c6a512-1295-4272-9138-f99709370657
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); |