summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/appevents.h1
-rw-r--r--apps/gui/gwps-common.c39
-rw-r--r--apps/gui/gwps.c51
-rw-r--r--apps/gui/gwps.h1
-rw-r--r--apps/gui/wps_parser.c44
-rw-r--r--apps/iap.c6
-rw-r--r--apps/mpeg.c5
-rw-r--r--apps/playback.c210
-rw-r--r--apps/plugin.c1
-rw-r--r--apps/plugin.h5
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 {
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 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)
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 @@ bool gui_wps_update(struct gui_wps *gwps)
{
/* 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 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];
/* 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 gui_wps_show(void)
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 @@ long gui_wps_show(void)
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 @@ long gui_wps_show(void)
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 @@ long gui_wps_show(void)
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 @@ static void wps_state_init(void)
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 7888c3944c..1042e1a795 100644
--- a/apps/gui/gwps.h
+++ b/apps/gui/gwps.h
@@ -478,6 +478,7 @@ struct wps_state
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 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[] = {
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 @@ static const struct wps_tag all_tags[] = {
{ 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 dd29563b1e..4d0c473800 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 @@ void iap_setup(int ratenum)
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 @@ int iap_getc(unsigned char x)
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 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)
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 @@ static struct trackdata *add_track_to_tag_list(const char *filename)
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 11f76d4db8..3709b407fa 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -201,14 +201,15 @@ size_t filebuflen = 0; /* Size of buffer (A/C-) */
/* 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 int track_widx = 0; /* Track being buffered (A) */
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 @@ struct mp3entry* audio_current_track(void)
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 @@ struct mp3entry* audio_next_track(void)
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 @@ void audio_skip(int direction)
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 @@ void audio_set_crossfade(int enable)
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 @@ static void codec_pcmbuf_position_callback(size_t size)
{
/* 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 @@ static void codec_set_elapsed_callback(unsigned int value)
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 @@ static void codec_set_offset_callback(size_t value)
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 @@ static bool codec_load_next_track(void)
{
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 @@ static bool codec_request_next_track_callback(void)
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 @@ static bool codec_request_next_track_callback(void)
}
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 @@ static void codec_thread(void)
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 @@ static void codec_thread(void)
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 @@ static void codec_thread(void)
{
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 @@ static void codec_thread(void)
* 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 @@ static void codec_thread(void)
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 @@ static void buffering_handle_finished_callback(int *data)
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 @@ static void audio_update_trackinfo(void)
{
/* 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 @@ static bool audio_loadcodec(bool start_play)
/* 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 @@ static bool audio_load_track(size_t offset, bool start_play)
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 @@ static bool audio_load_track(size_t offset, bool start_play)
{
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 @@ static bool audio_load_track(size_t offset, bool start_play)
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 @@ static bool audio_load_track(size_t offset, bool start_play)
{
/* 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 @@ static void audio_finish_load_track(void)
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_finish_load_track(void)
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 @@ static void audio_fill_file_buffer(bool start_play, size_t offset)
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 @@ static void audio_rebuffer(void)
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 @@ static int audio_check_new_track(void)
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 @@ static int audio_check_new_track(void)
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 @@ static int audio_check_new_track(void)
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 @@ static void audio_stop_playback(void)
/* 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 @@ static void audio_stop_playback(void)
/* 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 @@ static void audio_play_start(size_t offset)
paused = false;
audio_stop_codec_flush();
- track_changed = true;
-
playing = true;
track_load_started = false;
@@ -2325,25 +2322,15 @@ static void audio_finalise_track_change(void)
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 @@ void audio_init(void)
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 2126641572..17e9ac670b 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -463,7 +463,6 @@ static const struct plugin_api rockbox_api = {
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 8954373d23..fdcf3c2afa 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -128,12 +128,12 @@ void* plugin_get_buffer(size_t *buffer_size);
#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 @@ struct plugin_api {
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);