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
diff --git a/apps/appevents.h b/apps/appevents.h
index 8cbc301..e3c4a92 100644
--- a/apps/appevents.h
+++ b/apps/appevents.h
@@ -34,6 +34,7 @@
PLAYBACK_EVENT_TRACK_BUFFER = (EVENT_CLASS_PLAYBACK|1),
PLAYBACK_EVENT_TRACK_FINISH,
PLAYBACK_EVENT_TRACK_CHANGE,
+ PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE,
};
/** Buffering events **/
diff --git a/apps/gui/gwps-common.c b/apps/gui/gwps-common.c
index f32b002..189fc6f 100644
--- a/apps/gui/gwps-common.c
+++ b/apps/gui/gwps-common.c
@@ -348,33 +348,8 @@
bool gui_wps_update(struct gui_wps *gwps)
{
- bool track_changed = audio_has_changed_track();
struct mp3entry *id3 = gwps->state->id3;
-
- gwps->state->nid3 = audio_next_track();
- if (track_changed)
- {
- gwps->state->id3 = id3 = audio_current_track();
-
- if (cuesheet_is_enabled() && id3->cuesheet_type
- && strcmp(id3->path, curr_cue->audio_filename))
- {
- /* the current cuesheet isn't the right one any more */
- /* We need to parse the new cuesheet */
-
- char cuepath[MAX_PATH];
-
- if (look_for_cuesheet_file(id3->path, cuepath) &&
- parse_cuesheet(cuepath, curr_cue))
- {
- id3->cuesheet_type = 1;
- strcpy(curr_cue->audio_filename, id3->path);
- }
-
- cue_spoof_id3(curr_cue, id3);
- }
- }
-
+ bool retval;
if (cuesheet_is_enabled() && id3->cuesheet_type
&& (id3->elapsed < curr_cue->curr_track->offset
|| (curr_cue->curr_track_idx < curr_cue->track_count - 1
@@ -382,17 +357,15 @@
{
/* We've changed tracks within the cuesheet :
we need to update the ID3 info and refresh the WPS */
-
- track_changed = true;
+ gwps->state->do_full_update = true;
cue_find_current_track(curr_cue, id3->elapsed);
cue_spoof_id3(curr_cue, id3);
}
- if (track_changed)
- gwps->display->stop_scroll();
-
- return gui_wps_redraw(gwps, 0,
- track_changed ? WPS_REFRESH_ALL : WPS_REFRESH_NON_STATIC);
+ retval = gui_wps_redraw(gwps, 0,
+ gwps->state->do_full_update ?
+ WPS_REFRESH_ALL : WPS_REFRESH_NON_STATIC);
+ return retval;
}
diff --git a/apps/gui/gwps.c b/apps/gui/gwps.c
index 32a2721..5474b30 100644
--- a/apps/gui/gwps.c
+++ b/apps/gui/gwps.c
@@ -78,6 +78,8 @@
/* initial setup of wps_data */
static void wps_state_init(void);
+static void track_changed_callback(void *param);
+static void nextid3available_callback(void* param);
static void change_dir(int direction)
{
@@ -246,7 +248,7 @@
long restoretimer = RESTORE_WPS_INSTANTLY; /* timer to delay screen redraw temporarily */
bool exit = false;
bool bookmark = false;
- bool update_track = false;
+ bool update_track = false, partial_update = false;
int i;
long last_left = 0, last_right = 0;
wps_state_init();
@@ -651,7 +653,7 @@
restore = true;
break;
case ACTION_NONE: /* Timeout */
- update_track = true;
+ partial_update = true;
ffwd_rew(button); /* hopefully fix the ffw/rwd bug */
break;
#ifdef HAVE_RECORDING
@@ -671,13 +673,21 @@
break;
}
- if (update_track)
+ if (wps_state.do_full_update || partial_update || update_track)
{
+ if (update_track)
+ {
+ wps_state.do_full_update = true;
+ wps_state.id3 = audio_current_track();
+ wps_state.nid3 = audio_next_track();
+ }
FOR_NB_SCREENS(i)
{
gui_wps_update(&gui_wps[i]);
}
+ wps_state.do_full_update = false;
update_track = false;
+ partial_update = false;
}
if (restore && wps_state.id3 &&
@@ -723,7 +733,36 @@
return GO_TO_ROOT; /* unreachable - just to reduce compiler warnings */
}
-/* needs checking if needed end*/
+/* this is called from the playback thread so NO DRAWING! */
+static void track_changed_callback(void *param)
+{
+ wps_state.id3 = (struct mp3entry*)param;
+ wps_state.nid3 = audio_next_track();
+
+ if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type
+ && strcmp(wps_state.id3->path, curr_cue->audio_filename))
+ {
+ /* the current cuesheet isn't the right one any more */
+ /* We need to parse the new cuesheet */
+ char cuepath[MAX_PATH];
+
+ if (look_for_cuesheet_file(wps_state.id3->path, cuepath) &&
+ parse_cuesheet(cuepath, curr_cue))
+ {
+ wps_state.id3->cuesheet_type = 1;
+ strcpy(curr_cue->audio_filename, wps_state.id3->path);
+ }
+
+ cue_spoof_id3(curr_cue, wps_state.id3);
+ }
+ wps_state.do_full_update = true;
+}
+static void nextid3available_callback(void* param)
+{
+ (void)param;
+ wps_state.nid3 = audio_next_track();
+ wps_state.do_full_update = true;
+}
/* wps_state */
@@ -733,6 +772,10 @@
wps_state.paused = false;
wps_state.id3 = NULL;
wps_state.nid3 = NULL;
+ wps_state.do_full_update = true;
+ /* add the WPS track event callbacks */
+ add_event(PLAYBACK_EVENT_TRACK_CHANGE, false, track_changed_callback);
+ add_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, false, nextid3available_callback);
}
/* wps_state end*/
diff --git a/apps/gui/gwps.h b/apps/gui/gwps.h
index 7888c39..1042e1a 100644
--- a/apps/gui/gwps.h
+++ b/apps/gui/gwps.h
@@ -478,6 +478,7 @@
bool wps_time_countup;
struct mp3entry* id3;
struct mp3entry* nid3;
+ bool do_full_update;
};
diff --git a/apps/gui/wps_parser.c b/apps/gui/wps_parser.c
index ba2e217..390df56 100644
--- a/apps/gui/wps_parser.c
+++ b/apps/gui/wps_parser.c
@@ -215,16 +215,16 @@
parse_dir_level },
/* next file */
- { WPS_TOKEN_FILE_BITRATE, "Fb", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_FILE_CODEC, "Fc", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_FILE_FREQUENCY, "Ff", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_FILE_FREQUENCY_KHZ, "Fk", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_FILE_NAME_WITH_EXTENSION, "Fm", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_FILE_NAME, "Fn", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_FILE_PATH, "Fp", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_FILE_SIZE, "Fs", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_FILE_VBR, "Fv", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_FILE_DIRECTORY, "D", WPS_REFRESH_DYNAMIC,
+ { WPS_TOKEN_FILE_BITRATE, "Fb", WPS_REFRESH_STATIC, NULL },
+ { WPS_TOKEN_FILE_CODEC, "Fc", WPS_REFRESH_STATIC, NULL },
+ { WPS_TOKEN_FILE_FREQUENCY, "Ff", WPS_REFRESH_STATIC, NULL },
+ { WPS_TOKEN_FILE_FREQUENCY_KHZ, "Fk", WPS_REFRESH_STATIC, NULL },
+ { WPS_TOKEN_FILE_NAME_WITH_EXTENSION, "Fm", WPS_REFRESH_STATIC, NULL },
+ { WPS_TOKEN_FILE_NAME, "Fn", WPS_REFRESH_STATIC, NULL },
+ { WPS_TOKEN_FILE_PATH, "Fp", WPS_REFRESH_STATIC, NULL },
+ { WPS_TOKEN_FILE_SIZE, "Fs", WPS_REFRESH_STATIC, NULL },
+ { WPS_TOKEN_FILE_VBR, "Fv", WPS_REFRESH_STATIC, NULL },
+ { WPS_TOKEN_FILE_DIRECTORY, "D", WPS_REFRESH_STATIC,
parse_dir_level },
/* current metadata */
@@ -242,18 +242,18 @@
{ WPS_TOKEN_METADATA_COMMENT, "iC", WPS_REFRESH_STATIC, NULL },
/* next metadata */
- { WPS_TOKEN_METADATA_ARTIST, "Ia", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_METADATA_COMPOSER, "Ic", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_METADATA_ALBUM, "Id", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_METADATA_ALBUM_ARTIST, "IA", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_METADATA_GROUPING, "IG", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_METADATA_GENRE, "Ig", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_METADATA_DISC_NUMBER, "Ik", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_METADATA_TRACK_NUMBER, "In", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_METADATA_TRACK_TITLE, "It", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_METADATA_VERSION, "Iv", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_METADATA_YEAR, "Iy", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_METADATA_COMMENT, "IC", WPS_REFRESH_DYNAMIC, NULL },
+ { WPS_TOKEN_METADATA_ARTIST, "Ia", WPS_REFRESH_STATIC, NULL },
+ { WPS_TOKEN_METADATA_COMPOSER, "Ic", WPS_REFRESH_STATIC, NULL },
+ { WPS_TOKEN_METADATA_ALBUM, "Id", WPS_REFRESH_STATIC, NULL },
+ { WPS_TOKEN_METADATA_ALBUM_ARTIST, "IA", WPS_REFRESH_STATIC, NULL },
+ { WPS_TOKEN_METADATA_GROUPING, "IG", WPS_REFRESH_STATIC, NULL },
+ { WPS_TOKEN_METADATA_GENRE, "Ig", WPS_REFRESH_STATIC, NULL },
+ { WPS_TOKEN_METADATA_DISC_NUMBER, "Ik", WPS_REFRESH_STATIC, NULL },
+ { WPS_TOKEN_METADATA_TRACK_NUMBER, "In", WPS_REFRESH_STATIC, NULL },
+ { WPS_TOKEN_METADATA_TRACK_TITLE, "It", WPS_REFRESH_STATIC, NULL },
+ { WPS_TOKEN_METADATA_VERSION, "Iv", WPS_REFRESH_STATIC, NULL },
+ { WPS_TOKEN_METADATA_YEAR, "Iy", WPS_REFRESH_STATIC, NULL },
+ { WPS_TOKEN_METADATA_COMMENT, "IC", WPS_REFRESH_STATIC, NULL },
#if (CONFIG_CODEC != MAS3507D)
{ WPS_TOKEN_SOUND_PITCH, "Sp", WPS_REFRESH_DYNAMIC, NULL },
diff --git a/apps/iap.c b/apps/iap.c
index dd29563..4d0c473 100644
--- a/apps/iap.c
+++ b/apps/iap.c
@@ -29,6 +29,7 @@
#include "system.h"
#include "kernel.h"
#include "serial.h"
+#include "appevents.h"
#include "playlist.h"
#include "playback.h"
@@ -80,6 +81,7 @@
iap_setupflag = true;
iap_remotebtn = BUTTON_NONE;
tick_add_task(iap_task);
+ add_event(PLAYBACK_EVENT_TRACK_CHANGE, false, iap_track_changed);
}
void iap_bitrate_set(int ratenum)
@@ -175,8 +177,10 @@
return newpkt;
}
-void iap_track_changed(void)
+/* called by playback when the next track starts */
+void iap_track_changed(void *ignored)
{
+ (void)ignored;
iap_changedctr = 1;
}
diff --git a/apps/mpeg.c b/apps/mpeg.c
index cde72ab..5ebf58f 100644
--- a/apps/mpeg.c
+++ b/apps/mpeg.c
@@ -852,6 +852,7 @@
static struct trackdata *add_track_to_tag_list(const char *filename)
{
struct trackdata *track;
+ bool send_nid3_event;
if(num_tracks_in_memory() >= MAX_TRACK_ENTRIES)
{
@@ -882,7 +883,11 @@
if (cuesheet_callback(filename))
track->id3.cuesheet_type = 1;
+ /* if this track is the next track then let the UI know it can get it */
+ send_nid3_event = (track_write_idx == track_read_idx + 1);
track_write_idx = (track_write_idx+1) & MAX_TRACK_ENTRIES_MASK;
+ if (send_nid3_event)
+ send_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, NULL);
debug_tags();
return track;
}
diff --git a/apps/playback.c b/apps/playback.c
index 11f76d4..3709b40 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -201,14 +201,15 @@
/* Possible arrangements of the buffer */
static int buffer_state = AUDIOBUF_STATE_TRASHED; /* Buffer state */
-/* Used to keep the WPS up-to-date during track transtition */
-static struct mp3entry prevtrack_id3;
-
-/* Used to provide the codec with a pointer */
-static struct mp3entry curtrack_id3;
-
-/* Used to make next track info available while playing last track on buffer */
-static struct mp3entry lasttrack_id3;
+/* These are used to store the current and next (or prev if the current is the last)
+ * mp3entry's in a round-robin system. This guarentees that the pointer returned
+ * by audio_current/next_track will be valid for the full duration of the
+ * currently playing track */
+static struct mp3entry mp3entry_buf[2];
+static struct mp3entry *thistrack_id3, /* the currently playing track */
+ *othertrack_id3; /* prev track during track-change-transition, or end of playlist,
+ * next track otherwise */
+static struct mp3entry unbuffered_id3; /* the id3 for the first unbuffered track */
/* Track info structure about songs in the file buffer (A/C-) */
struct track_info {
@@ -232,10 +233,6 @@
static struct track_info *prev_ti = NULL; /* Pointer to the previously played
track */
-/* Set by the audio thread when the current track information has updated
- * and the WPS may need to update its cached information */
-static bool track_changed = false;
-
/* Information used only for filling the buffer */
/* Playlist steps from playing track to next track to be buffered (A) */
static int last_peek_offset = 0;
@@ -567,24 +564,25 @@
cur_idx = (track_ridx + offset) & MAX_TRACK_MASK;
- if (cur_idx == track_ridx && *curtrack_id3.path)
+ if (cur_idx == track_ridx && *thistrack_id3->path)
{
/* The usual case */
- return &curtrack_id3;
+ return thistrack_id3;
}
- else if (automatic_skip && offset == -1 && *prevtrack_id3.path)
+ else if (automatic_skip && offset == -1 && *othertrack_id3->path)
{
- /* We're in a track transition. The codec has moved on to the nex track,
- but the audio being played is still the same (now previous) track.
- prevtrack_id3.elapsed is being updated in an ISR by
- codec_pcmbuf_position_callback */
- return &prevtrack_id3;
+ /* We're in a track transition. The codec has moved on to the next track,
+ but the audio being played is still the same (now previous) track.
+ othertrack_id3.elapsed is being updated in an ISR by
+ codec_pcmbuf_position_callback */
+ return othertrack_id3;
}
else if (tracks[cur_idx].id3_hid >= 0)
{
- /* Get the ID3 metadata from the main buffer */
- struct mp3entry *ret = bufgetid3(tracks[cur_idx].id3_hid);
- if (ret) return ret;
+ /* The current track's info has been buffered but not read yet, so get it */
+ if (bufread(tracks[cur_idx].id3_hid, sizeof(struct mp3entry), &temp_id3)
+ == sizeof(struct mp3entry))
+ return &temp_id3;
}
/* We didn't find the ID3 metadata, so we fill temp_id3 with the little info
@@ -620,42 +618,34 @@
if (!audio_have_tracks())
return NULL;
- if (wps_offset == -1 && *prevtrack_id3.path)
+ if (wps_offset == -1 && *thistrack_id3->path)
{
/* We're in a track transition. The next track for the WPS is the one
currently being decoded. */
- return &curtrack_id3;
+ return thistrack_id3;
}
next_idx = (track_ridx + offset + 1) & MAX_TRACK_MASK;
if (tracks[next_idx].id3_hid >= 0)
- return bufgetid3(tracks[next_idx].id3_hid);
+ {
+ if (bufread(tracks[next_idx].id3_hid, sizeof(struct mp3entry), othertrack_id3)
+ == sizeof(struct mp3entry))
+ return othertrack_id3;
+ else
+ return NULL;
+ }
if (next_idx == track_widx)
{
/* The next track hasn't been buffered yet, so we return the static
version of its metadata. */
- return &lasttrack_id3;
+ return &unbuffered_id3;
}
return NULL;
}
-bool audio_has_changed_track(void)
-{
- if (track_changed)
- {
-#ifdef IPOD_ACCESSORY_PROTOCOL
- iap_track_changed();
-#endif
- track_changed = false;
- return true;
- }
-
- return false;
-}
-
void audio_play(long offset)
{
logf("audio_play");
@@ -705,7 +695,6 @@
queue_post(&audio_queue, Q_AUDIO_SKIP, direction);
/* Update wps while our message travels inside deep playback queues. */
wps_offset += direction;
- track_changed = true;
}
else
{
@@ -823,7 +812,7 @@
if (was_playing)
{
/* Store the track resume position */
- offset = curtrack_id3.offset;
+ offset = thistrack_id3->offset;
}
/* Blast it - audio buffer will have to be setup again next time
@@ -963,15 +952,15 @@
{
/* This is called from an ISR, so be quick */
unsigned int time = size * 1000 / 4 / NATIVE_FREQUENCY +
- prevtrack_id3.elapsed;
+ othertrack_id3->elapsed;
- if (time >= prevtrack_id3.length)
+ if (time >= othertrack_id3->length)
{
pcmbuf_set_position_callback(NULL);
- prevtrack_id3.elapsed = prevtrack_id3.length;
+ othertrack_id3->elapsed = othertrack_id3->length;
}
else
- prevtrack_id3.elapsed = time;
+ othertrack_id3->elapsed = time;
}
static void codec_set_elapsed_callback(unsigned int value)
@@ -986,11 +975,11 @@
latency = pcmbuf_get_latency();
if (value < latency)
- curtrack_id3.elapsed = 0;
- else if (value - latency > curtrack_id3.elapsed ||
- value - latency < curtrack_id3.elapsed - 2)
+ thistrack_id3->elapsed = 0;
+ else if (value - latency > thistrack_id3->elapsed ||
+ value - latency < thistrack_id3->elapsed - 2)
{
- curtrack_id3.elapsed = value - latency;
+ thistrack_id3->elapsed = value - latency;
}
}
@@ -1001,11 +990,11 @@
if (ci.seek_time)
return;
- latency = pcmbuf_get_latency() * curtrack_id3.bitrate / 8;
+ latency = pcmbuf_get_latency() * thistrack_id3->bitrate / 8;
if (value < latency)
- curtrack_id3.offset = 0;
+ thistrack_id3->offset = 0;
else
- curtrack_id3.offset = value - latency;
+ thistrack_id3->offset = value - latency;
}
static void codec_advance_buffer_counters(size_t amount)
@@ -1197,7 +1186,7 @@
{
intptr_t result = Q_CODEC_REQUEST_FAILED;
- prev_track_elapsed = curtrack_id3.elapsed;
+ prev_track_elapsed = thistrack_id3->elapsed;
#ifdef AB_REPEAT_ENABLE
ab_end_of_track_report();
@@ -1247,18 +1236,16 @@
if (ci.stop_codec || !playing)
return false;
- prev_codectype = get_codec_base_type(curtrack_id3.codectype);
-
+ prev_codectype = get_codec_base_type(thistrack_id3->codectype);
if (!codec_load_next_track())
return false;
/* Seek to the beginning of the new track because if the struct
mp3entry was buffered, "elapsed" might not be zero (if the track has
been played already but not unbuffered) */
- codec_seek_buffer_callback(curtrack_id3.first_frame_offset);
-
+ codec_seek_buffer_callback(thistrack_id3->first_frame_offset);
/* Check if the next codec is the same file. */
- if (prev_codectype == get_codec_base_type(curtrack_id3.codectype))
+ if (prev_codectype == get_codec_base_type(thistrack_id3->codectype))
{
logf("New track loaded");
codec_discard_codec_callback();
@@ -1266,7 +1253,7 @@
}
else
{
- logf("New codec:%d/%d", curtrack_id3.codectype, prev_codectype);
+ logf("New codec:%d/%d", thistrack_id3->codectype, prev_codectype);
return false;
}
}
@@ -1293,6 +1280,7 @@
audio_codec_loaded = true;
ci.stop_codec = false;
status = codec_load_file((const char *)ev.data, &ci);
+ LOGFQUEUE("codec_load_file %s %d\n", (const char *)ev.data, status);
break;
case Q_CODEC_LOAD:
@@ -1312,6 +1300,7 @@
audio_codec_loaded = true;
ci.stop_codec = false;
status = codec_load_buf(CUR_TI->codec_hid, &ci);
+ LOGFQUEUE("codec_load_buf %d\n", status);
break;
case Q_CODEC_DO_CALLBACK:
@@ -1362,7 +1351,7 @@
{
if (!ci.new_track)
{
- logf("Codec failure");
+ logf("Codec failure, %d %d", ci.new_track, status);
splash(HZ*2, "Codec failure");
}
@@ -1383,8 +1372,10 @@
* triggering the WPS exit */
while(pcm_is_playing())
{
- curtrack_id3.elapsed =
- curtrack_id3.length - pcmbuf_get_latency();
+ /* There has been one too many struct pointer swaps by now
+ * so even though it says othertrack_id3, its the correct one! */
+ othertrack_id3->elapsed =
+ othertrack_id3->length - pcmbuf_get_latency();
sleep(1);
}
@@ -1405,7 +1396,7 @@
else
{
const char *codec_fn =
- get_codec_filename(curtrack_id3.codectype);
+ get_codec_filename(thistrack_id3->codectype);
if (codec_fn)
{
LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
@@ -1481,10 +1472,14 @@
if (*data == tracks[track_widx].id3_hid)
{
+ int offset = ci.new_track + wps_offset;
+ int next_idx = (track_ridx + offset + 1) & MAX_TRACK_MASK;
/* The metadata handle for the last loaded track has been buffered.
We can ask the audio thread to load the rest of the track's data. */
LOGFQUEUE("audio >| audio Q_AUDIO_FINISH_LOAD");
queue_post(&audio_queue, Q_AUDIO_FINISH_LOAD, 0);
+ if (tracks[next_idx].id3_hid == *data)
+ send_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, NULL);
}
else
{
@@ -1534,15 +1529,15 @@
{
/* Load the curent track's metadata into curtrack_id3 */
if (CUR_TI->id3_hid >= 0)
- copy_mp3entry(&curtrack_id3, bufgetid3(CUR_TI->id3_hid));
+ copy_mp3entry(thistrack_id3, bufgetid3(CUR_TI->id3_hid));
/* Reset current position */
- curtrack_id3.elapsed = 0;
- curtrack_id3.offset = 0;
+ thistrack_id3->elapsed = 0;
+ thistrack_id3->offset = 0;
/* Update the codec API */
ci.filesize = CUR_TI->filesize;
- ci.id3 = &curtrack_id3;
+ ci.id3 = thistrack_id3;
ci.curpos = 0;
ci.taginfo_ready = &CUR_TI->taginfo_ready;
}
@@ -1608,7 +1603,7 @@
/* Load the codec directly from disk and save some memory. */
track_ridx = track_widx;
ci.filesize = CUR_TI->filesize;
- ci.id3 = &curtrack_id3;
+ ci.id3 = thistrack_id3;
ci.taginfo_ready = &CUR_TI->taginfo_ready;
ci.curpos = 0;
LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
@@ -1698,10 +1693,10 @@
if (!trackname)
{
logf("End-of-playlist");
- memset(&lasttrack_id3, 0, sizeof(struct mp3entry));
+ memset(&unbuffered_id3, 0, sizeof(struct mp3entry));
filling = STATE_END_OF_PLAYLIST;
- if (curtrack_id3.length == 0 && curtrack_id3.filesize == 0)
+ if (thistrack_id3->length == 0 && thistrack_id3->filesize == 0)
{
/* Stop playback if no valid track was found. */
audio_stop_playback();
@@ -1720,7 +1715,6 @@
{
buf_set_watermark(filebuflen/2);
dsp_configure(ci.dsp, DSP_RESET, 0);
- track_changed = true;
playlist_update_resume_info(audio_current_track());
}
@@ -1732,7 +1726,7 @@
if (tracks[track_widx].id3_hid < 0)
{
/* Buffer is full. */
- get_metadata(&lasttrack_id3, fd, trackname);
+ get_metadata(&unbuffered_id3, fd, trackname);
last_peek_offset--;
close(fd);
logf("buffer is full for now");
@@ -1744,13 +1738,18 @@
{
/* TODO: Superfluos buffering call? */
buf_request_buffer_handle(tracks[track_widx].id3_hid);
- copy_mp3entry(&curtrack_id3, bufgetid3(tracks[track_widx].id3_hid));
- curtrack_id3.offset = offset;
+ struct mp3entry *id3 = bufgetid3(tracks[track_widx].id3_hid);
+ if (id3)
+ {
+ copy_mp3entry(thistrack_id3, id3);
+ thistrack_id3->offset = offset;
+ }
+ else
+ memset(thistrack_id3, 0, sizeof(struct mp3entry));
}
if (start_play)
{
- track_changed = true;
playlist_update_resume_info(audio_current_track());
}
}
@@ -1780,7 +1779,7 @@
struct mp3entry *track_id3;
if (track_widx == track_ridx)
- track_id3 = &curtrack_id3;
+ track_id3 = thistrack_id3;
else
track_id3 = bufgetid3(tracks[track_widx].id3_hid);
@@ -1935,8 +1934,6 @@
static void audio_fill_file_buffer(bool start_play, size_t offset)
{
- bool had_next_track = audio_next_track() != NULL;
-
filling = STATE_FILLING;
trigger_cpu_boost();
@@ -1959,9 +1956,6 @@
playlist_update_resume_info(audio_current_track());
audio_load_track(offset, start_play);
-
- if (!had_next_track && audio_next_track())
- track_changed = true;
}
static void audio_rebuffer(void)
@@ -1982,7 +1976,7 @@
ci.curpos = 0;
if (!CUR_TI->taginfo_ready)
- memset(&curtrack_id3, 0, sizeof(struct mp3entry));
+ memset(thistrack_id3, 0, sizeof(struct mp3entry));
audio_fill_file_buffer(false, 0);
}
@@ -1995,9 +1989,16 @@
int old_track_ridx = track_ridx;
int i, idx;
bool forward;
+ struct mp3entry *temp = thistrack_id3;
/* Now it's good time to send track finish events. */
- send_event(PLAYBACK_EVENT_TRACK_FINISH, &curtrack_id3);
+ send_event(PLAYBACK_EVENT_TRACK_FINISH, thistrack_id3);
+ /* swap the mp3entry pointers */
+ thistrack_id3 = othertrack_id3;
+ othertrack_id3 = temp;
+ ci.id3 = thistrack_id3;
+ memset(thistrack_id3, 0, sizeof(struct mp3entry));
+
if (dir_skip)
{
dir_skip = false;
@@ -2035,22 +2036,23 @@
LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
return Q_CODEC_REQUEST_FAILED;
}
-
+
if (new_playlist)
{
ci.new_track = 1;
new_playlist = false;
}
- /* Save the track metadata to allow the WPS to display it
- while PCM finishes playing that track */
- copy_mp3entry(&prevtrack_id3, &curtrack_id3);
-
+ /* FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
+ * 1) why are we doing this?
+ * 2) thistrack_id3 has already been cleared anyway */
/* Update the main buffer copy of the track metadata with the one
the codec has been using (for the unbuffer callbacks) */
if (CUR_TI->id3_hid >= 0)
- copy_mp3entry(bufgetid3(CUR_TI->id3_hid), &curtrack_id3);
-
+ copy_mp3entry(bufgetid3(CUR_TI->id3_hid), thistrack_id3);
+ /* FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME */
+
+
/* Save a pointer to the old track to allow later clearing */
prev_ti = CUR_TI;
@@ -2079,7 +2081,6 @@
if (automatic_skip)
{
wps_offset = -ci.new_track;
- track_changed = true;
}
/* If it is not safe to even skip this many track entries */
@@ -2185,7 +2186,7 @@
/* TODO: Create auto bookmark too? */
- prev_track_elapsed = curtrack_id3.elapsed;
+ prev_track_elapsed = othertrack_id3->elapsed;
remove_event(BUFFER_EVENT_BUFFER_LOW, buffering_low_buffer_callback);
}
@@ -2202,8 +2203,6 @@
/* Close all tracks */
audio_release_tracks();
-
- memset(&curtrack_id3, 0, sizeof(struct mp3entry));
}
static void audio_play_start(size_t offset)
@@ -2219,8 +2218,6 @@
paused = false;
audio_stop_codec_flush();
- track_changed = true;
-
playing = true;
track_load_started = false;
@@ -2325,25 +2322,15 @@
automatic_skip = false;
/* Invalidate prevtrack_id3 */
- prevtrack_id3.path[0] = 0;
+ memset(othertrack_id3, 0, sizeof(struct mp3entry));
if (prev_ti && prev_ti->audio_hid < 0)
{
/* No audio left so we clear all the track info. */
clear_track_info(prev_ti);
}
-
- if (prev_ti && prev_ti->id3_hid >= 0)
- {
- /* Reset the elapsed time to force the progressbar to be empty if
- the user skips back to this track */
- bufgetid3(prev_ti->id3_hid)->elapsed = 0;
- }
}
-
- send_event(PLAYBACK_EVENT_TRACK_CHANGE, &curtrack_id3);
-
- track_changed = true;
+ send_event(PLAYBACK_EVENT_TRACK_CHANGE, thistrack_id3);
playlist_update_resume_info(audio_current_track());
}
@@ -2588,6 +2575,9 @@
ci.dsp = (struct dsp_config *)dsp_configure(NULL, DSP_MYDSP,
CODEC_IDX_AUDIO);
+ thistrack_id3 = &mp3entry_buf[0];
+ othertrack_id3 = &mp3entry_buf[1];
+
/* initialize the buffer */
filebuf = audiobuf;
diff --git a/apps/plugin.c b/apps/plugin.c
index 2126641..17e9ac6 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -463,7 +463,6 @@
audio_ff_rewind,
audio_next_track,
audio_status,
- audio_has_changed_track,
audio_current_track,
audio_flush_and_reload_tracks,
audio_get_file_pos,
diff --git a/apps/plugin.h b/apps/plugin.h
index 8954373..fdcf3c2 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -128,12 +128,12 @@
#define PLUGIN_MAGIC 0x526F634B /* RocK */
/* increase this every time the api struct changes */
-#define PLUGIN_API_VERSION 146
+#define PLUGIN_API_VERSION 147
/* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any
new function which are "waiting" at the end of the function table) */
-#define PLUGIN_MIN_API_VERSION 146
+#define PLUGIN_MIN_API_VERSION 147
/* plugin return codes */
enum plugin_status {
@@ -588,7 +588,6 @@
void (*audio_ff_rewind)(long newtime);
struct mp3entry* (*audio_next_track)(void);
int (*audio_status)(void);
- bool (*audio_has_changed_track)(void);
struct mp3entry* (*audio_current_track)(void);
void (*audio_flush_and_reload_tracks)(void);
int (*audio_get_file_pos)(void);
diff --git a/firmware/export/audio.h b/firmware/export/audio.h
index b4a2c82..6236c6d 100644
--- a/firmware/export/audio.h
+++ b/firmware/export/audio.h
@@ -89,7 +89,6 @@
void audio_flush_and_reload_tracks(void);
struct mp3entry* audio_current_track(void);
struct mp3entry* audio_next_track(void);
-bool audio_has_changed_track(void);
void audio_get_debugdata(struct audio_debug *dbgdata);
#ifdef HAVE_DISK_STORAGE
void audio_set_buffer_margin(int seconds);
diff --git a/firmware/export/iap.h b/firmware/export/iap.h
index 6c0b968..d3afd6b 100644
--- a/firmware/export/iap.h
+++ b/firmware/export/iap.h
@@ -26,6 +26,6 @@
extern void iap_bitrate_set(int ratenum);
extern void iap_periodic(void);
extern void iap_handlepkt(void);
-extern void iap_track_changed(void);
+extern void iap_track_changed(void *ignored);
#endif