summaryrefslogtreecommitdiff
path: root/apps/cuesheet.c
diff options
context:
space:
mode:
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 @@
42 42
43#define CUE_DIR ROCKBOX_DIR "/cue" 43#define CUE_DIR ROCKBOX_DIR "/cue"
44 44
45bool look_for_cuesheet_file(const char *trackpath, char *found_cue_path) 45bool look_for_cuesheet_file(struct mp3entry *track_id3, struct cuesheet_file *cue_file)
46{ 46{
47 /* DEBUGF("look for cue file\n"); */ 47 /* DEBUGF("look for cue file\n"); */
48 48
49 char cuepath[MAX_PATH]; 49 char cuepath[MAX_PATH];
50 char *dot, *slash; 50 char *dot, *slash;
51 51
52 slash = strrchr(trackpath, '/'); 52 if (track_id3->embed_cuesheet.present)
53 if (!slash)
54 { 53 {
55 found_cue_path = NULL; 54 cue_file->pos = track_id3->embed_cuesheet.pos;
56 return false; 55 cue_file->size = track_id3->embed_cuesheet.size;
56 cue_file->encoding = track_id3->embed_cuesheet.encoding;
57 strlcpy(cue_file->path, track_id3->path, MAX_PATH);
58 return true;
57 } 59 }
58 60
59 strlcpy(cuepath, trackpath, MAX_PATH); 61 cue_file->pos = 0;
62 cue_file->size = 0;
63 cue_file->path[0] = '\0';
64 slash = strrchr(track_id3->path, '/');
65 if (!slash)
66 return false;
67 strlcpy(cuepath, track_id3->path, MAX_PATH);
60 dot = strrchr(cuepath, '.'); 68 dot = strrchr(cuepath, '.');
61 strcpy(dot, ".cue"); 69 strcpy(dot, ".cue");
62 70
@@ -67,15 +75,10 @@ bool look_for_cuesheet_file(const char *trackpath, char *found_cue_path)
67 char *dot = strrchr(cuepath, '.'); 75 char *dot = strrchr(cuepath, '.');
68 strcpy(dot, ".cue"); 76 strcpy(dot, ".cue");
69 if (!file_exists(cuepath)) 77 if (!file_exists(cuepath))
70 {
71 if (found_cue_path)
72 found_cue_path = NULL;
73 return false; 78 return false;
74 }
75 } 79 }
76 80
77 if (found_cue_path) 81 strlcpy(cue_file->path, cuepath, MAX_PATH);
78 strlcpy(found_cue_path, cuepath, MAX_PATH);
79 return true; 82 return true;
80} 83}
81 84
@@ -99,29 +102,81 @@ static char *get_string(const char *line)
99 return start; 102 return start;
100} 103}
101 104
102/* parse cuesheet "file" and store the information in "cue" */ 105/* parse cuesheet "cue_file" and store the information in "cue" */
103bool parse_cuesheet(char *file, struct cuesheet *cue) 106bool parse_cuesheet(struct cuesheet_file *cue_file, struct cuesheet *cue)
104{ 107{
105 char line[MAX_PATH]; 108 char line[MAX_PATH];
106 char *s; 109 char *s;
107 bool utf8 = false; 110 unsigned char char_enc = CHAR_ENC_ISO_8859_1;
111 bool is_embedded = false;
112 int line_len;
113 int bytes_left = 0;
114 int read_bytes = MAX_PATH;
115 unsigned char utf16_buf[MAX_PATH];
116
117 int fd = open(cue_file->path, O_RDONLY, 0644);
118 if(fd < 0)
119 return false;
120 if (cue_file->pos > 0)
121 {
122 is_embedded = true;
123 lseek(fd, cue_file->pos, SEEK_SET);
124 bytes_left = cue_file->size;
125 char_enc = cue_file->encoding;
126 }
108 127
109 int fd = open_utf8(file,O_RDONLY); 128 /* Look for a Unicode BOM */
110 if (fd < 0) 129 unsigned char bom_read = 0;
130 read(fd, line, 3);
131 if(!memcmp(line, "\xef\xbb\xbf", 3))
111 { 132 {
112 /* couln't open the file */ 133 char_enc = CHAR_ENC_UTF_8;
113 return false; 134 bom_read = 3;
135 }
136 else if(!memcmp(line, "\xff\xfe", 2))
137 {
138 char_enc = CHAR_ENC_UTF_16_LE;
139 bom_read = 2;
140 }
141 else if(!memcmp(line, "\xfe\xff", 2))
142 {
143 char_enc = CHAR_ENC_UTF_16_BE;
144 bom_read = 2;
145 }
146 if (bom_read < 3 )
147 lseek(fd, cue_file->pos + bom_read, SEEK_SET);
148 if (is_embedded)
149 {
150 if (bom_read > 0)
151 bytes_left -= bom_read;
152 if (read_bytes > bytes_left)
153 read_bytes = bytes_left;
114 } 154 }
115 if(lseek(fd, 0, SEEK_CUR) > 0)
116 utf8 = true;
117 155
118 /* Initialization */ 156 /* Initialization */
119 memset(cue, 0, sizeof(struct cuesheet)); 157 memset(cue, 0, sizeof(struct cuesheet));
120 strcpy(cue->path, file); 158 strcpy(cue->path, cue_file->path);
121 cue->curr_track = cue->tracks; 159 cue->curr_track = cue->tracks;
122 160
123 while ( read_line(fd,line,MAX_PATH) && cue->track_count < MAX_TRACKS ) 161 while ((line_len = read_line(fd, line, read_bytes)) > 0
162 && cue->track_count < MAX_TRACKS )
124 { 163 {
164 if (char_enc == CHAR_ENC_UTF_16_LE)
165 {
166 s = utf16LEdecode(line, utf16_buf, line_len);
167 /* terminate the string at the newline */
168 *s = '\0';
169 strcpy(line, utf16_buf);
170 /* chomp the trailing 0 after the newline */
171 lseek(fd, 1, SEEK_CUR);
172 line_len++;
173 }
174 else if (char_enc == CHAR_ENC_UTF_16_BE)
175 {
176 s = utf16BEdecode(line, utf16_buf, line_len);
177 *s = '\0';
178 strcpy(line, utf16_buf);
179 }
125 s = skip_whitespace(line); 180 s = skip_whitespace(line);
126 181
127 if (!strncmp(s, "TRACK", 5)) 182 if (!strncmp(s, "TRACK", 5))
@@ -169,9 +224,10 @@ bool parse_cuesheet(char *file, struct cuesheet *cue)
169 224
170 if (dest) 225 if (dest)
171 { 226 {
172 if (!utf8) 227 if (char_enc == CHAR_ENC_ISO_8859_1)
173 { 228 {
174 dest = iso_decode(string, dest, -1, MIN(strlen(string), MAX_NAME)); 229 dest = iso_decode(string, dest, -1,
230 MIN(strlen(string), MAX_NAME));
175 *dest = '\0'; 231 *dest = '\0';
176 } 232 }
177 else 233 else
@@ -180,6 +236,14 @@ bool parse_cuesheet(char *file, struct cuesheet *cue)
180 } 236 }
181 } 237 }
182 } 238 }
239 if (is_embedded)
240 {
241 bytes_left -= line_len;
242 if (bytes_left <= 0)
243 break;
244 if (bytes_left < read_bytes)
245 read_bytes = bytes_left;
246 }
183 } 247 }
184 close(fd); 248 close(fd);
185 249
@@ -256,7 +320,7 @@ void browse_cuesheet(struct cuesheet *cue)
256 bool done = false; 320 bool done = false;
257 int sel; 321 int sel;
258 char title[MAX_PATH]; 322 char title[MAX_PATH];
259 char cuepath[MAX_PATH]; 323 struct cuesheet_file cue_file;
260 struct mp3entry *id3 = audio_current_track(); 324 struct mp3entry *id3 = audio_current_track();
261 325
262 snprintf(title, MAX_PATH, "%s: %s", cue->performer, cue->title); 326 snprintf(title, MAX_PATH, "%s: %s", cue->performer, cue->title);
@@ -283,8 +347,8 @@ void browse_cuesheet(struct cuesheet *cue)
283 id3 = audio_current_track(); 347 id3 = audio_current_track();
284 if (id3 && *id3->path && strcmp(id3->path, "No file!")) 348 if (id3 && *id3->path && strcmp(id3->path, "No file!"))
285 { 349 {
286 look_for_cuesheet_file(id3->path, cuepath); 350 look_for_cuesheet_file(id3, &cue_file);
287 if (id3->cuesheet && !strcmp(cue->path, cuepath)) 351 if (id3->cuesheet && !strcmp(cue->path, cue_file.path))
288 { 352 {
289 sel = gui_synclist_get_sel_pos(&lists); 353 sel = gui_synclist_get_sel_pos(&lists);
290 seek(cue->tracks[sel/2].offset); 354 seek(cue->tracks[sel/2].offset);
@@ -300,11 +364,16 @@ void browse_cuesheet(struct cuesheet *cue)
300bool display_cuesheet_content(char* filename) 364bool display_cuesheet_content(char* filename)
301{ 365{
302 size_t bufsize = 0; 366 size_t bufsize = 0;
367 struct cuesheet_file cue_file;
303 struct cuesheet *cue = (struct cuesheet *)plugin_get_buffer(&bufsize); 368 struct cuesheet *cue = (struct cuesheet *)plugin_get_buffer(&bufsize);
304 if (!cue || bufsize < sizeof(struct cuesheet)) 369 if (!cue || bufsize < sizeof(struct cuesheet))
305 return false; 370 return false;
306 371
307 if (!parse_cuesheet(filename, cue)) 372 strlcpy(cue_file.path, filename, MAX_PATH);
373 cue_file.pos = 0;
374 cue_file.size = 0;
375
376 if (!parse_cuesheet(&cue_file, cue))
308 return false; 377 return false;
309 378
310 browse_cuesheet(cue); 379 browse_cuesheet(cue);