diff --git a/apps/cuesheet.c b/apps/cuesheet.c index fa1d93f334..aaa2670a40 100644 --- a/apps/cuesheet.c +++ b/apps/cuesheet.c @@ -43,33 +43,6 @@ #define CUE_DIR ROCKBOX_DIR "/cue" -struct cuesheet *curr_cue; - -#if CONFIG_CODEC != SWCODEC -/* special trickery because the hwcodec playback engine is in firmware/ */ -static bool cuesheet_handler(const char *filename) -{ - return cuesheet_is_enabled() && look_for_cuesheet_file(filename, NULL); -} -#endif - -void cuesheet_init(void) -{ - if (global_settings.cuesheet) { - curr_cue = (struct cuesheet *)buffer_alloc(sizeof(struct cuesheet)); -#if CONFIG_CODEC != SWCODEC - audio_set_cuesheet_callback(cuesheet_handler); -#endif - } else { - curr_cue = NULL; - } -} - -bool cuesheet_is_enabled(void) -{ - return (curr_cue != NULL); -} - bool look_for_cuesheet_file(const char *trackpath, char *found_cue_path) { /* DEBUGF("look for cue file\n"); */ @@ -134,7 +107,6 @@ bool parse_cuesheet(char *file, struct cuesheet *cue) char *s; bool utf8 = false; - DEBUGF("cue parse\n"); int fd = open_utf8(file,O_RDONLY); if (fd < 0) { @@ -293,12 +265,8 @@ void browse_cuesheet(struct cuesheet *cue) gui_synclist_set_nb_items(&lists, 2*cue->track_count); gui_synclist_set_title(&lists, title, 0); - if (id3 && *id3->path && strcmp(id3->path, "No file!")) - { - look_for_cuesheet_file(id3->path, cuepath); - } - if (id3 && id3->cuesheet_type && !strcmp(cue->path, cuepath)) + if (id3) { gui_synclist_select_item(&lists, 2*cue_find_current_track(cue, id3->elapsed)); @@ -317,7 +285,7 @@ void browse_cuesheet(struct cuesheet *cue) if (id3 && *id3->path && strcmp(id3->path, "No file!")) { look_for_cuesheet_file(id3->path, cuepath); - if (id3->cuesheet_type && !strcmp(cue->path, cuepath)) + if (id3->cuesheet && !strcmp(cue->path, cuepath)) { sel = gui_synclist_get_sel_pos(&lists); seek(cue->tracks[sel/2].offset); @@ -351,8 +319,9 @@ bool display_cuesheet_content(char* filename) */ bool curr_cuesheet_skip(int direction, unsigned long curr_pos) { + struct cuesheet *curr_cue = audio_current_track()->cuesheet; int track = cue_find_current_track(curr_cue, curr_pos); - + if (direction >= 0 && track == curr_cue->track_count - 1) { /* we want to get out of the cuesheet */ @@ -406,6 +375,7 @@ static inline void draw_veritcal_line_mark(struct screen * screen, void cue_draw_markers(struct screen *screen, unsigned long tracklen, int x1, int x2, int y, int h) { + struct cuesheet *curr_cue = audio_current_track()->cuesheet; int i,xi; int w = x2 - x1; for (i=1; i < curr_cue->track_count; i++) @@ -415,3 +385,17 @@ void cue_draw_markers(struct screen *screen, unsigned long tracklen, } } #endif + +bool cuesheet_subtrack_changed(struct mp3entry *id3) +{ + struct cuesheet *cue = id3->cuesheet; + if (cue && (id3->elapsed < cue->curr_track->offset + || (cue->curr_track_idx < cue->track_count - 1 + && id3->elapsed >= (cue->curr_track+1)->offset))) + { + cue_find_current_track(cue, id3->elapsed); + cue_spoof_id3(cue, id3); + return true; + } + return false; +} diff --git a/apps/cuesheet.h b/apps/cuesheet.h index 41ee9be397..22ad92fdd3 100644 --- a/apps/cuesheet.h +++ b/apps/cuesheet.h @@ -52,14 +52,6 @@ struct cuesheet { struct cue_track_info *curr_track; }; -extern struct cuesheet *curr_cue; - -/* returns true if cuesheet support is initialised */ -bool cuesheet_is_enabled(void); - -/* allocates the cuesheet buffer */ -void cuesheet_init(void); - /* looks if there is a cuesheet file that has a name matching "trackpath" */ bool look_for_cuesheet_file(const char *trackpath, char *found_cue_path); @@ -90,4 +82,7 @@ void cue_draw_markers(struct screen *screen, unsigned long tracklen, int x1, int x2, int y, int h); #endif +/* check if the subtrack has changed */ +bool cuesheet_subtrack_changed(struct mp3entry *id3); + #endif diff --git a/apps/gui/gwps-common.c b/apps/gui/gwps-common.c index c0923a9ab5..dd6ac02d85 100644 --- a/apps/gui/gwps-common.c +++ b/apps/gui/gwps-common.c @@ -355,18 +355,8 @@ bool gui_wps_update(struct gui_wps *gwps) { struct mp3entry *id3 = gwps->state->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 - && id3->elapsed >= (curr_cue->curr_track+1)->offset))) - { - /* We've changed tracks within the cuesheet : - we need to update the ID3 info and refresh the WPS */ - gwps->state->do_full_update = true; - cue_find_current_track(curr_cue, id3->elapsed); - cue_spoof_id3(curr_cue, id3); - } - + gwps->state->do_full_update = gwps->state->do_full_update || + cuesheet_subtrack_changed(id3); retval = gui_wps_redraw(gwps, 0, gwps->state->do_full_update ? WPS_REFRESH_ALL : WPS_REFRESH_NON_STATIC); @@ -421,7 +411,7 @@ static void draw_progressbar(struct gui_wps *gwps, pb->x, pb->x + pb->width, y, pb->height); #endif - if ( cuesheet_is_enabled() && state->id3->cuesheet_type ) + if (state->id3->cuesheet) cue_draw_markers(display, state->id3->length, pb->x, pb->x + pb->width, y+1, pb->height-2); } diff --git a/apps/gui/gwps.c b/apps/gui/gwps.c index 9eea925220..eb1437c910 100644 --- a/apps/gui/gwps.c +++ b/apps/gui/gwps.c @@ -148,7 +148,7 @@ static void prev_track(unsigned long skip_thresh) } else { - if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type) + if (wps_state.id3->cuesheet) { curr_cuesheet_skip(-1, wps_state.id3->elapsed); return; @@ -173,7 +173,7 @@ static void prev_track(unsigned long skip_thresh) static void next_track(void) { /* take care of if we're playing a cuesheet */ - if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type) + if (wps_state.id3->cuesheet) { if (curr_cuesheet_skip(1, wps_state.id3->elapsed)) { @@ -557,7 +557,7 @@ long gui_wps_show(void) break; if (current_tick -last_right < HZ) { - if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type) + if (wps_state.id3->cuesheet) { audio_next(); } @@ -577,7 +577,7 @@ long gui_wps_show(void) break; if (current_tick -last_left < HZ) { - if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type) + if (wps_state.id3->cuesheet) { if (!wps_state.paused) #if (CONFIG_CODEC == SWCODEC) @@ -870,22 +870,10 @@ 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)) + if (wps_state.id3->cuesheet) { - /* 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); + cue_find_current_track(wps_state.id3->cuesheet, wps_state.id3->elapsed); + cue_spoof_id3(wps_state.id3->cuesheet, wps_state.id3); } wps_state.do_full_update = true; } diff --git a/apps/main.c b/apps/main.c index a7c8bef6c0..929c946334 100644 --- a/apps/main.c +++ b/apps/main.c @@ -110,8 +110,6 @@ #include "m5636.h" #endif -#include "cuesheet.h" - #ifdef SIMULATOR #include "sim_tasks.h" #include "system-sdl.h" @@ -336,7 +334,6 @@ static void init(void) #endif /* CONFIG_CODEC != SWCODEC */ scrobbler_init(); - cuesheet_init(); #if CONFIG_CODEC == SWCODEC tdspeed_init(); #endif /* CONFIG_CODEC == SWCODEC */ @@ -552,7 +549,6 @@ static void init(void) tree_mem_init(); filetype_init(); scrobbler_init(); - cuesheet_init(); #if CONFIG_CODEC == SWCODEC tdspeed_init(); #endif /* CONFIG_CODEC == SWCODEC */ diff --git a/apps/menus/playback_menu.c b/apps/menus/playback_menu.c index 28e8601282..1e8670ebea 100644 --- a/apps/menus/playback_menu.c +++ b/apps/menus/playback_menu.c @@ -157,7 +157,7 @@ static int cuesheet_callback(int action,const struct menu_item_ex *this_item) switch (action) { case ACTION_EXIT_MENUITEM: /* on exit */ - if (!cuesheet_is_enabled() && global_settings.cuesheet) + if (global_settings.cuesheet) splash(HZ*2, ID2P(LANG_PLEASE_REBOOT)); break; } diff --git a/apps/metadata.c b/apps/metadata.c index b995e11d95..a0409a83ac 100644 --- a/apps/metadata.c +++ b/apps/metadata.c @@ -394,13 +394,6 @@ bool get_metadata(struct mp3entry* id3, int fd, const char* trackname) } /* We have successfully read the metadata from the file */ - -#ifndef __PCTOOL__ - if (cuesheet_is_enabled() && look_for_cuesheet_file(trackname, NULL)) - { - id3->cuesheet_type = 1; - } -#endif lseek(fd, 0, SEEK_SET); strlcpy(id3->path, trackname, sizeof(id3->path)); diff --git a/apps/metadata.h b/apps/metadata.h index 6c0201781a..f3b50c947d 100644 --- a/apps/metadata.h +++ b/apps/metadata.h @@ -239,7 +239,7 @@ struct mp3entry { #endif /* Cuesheet support */ - int cuesheet_type; /* 0: none, 1: external, 2: embedded */ + struct cuesheet *cuesheet; /* Musicbrainz Track ID */ char* mb_track_id; diff --git a/apps/mpeg.c b/apps/mpeg.c index 0e1217b5c8..5db0272752 100644 --- a/apps/mpeg.c +++ b/apps/mpeg.c @@ -40,6 +40,8 @@ #include "sound.h" #include "bitswap.h" #include "appevents.h" +#include "cuesheet.h" +#include "settings.h" #ifndef SIMULATOR #include "i2c.h" #include "mas.h" @@ -116,8 +118,9 @@ static int track_read_idx = 0; static int track_write_idx = 0; #endif /* !SIMULATOR */ -/* Cuesheet callback */ -static bool (*cuesheet_callback)(const char *filename) = NULL; +/* Cuesheet support */ +static struct cuesheet *curr_cuesheet = NULL; +static bool checked_for_cuesheet = false; static const char mpeg_thread_name[] = "mpeg"; static unsigned int mpeg_errno; @@ -265,6 +268,7 @@ static void remove_current_tag(void) { /* First move the index, so nobody tries to access the tag */ track_read_idx = (track_read_idx+1) & MAX_TRACK_ENTRIES_MASK; + checked_for_cuesheet = false; debug_tags(); } else @@ -470,11 +474,6 @@ unsigned long mpeg_get_last_header(void) #endif /* !SIMULATOR */ } -void audio_set_cuesheet_callback(bool (*handler)(const char *filename)) -{ - cuesheet_callback = handler; -} - #ifndef SIMULATOR /* Send callback events to notify about removing old tracks. */ static void generate_unbuffer_events(void) @@ -878,9 +877,6 @@ static struct trackdata *add_track_to_tag_list(const char *filename) if (track->id3.album) lcd_getstringsize(track->id3.album, NULL, NULL); #endif - if (cuesheet_callback) - 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); @@ -2047,10 +2043,28 @@ static void mpeg_thread(void) struct mp3entry* audio_current_track() { #ifdef SIMULATOR - return &taginfo; + struct mp3entry *id3 = &taginfo; #else /* !SIMULATOR */ if(num_tracks_in_memory()) - return &get_trackdata(0)->id3; + { + struct mp3entry *id3 = &get_trackdata(0)->id3; +#endif + if (!checked_for_cuesheet && curr_cuesheet && id3->cuesheet == NULL) + { + checked_for_cuesheet = true; /* only check once per track */ + char cuepath[MAX_PATH]; + + if (look_for_cuesheet_file(id3->path, cuepath) && + parse_cuesheet(cuepath, curr_cuesheet)) + { + strcpy(curr_cuesheet->audio_filename, id3->path); + id3->cuesheet = curr_cuesheet; + cue_spoof_id3(curr_cuesheet, id3); + } + } + return id3; +#ifndef SIMULATOR + } else return NULL; #endif /* !SIMULATOR */ @@ -2819,6 +2833,19 @@ static void mpeg_thread(void) { id3->elapsed+=1000; id3->offset+=1000; + if (id3->cuesheet) + { + struct cuesheet *cue = id3->cuesheet; + unsigned elapsed = id3->elapsed; + if (elapsed < cue->curr_track->offset || + (cue->curr_track_idx < cue->track_count-1 && + elapsed >= (cue->curr_track+1)->offset)) + { + cue_find_current_track(id3->cuesheet, id3->elapsed); + cue_spoof_id3(id3->cuesheet, id3); + send_event(PLAYBACK_EVENT_CUESHEET_TRACK_CHANGE, id3); + } + } } if (id3->elapsed>=id3->length) audio_next(); @@ -2831,6 +2858,9 @@ static void mpeg_thread(void) void audio_init(void) { mpeg_errno = 0; + /* cuesheet support */ + if (global_settings.cuesheet) + curr_cuesheet = (struct cuesheet*)buffer_alloc(sizeof(struct cuesheet)); #ifndef SIMULATOR audiobuflen = audiobufend - audiobuf; diff --git a/apps/onplay.c b/apps/onplay.c index 9f38b32fb4..ad71f7302e 100644 --- a/apps/onplay.c +++ b/apps/onplay.c @@ -967,9 +967,9 @@ MENUITEM_FUNCTION(rating_item, 0, ID2P(LANG_MENU_SET_RATING), static bool view_cue(void) { struct mp3entry* id3 = audio_current_track(); - if(id3 && cuesheet_is_enabled() && id3->cuesheet_type) + if(id3 && id3->cuesheet) { - browse_cuesheet(curr_cue); + browse_cuesheet(id3->cuesheet); } return false; } @@ -981,8 +981,8 @@ static int view_cue_item_callback(int action, switch (action) { case ACTION_REQUEST_MENUITEM: - if (!selected_file || !cuesheet_is_enabled() - || !id3 || !id3->cuesheet_type) + if (!selected_file + || !id3 || !id3->cuesheet) return ACTION_EXIT_MENUITEM; break; } diff --git a/apps/playback.c b/apps/playback.c index cee89d3bbb..7bd3f252ae 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -210,6 +210,9 @@ static struct mp3entry *thistrack_id3, /* the currently playing track */ * next track otherwise */ static struct mp3entry unbuffered_id3; /* the id3 for the first unbuffered track */ +/* for cuesheet support */ +static struct cuesheet *curr_cue = NULL; + /* Track info structure about songs in the file buffer (A/C-) */ struct track_info { int audio_hid; /* The ID for the track's buffer handle */ @@ -218,6 +221,7 @@ struct track_info { #ifdef HAVE_ALBUMART int aa_hid; /* The ID for the track's album art handle */ #endif + int cuesheet_hid; /* The ID for the track's parsed cueesheet handle */ size_t filesize; /* File total length */ @@ -384,6 +388,13 @@ static bool clear_track_info(struct track_info *track) } #endif + if (track->cuesheet_hid >= 0) { + if (bufclose(track->cuesheet_hid)) + track->cuesheet_hid = -1; + else + return false; + } + track->filesize = 0; track->taginfo_ready = false; @@ -566,6 +577,12 @@ struct mp3entry* audio_current_track(void) if (cur_idx == track_ridx && *thistrack_id3->path) { /* The usual case */ + if (tracks[cur_idx].cuesheet_hid >= 0) + { + bufread(tracks[cur_idx].cuesheet_hid, sizeof(struct cuesheet), curr_cue); + thistrack_id3->cuesheet = curr_cue; + cue_spoof_id3(thistrack_id3->cuesheet, thistrack_id3); + } return thistrack_id3; } else if (automatic_skip && offset == -1 && *othertrack_id3->path) @@ -574,6 +591,12 @@ struct mp3entry* audio_current_track(void) 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 */ + if (tracks[cur_idx].cuesheet_hid >= 0) + { + bufread(tracks[cur_idx].cuesheet_hid, sizeof(struct cuesheet), curr_cue); + othertrack_id3->cuesheet = curr_cue; + cue_spoof_id3(othertrack_id3->cuesheet, othertrack_id3); + } return othertrack_id3; } @@ -1826,7 +1849,21 @@ static void audio_finish_load_track(void) return; } + /* Try to load a cuesheet for the track */ + if (curr_cue) + { + char cuepath[MAX_PATH]; + struct cuesheet temp_cue; + + if (look_for_cuesheet_file(track_id3->path, cuepath) && + parse_cuesheet(cuepath, &temp_cue)) + { + strcpy(temp_cue.audio_filename, track_id3->path); + tracks[track_widx].cuesheet_hid = + bufalloc(&temp_cue, sizeof(struct cuesheet), TYPE_CUESHEET); + } + } #ifdef HAVE_ALBUMART if (tracks[track_widx].aa_hid < 0 && gui_sync_wps_uses_albumart()) { @@ -2602,6 +2639,10 @@ void audio_init(void) thistrack_id3 = &mp3entry_buf[0]; othertrack_id3 = &mp3entry_buf[1]; + /* cuesheet support */ + if (global_settings.cuesheet) + curr_cue = (struct cuesheet*)buffer_alloc(sizeof(struct cuesheet)); + /* initialize the buffer */ filebuf = audiobuf; @@ -2648,6 +2689,7 @@ void audio_init(void) #ifdef HAVE_ALBUMART tracks[i].aa_hid = -1; #endif + tracks[i].cuesheet_hid = -1; } add_event(BUFFER_EVENT_REBUFFER, false, buffering_handle_rebuffer_callback);