diff options
Diffstat (limited to 'apps/cuesheet.c')
-rw-r--r-- | apps/cuesheet.c | 104 |
1 files changed, 79 insertions, 25 deletions
diff --git a/apps/cuesheet.c b/apps/cuesheet.c index 73dd19fdab..52b8c5703b 100644 --- a/apps/cuesheet.c +++ b/apps/cuesheet.c | |||
@@ -42,30 +42,20 @@ | |||
42 | 42 | ||
43 | #define CUE_DIR ROCKBOX_DIR "/cue" | 43 | #define CUE_DIR ROCKBOX_DIR "/cue" |
44 | 44 | ||
45 | bool look_for_cuesheet_file(struct mp3entry *track_id3, struct cuesheet_file *cue_file) | 45 | static bool search_for_cuesheet(const char *path, struct cuesheet_file *cue_file) |
46 | { | 46 | { |
47 | /* DEBUGF("look for cue file\n"); */ | ||
48 | size_t len; | 47 | size_t len; |
49 | char cuepath[MAX_PATH]; | 48 | char cuepath[MAX_PATH]; |
50 | char *dot, *slash, *slash_cuepath; | 49 | char *dot, *slash, *slash_cuepath; |
51 | 50 | ||
52 | if (track_id3->has_embedded_cuesheet) | ||
53 | { | ||
54 | cue_file->pos = track_id3->embedded_cuesheet.pos; | ||
55 | cue_file->size = track_id3->embedded_cuesheet.size; | ||
56 | cue_file->encoding = track_id3->embedded_cuesheet.encoding; | ||
57 | strlcpy(cue_file->path, track_id3->path, MAX_PATH); | ||
58 | return true; | ||
59 | } | ||
60 | |||
61 | cue_file->pos = 0; | 51 | cue_file->pos = 0; |
62 | cue_file->size = 0; | 52 | cue_file->size = 0; |
63 | cue_file->path[0] = '\0'; | 53 | cue_file->path[0] = '\0'; |
64 | slash = strrchr(track_id3->path, '/'); | 54 | slash = strrchr(path, '/'); |
65 | if (!slash) | 55 | if (!slash) |
66 | return false; | 56 | return false; |
67 | len = strlcpy(cuepath, track_id3->path, MAX_PATH); | 57 | len = strlcpy(cuepath, path, MAX_PATH); |
68 | slash_cuepath = &cuepath[slash - track_id3->path]; | 58 | slash_cuepath = &cuepath[slash - path]; |
69 | dot = strrchr(slash_cuepath, '.'); | 59 | dot = strrchr(slash_cuepath, '.'); |
70 | if (dot) | 60 | if (dot) |
71 | strlcpy(dot, ".cue", MAX_PATH - (dot-cuepath)); | 61 | strlcpy(dot, ".cue", MAX_PATH - (dot-cuepath)); |
@@ -82,7 +72,7 @@ bool look_for_cuesheet_file(struct mp3entry *track_id3, struct cuesheet_file *cu | |||
82 | skip: | 72 | skip: |
83 | if ((len+4) >= MAX_PATH) | 73 | if ((len+4) >= MAX_PATH) |
84 | return false; | 74 | return false; |
85 | strlcpy(cuepath, track_id3->path, MAX_PATH); | 75 | strlcpy(cuepath, path, MAX_PATH); |
86 | strlcat(cuepath, ".cue", MAX_PATH); | 76 | strlcat(cuepath, ".cue", MAX_PATH); |
87 | if (!file_exists(cuepath)) | 77 | if (!file_exists(cuepath)) |
88 | return false; | 78 | return false; |
@@ -93,6 +83,21 @@ skip: | |||
93 | return true; | 83 | return true; |
94 | } | 84 | } |
95 | 85 | ||
86 | bool look_for_cuesheet_file(struct mp3entry *track_id3, struct cuesheet_file *cue_file) | ||
87 | { | ||
88 | /* DEBUGF("look for cue file\n"); */ | ||
89 | if (track_id3->has_embedded_cuesheet) | ||
90 | { | ||
91 | cue_file->pos = track_id3->embedded_cuesheet.pos; | ||
92 | cue_file->size = track_id3->embedded_cuesheet.size; | ||
93 | cue_file->encoding = track_id3->embedded_cuesheet.encoding; | ||
94 | strlcpy(cue_file->path, track_id3->path, MAX_PATH); | ||
95 | return true; | ||
96 | } | ||
97 | |||
98 | return search_for_cuesheet(track_id3->path, cue_file); | ||
99 | } | ||
100 | |||
96 | static char *get_string(const char *line) | 101 | static char *get_string(const char *line) |
97 | { | 102 | { |
98 | char *start, *end; | 103 | char *start, *end; |
@@ -169,6 +174,9 @@ bool parse_cuesheet(struct cuesheet_file *cue_file, struct cuesheet *cue) | |||
169 | strcpy(cue->path, cue_file->path); | 174 | strcpy(cue->path, cue_file->path); |
170 | cue->curr_track = cue->tracks; | 175 | cue->curr_track = cue->tracks; |
171 | 176 | ||
177 | if (is_embedded) | ||
178 | strcpy(cue->file, cue->path); | ||
179 | |||
172 | while ((line_len = read_line(fd, line, read_bytes)) > 0 | 180 | while ((line_len = read_line(fd, line, read_bytes)) > 0 |
173 | && cue->track_count < MAX_TRACKS ) | 181 | && cue->track_count < MAX_TRACKS ) |
174 | { | 182 | { |
@@ -208,13 +216,17 @@ bool parse_cuesheet(struct cuesheet_file *cue_file, struct cuesheet *cue) | |||
208 | } | 216 | } |
209 | else if (!strncmp(s, "TITLE", 5) | 217 | else if (!strncmp(s, "TITLE", 5) |
210 | || !strncmp(s, "PERFORMER", 9) | 218 | || !strncmp(s, "PERFORMER", 9) |
211 | || !strncmp(s, "SONGWRITER", 10)) | 219 | || !strncmp(s, "SONGWRITER", 10) |
220 | || !strncmp(s, "FILE", 4)) | ||
212 | { | 221 | { |
213 | char *dest = NULL; | 222 | char *dest = NULL; |
214 | char *string = get_string(s); | 223 | char *string = get_string(s); |
215 | if (!string) | 224 | if (!string) |
216 | break; | 225 | break; |
217 | 226 | ||
227 | size_t count = MAX_NAME*3 + 1; | ||
228 | size_t count8859 = MAX_NAME; | ||
229 | |||
218 | switch (*s) | 230 | switch (*s) |
219 | { | 231 | { |
220 | case 'T': /* TITLE */ | 232 | case 'T': /* TITLE */ |
@@ -231,6 +243,15 @@ bool parse_cuesheet(struct cuesheet_file *cue_file, struct cuesheet *cue) | |||
231 | dest = (cue->track_count <= 0) ? cue->songwriter : | 243 | dest = (cue->track_count <= 0) ? cue->songwriter : |
232 | cue->tracks[cue->track_count-1].songwriter; | 244 | cue->tracks[cue->track_count-1].songwriter; |
233 | break; | 245 | break; |
246 | |||
247 | case 'F': /* FILE */ | ||
248 | if (is_embedded || cue->track_count > 0) | ||
249 | break; | ||
250 | |||
251 | dest = cue->file; | ||
252 | count = MAX_PATH; | ||
253 | count8859 = MAX_PATH/3; | ||
254 | break; | ||
234 | } | 255 | } |
235 | 256 | ||
236 | if (dest) | 257 | if (dest) |
@@ -238,12 +259,12 @@ bool parse_cuesheet(struct cuesheet_file *cue_file, struct cuesheet *cue) | |||
238 | if (char_enc == CHAR_ENC_ISO_8859_1) | 259 | if (char_enc == CHAR_ENC_ISO_8859_1) |
239 | { | 260 | { |
240 | dest = iso_decode(string, dest, -1, | 261 | dest = iso_decode(string, dest, -1, |
241 | MIN(strlen(string), MAX_NAME)); | 262 | MIN(strlen(string), count8859)); |
242 | *dest = '\0'; | 263 | *dest = '\0'; |
243 | } | 264 | } |
244 | else | 265 | else |
245 | { | 266 | { |
246 | strlcpy(dest, string, MAX_NAME*3 + 1); | 267 | strlcpy(dest, string, count); |
247 | } | 268 | } |
248 | } | 269 | } |
249 | } | 270 | } |
@@ -258,6 +279,16 @@ bool parse_cuesheet(struct cuesheet_file *cue_file, struct cuesheet *cue) | |||
258 | } | 279 | } |
259 | close(fd); | 280 | close(fd); |
260 | 281 | ||
282 | /* If just a filename, add path information from cuesheet path */ | ||
283 | if (*cue->file && !strrchr(cue->file, '/')) | ||
284 | { | ||
285 | strcpy(line, cue->file); | ||
286 | strcpy(cue->file, cue->path); | ||
287 | char *slash = strrchr(cue->file, '/'); | ||
288 | if (!slash++) slash = cue->file; | ||
289 | strlcpy(slash, line, MAX_PATH - (slash - cue->file)); | ||
290 | } | ||
291 | |||
261 | /* If some songs don't have performer info, we copy the cuesheet performer */ | 292 | /* If some songs don't have performer info, we copy the cuesheet performer */ |
262 | int i; | 293 | int i; |
263 | for (i = 0; i < cue->track_count; i++) | 294 | for (i = 0; i < cue->track_count; i++) |
@@ -329,7 +360,6 @@ void browse_cuesheet(struct cuesheet *cue) | |||
329 | struct gui_synclist lists; | 360 | struct gui_synclist lists; |
330 | int action; | 361 | int action; |
331 | bool done = false; | 362 | bool done = false; |
332 | int sel; | ||
333 | char title[MAX_PATH]; | 363 | char title[MAX_PATH]; |
334 | struct cuesheet_file cue_file; | 364 | struct cuesheet_file cue_file; |
335 | struct mp3entry *id3 = audio_current_track(); | 365 | struct mp3entry *id3 = audio_current_track(); |
@@ -355,17 +385,41 @@ void browse_cuesheet(struct cuesheet *cue) | |||
355 | switch (action) | 385 | switch (action) |
356 | { | 386 | { |
357 | case ACTION_STD_OK: | 387 | case ACTION_STD_OK: |
388 | { | ||
389 | bool startit = true; | ||
390 | unsigned long elapsed = | ||
391 | cue->tracks[gui_synclist_get_sel_pos(&lists)/2].offset; | ||
392 | |||
358 | id3 = audio_current_track(); | 393 | id3 = audio_current_track(); |
359 | if (id3 && *id3->path && strcmp(id3->path, "No file!")) | 394 | if (id3 && *id3->path) |
360 | { | 395 | { |
361 | look_for_cuesheet_file(id3, &cue_file); | 396 | look_for_cuesheet_file(id3, &cue_file); |
362 | if (id3->cuesheet && !strcmp(cue->path, cue_file.path)) | 397 | if (!strcmp(cue->path, cue_file.path)) |
363 | { | 398 | startit = false; |
364 | sel = gui_synclist_get_sel_pos(&lists); | 399 | } |
365 | seek(cue->tracks[sel/2].offset); | 400 | |
366 | } | 401 | if (!startit) |
402 | startit = !seek(elapsed); | ||
403 | |||
404 | if (!startit || !*cue->file) | ||
405 | break; | ||
406 | |||
407 | /* check that this cue is the same one that would be found by | ||
408 | a search from playback */ | ||
409 | char file[MAX_PATH]; | ||
410 | strlcpy(file, cue->file, MAX_PATH); | ||
411 | |||
412 | if (!strcmp(cue->path, file) || /* if embedded */ | ||
413 | (search_for_cuesheet(file, &cue_file) && | ||
414 | !strcmp(cue->path, cue_file.path))) | ||
415 | { | ||
416 | char *fname = strrsplt(file, '/'); | ||
417 | char *dirname = fname <= file + 1 ? "/" : file; | ||
418 | bookmark_play(dirname, 0, elapsed, 0, current_tick, fname); | ||
367 | } | 419 | } |
368 | break; | 420 | break; |
421 | } /* ACTION_STD_OK */ | ||
422 | |||
369 | case ACTION_STD_CANCEL: | 423 | case ACTION_STD_CANCEL: |
370 | done = true; | 424 | done = true; |
371 | } | 425 | } |