summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Gordon <rockbox@jdgordon.info>2009-07-20 05:18:18 +0000
committerJonathan Gordon <rockbox@jdgordon.info>2009-07-20 05:18:18 +0000
commit24b136f62de82d7419751b6aaeae0ad3d8497bea (patch)
treeb9bcfd07ca26f3da2f0ce500fc39e0719b3cbb8a
parent4c4fb82d9c112ccbcc4c94a7d85fe82d09801844 (diff)
downloadrockbox-24b136f62de82d7419751b6aaeae0ad3d8497bea.tar.gz
rockbox-24b136f62de82d7419751b6aaeae0ad3d8497bea.zip
rework cuesheet support:
swcodec: search for a .cue during buffering (with the possibility of adding embedded cuesheets later) hwcodec: search for a .cue when the id3 info for the current track is requested for the first time (disk should be spining so non issue) major beenfit from this is simplofy cuesheet handling code a bit... if mp3entry.cuesheet != NULL then there is a valid cuesheet.. no need to worry about if its enabled and preloaded. There is the possibility of putting the next/prev subtrack handling inside the playback code (as well as the id3 updating stuff (see FS#9789 for more info), but thats probably not a good idea. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21978 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/cuesheet.c54
-rw-r--r--apps/cuesheet.h11
-rw-r--r--apps/gui/gwps-common.c16
-rw-r--r--apps/gui/gwps.c26
-rw-r--r--apps/main.c4
-rw-r--r--apps/menus/playback_menu.c2
-rw-r--r--apps/metadata.c7
-rw-r--r--apps/metadata.h2
-rw-r--r--apps/mpeg.c54
-rw-r--r--apps/onplay.c8
-rw-r--r--apps/playback.c42
11 files changed, 122 insertions, 104 deletions
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 @@
43 43
44#define CUE_DIR ROCKBOX_DIR "/cue" 44#define CUE_DIR ROCKBOX_DIR "/cue"
45 45
46struct cuesheet *curr_cue;
47
48#if CONFIG_CODEC != SWCODEC
49/* special trickery because the hwcodec playback engine is in firmware/ */
50static bool cuesheet_handler(const char *filename)
51{
52 return cuesheet_is_enabled() && look_for_cuesheet_file(filename, NULL);
53}
54#endif
55
56void cuesheet_init(void)
57{
58 if (global_settings.cuesheet) {
59 curr_cue = (struct cuesheet *)buffer_alloc(sizeof(struct cuesheet));
60#if CONFIG_CODEC != SWCODEC
61 audio_set_cuesheet_callback(cuesheet_handler);
62#endif
63 } else {
64 curr_cue = NULL;
65 }
66}
67
68bool cuesheet_is_enabled(void)
69{
70 return (curr_cue != NULL);
71}
72
73bool look_for_cuesheet_file(const char *trackpath, char *found_cue_path) 46bool look_for_cuesheet_file(const char *trackpath, char *found_cue_path)
74{ 47{
75 /* DEBUGF("look for cue file\n"); */ 48 /* DEBUGF("look for cue file\n"); */
@@ -134,7 +107,6 @@ bool parse_cuesheet(char *file, struct cuesheet *cue)
134 char *s; 107 char *s;
135 bool utf8 = false; 108 bool utf8 = false;
136 109
137 DEBUGF("cue parse\n");
138 int fd = open_utf8(file,O_RDONLY); 110 int fd = open_utf8(file,O_RDONLY);
139 if (fd < 0) 111 if (fd < 0)
140 { 112 {
@@ -293,12 +265,8 @@ void browse_cuesheet(struct cuesheet *cue)
293 gui_synclist_set_nb_items(&lists, 2*cue->track_count); 265 gui_synclist_set_nb_items(&lists, 2*cue->track_count);
294 gui_synclist_set_title(&lists, title, 0); 266 gui_synclist_set_title(&lists, title, 0);
295 267
296 if (id3 && *id3->path && strcmp(id3->path, "No file!"))
297 {
298 look_for_cuesheet_file(id3->path, cuepath);
299 }
300 268
301 if (id3 && id3->cuesheet_type && !strcmp(cue->path, cuepath)) 269 if (id3)
302 { 270 {
303 gui_synclist_select_item(&lists, 271 gui_synclist_select_item(&lists,
304 2*cue_find_current_track(cue, id3->elapsed)); 272 2*cue_find_current_track(cue, id3->elapsed));
@@ -317,7 +285,7 @@ void browse_cuesheet(struct cuesheet *cue)
317 if (id3 && *id3->path && strcmp(id3->path, "No file!")) 285 if (id3 && *id3->path && strcmp(id3->path, "No file!"))
318 { 286 {
319 look_for_cuesheet_file(id3->path, cuepath); 287 look_for_cuesheet_file(id3->path, cuepath);
320 if (id3->cuesheet_type && !strcmp(cue->path, cuepath)) 288 if (id3->cuesheet && !strcmp(cue->path, cuepath))
321 { 289 {
322 sel = gui_synclist_get_sel_pos(&lists); 290 sel = gui_synclist_get_sel_pos(&lists);
323 seek(cue->tracks[sel/2].offset); 291 seek(cue->tracks[sel/2].offset);
@@ -351,8 +319,9 @@ bool display_cuesheet_content(char* filename)
351 */ 319 */
352bool curr_cuesheet_skip(int direction, unsigned long curr_pos) 320bool curr_cuesheet_skip(int direction, unsigned long curr_pos)
353{ 321{
322 struct cuesheet *curr_cue = audio_current_track()->cuesheet;
354 int track = cue_find_current_track(curr_cue, curr_pos); 323 int track = cue_find_current_track(curr_cue, curr_pos);
355 324
356 if (direction >= 0 && track == curr_cue->track_count - 1) 325 if (direction >= 0 && track == curr_cue->track_count - 1)
357 { 326 {
358 /* we want to get out of the cuesheet */ 327 /* we want to get out of the cuesheet */
@@ -406,6 +375,7 @@ static inline void draw_veritcal_line_mark(struct screen * screen,
406void cue_draw_markers(struct screen *screen, unsigned long tracklen, 375void cue_draw_markers(struct screen *screen, unsigned long tracklen,
407 int x1, int x2, int y, int h) 376 int x1, int x2, int y, int h)
408{ 377{
378 struct cuesheet *curr_cue = audio_current_track()->cuesheet;
409 int i,xi; 379 int i,xi;
410 int w = x2 - x1; 380 int w = x2 - x1;
411 for (i=1; i < curr_cue->track_count; i++) 381 for (i=1; i < curr_cue->track_count; i++)
@@ -415,3 +385,17 @@ void cue_draw_markers(struct screen *screen, unsigned long tracklen,
415 } 385 }
416} 386}
417#endif 387#endif
388
389bool cuesheet_subtrack_changed(struct mp3entry *id3)
390{
391 struct cuesheet *cue = id3->cuesheet;
392 if (cue && (id3->elapsed < cue->curr_track->offset
393 || (cue->curr_track_idx < cue->track_count - 1
394 && id3->elapsed >= (cue->curr_track+1)->offset)))
395 {
396 cue_find_current_track(cue, id3->elapsed);
397 cue_spoof_id3(cue, id3);
398 return true;
399 }
400 return false;
401}
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 {
52 struct cue_track_info *curr_track; 52 struct cue_track_info *curr_track;
53}; 53};
54 54
55extern struct cuesheet *curr_cue;
56
57/* returns true if cuesheet support is initialised */
58bool cuesheet_is_enabled(void);
59
60/* allocates the cuesheet buffer */
61void cuesheet_init(void);
62
63/* looks if there is a cuesheet file that has a name matching "trackpath" */ 55/* looks if there is a cuesheet file that has a name matching "trackpath" */
64bool look_for_cuesheet_file(const char *trackpath, char *found_cue_path); 56bool look_for_cuesheet_file(const char *trackpath, char *found_cue_path);
65 57
@@ -90,4 +82,7 @@ void cue_draw_markers(struct screen *screen, unsigned long tracklen,
90 int x1, int x2, int y, int h); 82 int x1, int x2, int y, int h);
91#endif 83#endif
92 84
85/* check if the subtrack has changed */
86bool cuesheet_subtrack_changed(struct mp3entry *id3);
87
93#endif 88#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)
355{ 355{
356 struct mp3entry *id3 = gwps->state->id3; 356 struct mp3entry *id3 = gwps->state->id3;
357 bool retval; 357 bool retval;
358 if (cuesheet_is_enabled() && id3->cuesheet_type 358 gwps->state->do_full_update = gwps->state->do_full_update ||
359 && (id3->elapsed < curr_cue->curr_track->offset 359 cuesheet_subtrack_changed(id3);
360 || (curr_cue->curr_track_idx < curr_cue->track_count - 1
361 && id3->elapsed >= (curr_cue->curr_track+1)->offset)))
362 {
363 /* We've changed tracks within the cuesheet :
364 we need to update the ID3 info and refresh the WPS */
365 gwps->state->do_full_update = true;
366 cue_find_current_track(curr_cue, id3->elapsed);
367 cue_spoof_id3(curr_cue, id3);
368 }
369
370 retval = gui_wps_redraw(gwps, 0, 360 retval = gui_wps_redraw(gwps, 0,
371 gwps->state->do_full_update ? 361 gwps->state->do_full_update ?
372 WPS_REFRESH_ALL : WPS_REFRESH_NON_STATIC); 362 WPS_REFRESH_ALL : WPS_REFRESH_NON_STATIC);
@@ -421,7 +411,7 @@ static void draw_progressbar(struct gui_wps *gwps,
421 pb->x, pb->x + pb->width, y, pb->height); 411 pb->x, pb->x + pb->width, y, pb->height);
422#endif 412#endif
423 413
424 if ( cuesheet_is_enabled() && state->id3->cuesheet_type ) 414 if (state->id3->cuesheet)
425 cue_draw_markers(display, state->id3->length, 415 cue_draw_markers(display, state->id3->length,
426 pb->x, pb->x + pb->width, y+1, pb->height-2); 416 pb->x, pb->x + pb->width, y+1, pb->height-2);
427} 417}
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)
148 } 148 }
149 else 149 else
150 { 150 {
151 if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type) 151 if (wps_state.id3->cuesheet)
152 { 152 {
153 curr_cuesheet_skip(-1, wps_state.id3->elapsed); 153 curr_cuesheet_skip(-1, wps_state.id3->elapsed);
154 return; 154 return;
@@ -173,7 +173,7 @@ static void prev_track(unsigned long skip_thresh)
173static void next_track(void) 173static void next_track(void)
174{ 174{
175 /* take care of if we're playing a cuesheet */ 175 /* take care of if we're playing a cuesheet */
176 if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type) 176 if (wps_state.id3->cuesheet)
177 { 177 {
178 if (curr_cuesheet_skip(1, wps_state.id3->elapsed)) 178 if (curr_cuesheet_skip(1, wps_state.id3->elapsed))
179 { 179 {
@@ -557,7 +557,7 @@ long gui_wps_show(void)
557 break; 557 break;
558 if (current_tick -last_right < HZ) 558 if (current_tick -last_right < HZ)
559 { 559 {
560 if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type) 560 if (wps_state.id3->cuesheet)
561 { 561 {
562 audio_next(); 562 audio_next();
563 } 563 }
@@ -577,7 +577,7 @@ long gui_wps_show(void)
577 break; 577 break;
578 if (current_tick -last_left < HZ) 578 if (current_tick -last_left < HZ)
579 { 579 {
580 if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type) 580 if (wps_state.id3->cuesheet)
581 { 581 {
582 if (!wps_state.paused) 582 if (!wps_state.paused)
583#if (CONFIG_CODEC == SWCODEC) 583#if (CONFIG_CODEC == SWCODEC)
@@ -870,22 +870,10 @@ static void track_changed_callback(void *param)
870{ 870{
871 wps_state.id3 = (struct mp3entry*)param; 871 wps_state.id3 = (struct mp3entry*)param;
872 wps_state.nid3 = audio_next_track(); 872 wps_state.nid3 = audio_next_track();
873 873 if (wps_state.id3->cuesheet)
874 if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type
875 && strcmp(wps_state.id3->path, curr_cue->audio_filename))
876 { 874 {
877 /* the current cuesheet isn't the right one any more */ 875 cue_find_current_track(wps_state.id3->cuesheet, wps_state.id3->elapsed);
878 /* We need to parse the new cuesheet */ 876 cue_spoof_id3(wps_state.id3->cuesheet, wps_state.id3);
879 char cuepath[MAX_PATH];
880
881 if (look_for_cuesheet_file(wps_state.id3->path, cuepath) &&
882 parse_cuesheet(cuepath, curr_cue))
883 {
884 wps_state.id3->cuesheet_type = 1;
885 strcpy(curr_cue->audio_filename, wps_state.id3->path);
886 }
887
888 cue_spoof_id3(curr_cue, wps_state.id3);
889 } 877 }
890 wps_state.do_full_update = true; 878 wps_state.do_full_update = true;
891} 879}
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 @@
110#include "m5636.h" 110#include "m5636.h"
111#endif 111#endif
112 112
113#include "cuesheet.h"
114
115#ifdef SIMULATOR 113#ifdef SIMULATOR
116#include "sim_tasks.h" 114#include "sim_tasks.h"
117#include "system-sdl.h" 115#include "system-sdl.h"
@@ -336,7 +334,6 @@ static void init(void)
336#endif /* CONFIG_CODEC != SWCODEC */ 334#endif /* CONFIG_CODEC != SWCODEC */
337 335
338 scrobbler_init(); 336 scrobbler_init();
339 cuesheet_init();
340#if CONFIG_CODEC == SWCODEC 337#if CONFIG_CODEC == SWCODEC
341 tdspeed_init(); 338 tdspeed_init();
342#endif /* CONFIG_CODEC == SWCODEC */ 339#endif /* CONFIG_CODEC == SWCODEC */
@@ -552,7 +549,6 @@ static void init(void)
552 tree_mem_init(); 549 tree_mem_init();
553 filetype_init(); 550 filetype_init();
554 scrobbler_init(); 551 scrobbler_init();
555 cuesheet_init();
556#if CONFIG_CODEC == SWCODEC 552#if CONFIG_CODEC == SWCODEC
557 tdspeed_init(); 553 tdspeed_init();
558#endif /* CONFIG_CODEC == SWCODEC */ 554#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)
157 switch (action) 157 switch (action)
158 { 158 {
159 case ACTION_EXIT_MENUITEM: /* on exit */ 159 case ACTION_EXIT_MENUITEM: /* on exit */
160 if (!cuesheet_is_enabled() && global_settings.cuesheet) 160 if (global_settings.cuesheet)
161 splash(HZ*2, ID2P(LANG_PLEASE_REBOOT)); 161 splash(HZ*2, ID2P(LANG_PLEASE_REBOOT));
162 break; 162 break;
163 } 163 }
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)
394 } 394 }
395 395
396 /* We have successfully read the metadata from the file */ 396 /* We have successfully read the metadata from the file */
397
398#ifndef __PCTOOL__
399 if (cuesheet_is_enabled() && look_for_cuesheet_file(trackname, NULL))
400 {
401 id3->cuesheet_type = 1;
402 }
403#endif
404 397
405 lseek(fd, 0, SEEK_SET); 398 lseek(fd, 0, SEEK_SET);
406 strlcpy(id3->path, trackname, sizeof(id3->path)); 399 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 {
239#endif 239#endif
240 240
241 /* Cuesheet support */ 241 /* Cuesheet support */
242 int cuesheet_type; /* 0: none, 1: external, 2: embedded */ 242 struct cuesheet *cuesheet;
243 243
244 /* Musicbrainz Track ID */ 244 /* Musicbrainz Track ID */
245 char* mb_track_id; 245 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 @@
40#include "sound.h" 40#include "sound.h"
41#include "bitswap.h" 41#include "bitswap.h"
42#include "appevents.h" 42#include "appevents.h"
43#include "cuesheet.h"
44#include "settings.h"
43#ifndef SIMULATOR 45#ifndef SIMULATOR
44#include "i2c.h" 46#include "i2c.h"
45#include "mas.h" 47#include "mas.h"
@@ -116,8 +118,9 @@ static int track_read_idx = 0;
116static int track_write_idx = 0; 118static int track_write_idx = 0;
117#endif /* !SIMULATOR */ 119#endif /* !SIMULATOR */
118 120
119/* Cuesheet callback */ 121/* Cuesheet support */
120static bool (*cuesheet_callback)(const char *filename) = NULL; 122static struct cuesheet *curr_cuesheet = NULL;
123static bool checked_for_cuesheet = false;
121 124
122static const char mpeg_thread_name[] = "mpeg"; 125static const char mpeg_thread_name[] = "mpeg";
123static unsigned int mpeg_errno; 126static unsigned int mpeg_errno;
@@ -265,6 +268,7 @@ static void remove_current_tag(void)
265 { 268 {
266 /* First move the index, so nobody tries to access the tag */ 269 /* First move the index, so nobody tries to access the tag */
267 track_read_idx = (track_read_idx+1) & MAX_TRACK_ENTRIES_MASK; 270 track_read_idx = (track_read_idx+1) & MAX_TRACK_ENTRIES_MASK;
271 checked_for_cuesheet = false;
268 debug_tags(); 272 debug_tags();
269 } 273 }
270 else 274 else
@@ -470,11 +474,6 @@ unsigned long mpeg_get_last_header(void)
470#endif /* !SIMULATOR */ 474#endif /* !SIMULATOR */
471} 475}
472 476
473void audio_set_cuesheet_callback(bool (*handler)(const char *filename))
474{
475 cuesheet_callback = handler;
476}
477
478#ifndef SIMULATOR 477#ifndef SIMULATOR
479/* Send callback events to notify about removing old tracks. */ 478/* Send callback events to notify about removing old tracks. */
480static void generate_unbuffer_events(void) 479static void generate_unbuffer_events(void)
@@ -878,9 +877,6 @@ static struct trackdata *add_track_to_tag_list(const char *filename)
878 if (track->id3.album) 877 if (track->id3.album)
879 lcd_getstringsize(track->id3.album, NULL, NULL); 878 lcd_getstringsize(track->id3.album, NULL, NULL);
880#endif 879#endif
881 if (cuesheet_callback)
882 if (cuesheet_callback(filename))
883 track->id3.cuesheet_type = 1;
884 880
885 /* if this track is the next track then let the UI know it can get it */ 881 /* if this track is the next track then let the UI know it can get it */
886 send_nid3_event = (track_write_idx == track_read_idx + 1); 882 send_nid3_event = (track_write_idx == track_read_idx + 1);
@@ -2047,10 +2043,28 @@ static void mpeg_thread(void)
2047struct mp3entry* audio_current_track() 2043struct mp3entry* audio_current_track()
2048{ 2044{
2049#ifdef SIMULATOR 2045#ifdef SIMULATOR
2050 return &taginfo; 2046 struct mp3entry *id3 = &taginfo;
2051#else /* !SIMULATOR */ 2047#else /* !SIMULATOR */
2052 if(num_tracks_in_memory()) 2048 if(num_tracks_in_memory())
2053 return &get_trackdata(0)->id3; 2049 {
2050 struct mp3entry *id3 = &get_trackdata(0)->id3;
2051#endif
2052 if (!checked_for_cuesheet && curr_cuesheet && id3->cuesheet == NULL)
2053 {
2054 checked_for_cuesheet = true; /* only check once per track */
2055 char cuepath[MAX_PATH];
2056
2057 if (look_for_cuesheet_file(id3->path, cuepath) &&
2058 parse_cuesheet(cuepath, curr_cuesheet))
2059 {
2060 strcpy(curr_cuesheet->audio_filename, id3->path);
2061 id3->cuesheet = curr_cuesheet;
2062 cue_spoof_id3(curr_cuesheet, id3);
2063 }
2064 }
2065 return id3;
2066#ifndef SIMULATOR
2067 }
2054 else 2068 else
2055 return NULL; 2069 return NULL;
2056#endif /* !SIMULATOR */ 2070#endif /* !SIMULATOR */
@@ -2819,6 +2833,19 @@ static void mpeg_thread(void)
2819 { 2833 {
2820 id3->elapsed+=1000; 2834 id3->elapsed+=1000;
2821 id3->offset+=1000; 2835 id3->offset+=1000;
2836 if (id3->cuesheet)
2837 {
2838 struct cuesheet *cue = id3->cuesheet;
2839 unsigned elapsed = id3->elapsed;
2840 if (elapsed < cue->curr_track->offset ||
2841 (cue->curr_track_idx < cue->track_count-1 &&
2842 elapsed >= (cue->curr_track+1)->offset))
2843 {
2844 cue_find_current_track(id3->cuesheet, id3->elapsed);
2845 cue_spoof_id3(id3->cuesheet, id3);
2846 send_event(PLAYBACK_EVENT_CUESHEET_TRACK_CHANGE, id3);
2847 }
2848 }
2822 } 2849 }
2823 if (id3->elapsed>=id3->length) 2850 if (id3->elapsed>=id3->length)
2824 audio_next(); 2851 audio_next();
@@ -2831,6 +2858,9 @@ static void mpeg_thread(void)
2831void audio_init(void) 2858void audio_init(void)
2832{ 2859{
2833 mpeg_errno = 0; 2860 mpeg_errno = 0;
2861 /* cuesheet support */
2862 if (global_settings.cuesheet)
2863 curr_cuesheet = (struct cuesheet*)buffer_alloc(sizeof(struct cuesheet));
2834 2864
2835#ifndef SIMULATOR 2865#ifndef SIMULATOR
2836 audiobuflen = audiobufend - audiobuf; 2866 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),
967static bool view_cue(void) 967static bool view_cue(void)
968{ 968{
969 struct mp3entry* id3 = audio_current_track(); 969 struct mp3entry* id3 = audio_current_track();
970 if(id3 && cuesheet_is_enabled() && id3->cuesheet_type) 970 if(id3 && id3->cuesheet)
971 { 971 {
972 browse_cuesheet(curr_cue); 972 browse_cuesheet(id3->cuesheet);
973 } 973 }
974 return false; 974 return false;
975} 975}
@@ -981,8 +981,8 @@ static int view_cue_item_callback(int action,
981 switch (action) 981 switch (action)
982 { 982 {
983 case ACTION_REQUEST_MENUITEM: 983 case ACTION_REQUEST_MENUITEM:
984 if (!selected_file || !cuesheet_is_enabled() 984 if (!selected_file
985 || !id3 || !id3->cuesheet_type) 985 || !id3 || !id3->cuesheet)
986 return ACTION_EXIT_MENUITEM; 986 return ACTION_EXIT_MENUITEM;
987 break; 987 break;
988 } 988 }
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 */
210 * next track otherwise */ 210 * next track otherwise */
211static struct mp3entry unbuffered_id3; /* the id3 for the first unbuffered track */ 211static struct mp3entry unbuffered_id3; /* the id3 for the first unbuffered track */
212 212
213/* for cuesheet support */
214static struct cuesheet *curr_cue = NULL;
215
213/* Track info structure about songs in the file buffer (A/C-) */ 216/* Track info structure about songs in the file buffer (A/C-) */
214struct track_info { 217struct track_info {
215 int audio_hid; /* The ID for the track's buffer handle */ 218 int audio_hid; /* The ID for the track's buffer handle */
@@ -218,6 +221,7 @@ struct track_info {
218#ifdef HAVE_ALBUMART 221#ifdef HAVE_ALBUMART
219 int aa_hid; /* The ID for the track's album art handle */ 222 int aa_hid; /* The ID for the track's album art handle */
220#endif 223#endif
224 int cuesheet_hid; /* The ID for the track's parsed cueesheet handle */
221 225
222 size_t filesize; /* File total length */ 226 size_t filesize; /* File total length */
223 227
@@ -384,6 +388,13 @@ static bool clear_track_info(struct track_info *track)
384 } 388 }
385#endif 389#endif
386 390
391 if (track->cuesheet_hid >= 0) {
392 if (bufclose(track->cuesheet_hid))
393 track->cuesheet_hid = -1;
394 else
395 return false;
396 }
397
387 track->filesize = 0; 398 track->filesize = 0;
388 track->taginfo_ready = false; 399 track->taginfo_ready = false;
389 400
@@ -566,6 +577,12 @@ struct mp3entry* audio_current_track(void)
566 if (cur_idx == track_ridx && *thistrack_id3->path) 577 if (cur_idx == track_ridx && *thistrack_id3->path)
567 { 578 {
568 /* The usual case */ 579 /* The usual case */
580 if (tracks[cur_idx].cuesheet_hid >= 0)
581 {
582 bufread(tracks[cur_idx].cuesheet_hid, sizeof(struct cuesheet), curr_cue);
583 thistrack_id3->cuesheet = curr_cue;
584 cue_spoof_id3(thistrack_id3->cuesheet, thistrack_id3);
585 }
569 return thistrack_id3; 586 return thistrack_id3;
570 } 587 }
571 else if (automatic_skip && offset == -1 && *othertrack_id3->path) 588 else if (automatic_skip && offset == -1 && *othertrack_id3->path)
@@ -574,6 +591,12 @@ struct mp3entry* audio_current_track(void)
574 but the audio being played is still the same (now previous) track. 591 but the audio being played is still the same (now previous) track.
575 othertrack_id3.elapsed is being updated in an ISR by 592 othertrack_id3.elapsed is being updated in an ISR by
576 codec_pcmbuf_position_callback */ 593 codec_pcmbuf_position_callback */
594 if (tracks[cur_idx].cuesheet_hid >= 0)
595 {
596 bufread(tracks[cur_idx].cuesheet_hid, sizeof(struct cuesheet), curr_cue);
597 othertrack_id3->cuesheet = curr_cue;
598 cue_spoof_id3(othertrack_id3->cuesheet, othertrack_id3);
599 }
577 return othertrack_id3; 600 return othertrack_id3;
578 } 601 }
579 602
@@ -1826,7 +1849,21 @@ static void audio_finish_load_track(void)
1826 1849
1827 return; 1850 return;
1828 } 1851 }
1852 /* Try to load a cuesheet for the track */
1853 if (curr_cue)
1854 {
1855 char cuepath[MAX_PATH];
1829 1856
1857 struct cuesheet temp_cue;
1858
1859 if (look_for_cuesheet_file(track_id3->path, cuepath) &&
1860 parse_cuesheet(cuepath, &temp_cue))
1861 {
1862 strcpy(temp_cue.audio_filename, track_id3->path);
1863 tracks[track_widx].cuesheet_hid =
1864 bufalloc(&temp_cue, sizeof(struct cuesheet), TYPE_CUESHEET);
1865 }
1866 }
1830#ifdef HAVE_ALBUMART 1867#ifdef HAVE_ALBUMART
1831 if (tracks[track_widx].aa_hid < 0 && gui_sync_wps_uses_albumart()) 1868 if (tracks[track_widx].aa_hid < 0 && gui_sync_wps_uses_albumart())
1832 { 1869 {
@@ -2602,6 +2639,10 @@ void audio_init(void)
2602 thistrack_id3 = &mp3entry_buf[0]; 2639 thistrack_id3 = &mp3entry_buf[0];
2603 othertrack_id3 = &mp3entry_buf[1]; 2640 othertrack_id3 = &mp3entry_buf[1];
2604 2641
2642 /* cuesheet support */
2643 if (global_settings.cuesheet)
2644 curr_cue = (struct cuesheet*)buffer_alloc(sizeof(struct cuesheet));
2645
2605 /* initialize the buffer */ 2646 /* initialize the buffer */
2606 filebuf = audiobuf; 2647 filebuf = audiobuf;
2607 2648
@@ -2648,6 +2689,7 @@ void audio_init(void)
2648#ifdef HAVE_ALBUMART 2689#ifdef HAVE_ALBUMART
2649 tracks[i].aa_hid = -1; 2690 tracks[i].aa_hid = -1;
2650#endif 2691#endif
2692 tracks[i].cuesheet_hid = -1;
2651 } 2693 }
2652 2694
2653 add_event(BUFFER_EVENT_REBUFFER, false, buffering_handle_rebuffer_callback); 2695 add_event(BUFFER_EVENT_REBUFFER, false, buffering_handle_rebuffer_callback);