From 02fd314a0b426d6d445e2c9b167681ade6b0c1d2 Mon Sep 17 00:00:00 2001 From: Nick Peskett Date: Fri, 16 Dec 2011 10:09:41 +0000 Subject: FS #12419 : Support for embedded cuesheets. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31321 a1c6a512-1295-4272-9138-f99709370657 --- apps/cuesheet.c | 127 +++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 98 insertions(+), 29 deletions(-) (limited to 'apps/cuesheet.c') diff --git a/apps/cuesheet.c b/apps/cuesheet.c index 935af60898..ab4063a66a 100644 --- a/apps/cuesheet.c +++ b/apps/cuesheet.c @@ -42,21 +42,29 @@ #define CUE_DIR ROCKBOX_DIR "/cue" -bool look_for_cuesheet_file(const char *trackpath, char *found_cue_path) +bool look_for_cuesheet_file(struct mp3entry *track_id3, struct cuesheet_file *cue_file) { /* DEBUGF("look for cue file\n"); */ char cuepath[MAX_PATH]; char *dot, *slash; - slash = strrchr(trackpath, '/'); - if (!slash) + if (track_id3->embed_cuesheet.present) { - found_cue_path = NULL; - return false; + cue_file->pos = track_id3->embed_cuesheet.pos; + cue_file->size = track_id3->embed_cuesheet.size; + cue_file->encoding = track_id3->embed_cuesheet.encoding; + strlcpy(cue_file->path, track_id3->path, MAX_PATH); + return true; } - strlcpy(cuepath, trackpath, MAX_PATH); + cue_file->pos = 0; + cue_file->size = 0; + cue_file->path[0] = '\0'; + slash = strrchr(track_id3->path, '/'); + if (!slash) + return false; + strlcpy(cuepath, track_id3->path, MAX_PATH); dot = strrchr(cuepath, '.'); strcpy(dot, ".cue"); @@ -67,15 +75,10 @@ bool look_for_cuesheet_file(const char *trackpath, char *found_cue_path) char *dot = strrchr(cuepath, '.'); strcpy(dot, ".cue"); if (!file_exists(cuepath)) - { - if (found_cue_path) - found_cue_path = NULL; return false; - } } - if (found_cue_path) - strlcpy(found_cue_path, cuepath, MAX_PATH); + strlcpy(cue_file->path, cuepath, MAX_PATH); return true; } @@ -99,29 +102,81 @@ static char *get_string(const char *line) return start; } -/* parse cuesheet "file" and store the information in "cue" */ -bool parse_cuesheet(char *file, struct cuesheet *cue) +/* parse cuesheet "cue_file" and store the information in "cue" */ +bool parse_cuesheet(struct cuesheet_file *cue_file, struct cuesheet *cue) { char line[MAX_PATH]; char *s; - bool utf8 = false; + unsigned char char_enc = CHAR_ENC_ISO_8859_1; + bool is_embedded = false; + int line_len; + int bytes_left = 0; + int read_bytes = MAX_PATH; + unsigned char utf16_buf[MAX_PATH]; + + int fd = open(cue_file->path, O_RDONLY, 0644); + if(fd < 0) + return false; + if (cue_file->pos > 0) + { + is_embedded = true; + lseek(fd, cue_file->pos, SEEK_SET); + bytes_left = cue_file->size; + char_enc = cue_file->encoding; + } - int fd = open_utf8(file,O_RDONLY); - if (fd < 0) + /* Look for a Unicode BOM */ + unsigned char bom_read = 0; + read(fd, line, 3); + if(!memcmp(line, "\xef\xbb\xbf", 3)) { - /* couln't open the file */ - return false; + char_enc = CHAR_ENC_UTF_8; + bom_read = 3; + } + else if(!memcmp(line, "\xff\xfe", 2)) + { + char_enc = CHAR_ENC_UTF_16_LE; + bom_read = 2; + } + else if(!memcmp(line, "\xfe\xff", 2)) + { + char_enc = CHAR_ENC_UTF_16_BE; + bom_read = 2; + } + if (bom_read < 3 ) + lseek(fd, cue_file->pos + bom_read, SEEK_SET); + if (is_embedded) + { + if (bom_read > 0) + bytes_left -= bom_read; + if (read_bytes > bytes_left) + read_bytes = bytes_left; } - if(lseek(fd, 0, SEEK_CUR) > 0) - utf8 = true; /* Initialization */ memset(cue, 0, sizeof(struct cuesheet)); - strcpy(cue->path, file); + strcpy(cue->path, cue_file->path); cue->curr_track = cue->tracks; - while ( read_line(fd,line,MAX_PATH) && cue->track_count < MAX_TRACKS ) + while ((line_len = read_line(fd, line, read_bytes)) > 0 + && cue->track_count < MAX_TRACKS ) { + if (char_enc == CHAR_ENC_UTF_16_LE) + { + s = utf16LEdecode(line, utf16_buf, line_len); + /* terminate the string at the newline */ + *s = '\0'; + strcpy(line, utf16_buf); + /* chomp the trailing 0 after the newline */ + lseek(fd, 1, SEEK_CUR); + line_len++; + } + else if (char_enc == CHAR_ENC_UTF_16_BE) + { + s = utf16BEdecode(line, utf16_buf, line_len); + *s = '\0'; + strcpy(line, utf16_buf); + } s = skip_whitespace(line); if (!strncmp(s, "TRACK", 5)) @@ -169,9 +224,10 @@ bool parse_cuesheet(char *file, struct cuesheet *cue) if (dest) { - if (!utf8) + if (char_enc == CHAR_ENC_ISO_8859_1) { - dest = iso_decode(string, dest, -1, MIN(strlen(string), MAX_NAME)); + dest = iso_decode(string, dest, -1, + MIN(strlen(string), MAX_NAME)); *dest = '\0'; } else @@ -180,6 +236,14 @@ bool parse_cuesheet(char *file, struct cuesheet *cue) } } } + if (is_embedded) + { + bytes_left -= line_len; + if (bytes_left <= 0) + break; + if (bytes_left < read_bytes) + read_bytes = bytes_left; + } } close(fd); @@ -256,7 +320,7 @@ void browse_cuesheet(struct cuesheet *cue) bool done = false; int sel; char title[MAX_PATH]; - char cuepath[MAX_PATH]; + struct cuesheet_file cue_file; struct mp3entry *id3 = audio_current_track(); snprintf(title, MAX_PATH, "%s: %s", cue->performer, cue->title); @@ -283,8 +347,8 @@ void browse_cuesheet(struct cuesheet *cue) id3 = audio_current_track(); if (id3 && *id3->path && strcmp(id3->path, "No file!")) { - look_for_cuesheet_file(id3->path, cuepath); - if (id3->cuesheet && !strcmp(cue->path, cuepath)) + look_for_cuesheet_file(id3, &cue_file); + if (id3->cuesheet && !strcmp(cue->path, cue_file.path)) { sel = gui_synclist_get_sel_pos(&lists); seek(cue->tracks[sel/2].offset); @@ -300,11 +364,16 @@ void browse_cuesheet(struct cuesheet *cue) bool display_cuesheet_content(char* filename) { size_t bufsize = 0; + struct cuesheet_file cue_file; struct cuesheet *cue = (struct cuesheet *)plugin_get_buffer(&bufsize); if (!cue || bufsize < sizeof(struct cuesheet)) return false; - if (!parse_cuesheet(filename, cue)) + strlcpy(cue_file.path, filename, MAX_PATH); + cue_file.pos = 0; + cue_file.size = 0; + + if (!parse_cuesheet(&cue_file, cue)) return false; browse_cuesheet(cue); -- cgit v1.2.3