summaryrefslogtreecommitdiffstats
path: root/apps/cuesheet.c
diff options
context:
space:
mode:
authorNick Peskett <rockbox@peskett.co.uk>2011-12-16 10:09:41 +0000
committerNick Peskett <rockbox@peskett.co.uk>2011-12-16 10:09:41 +0000
commit02fd314a0b426d6d445e2c9b167681ade6b0c1d2 (patch)
treead6100925dadaae0a69b8ec87b03eb8c1c5b23ab /apps/cuesheet.c
parent014003afac4e6ab5f132df25e0e92106ed21607a (diff)
downloadrockbox-02fd314a0b426d6d445e2c9b167681ade6b0c1d2.tar.gz
rockbox-02fd314a0b426d6d445e2c9b167681ade6b0c1d2.tar.bz2
rockbox-02fd314a0b426d6d445e2c9b167681ade6b0c1d2.zip
FS #12419 : Support for embedded cuesheets.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31321 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/cuesheet.c')
-rw-r--r--apps/cuesheet.c127
1 files changed, 98 insertions, 29 deletions
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);