1 /** 2 * (c) 2003-2006 Nathan Hjelm <hjelmn@users.sourceforge.net> 3 * v1.1 id3.c 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 **/ 19 20 #include <stdlib.h> 21 #include <stdio.h> 22 23 #include <string.h> 24 #include <errno.h> 25 26 #include <sys/ioctl.h> 27 #include <sys/types.h> 28 #include <sys/uio.h> 29 #include <sys/stat.h> 30 31 #include <time.h> 32 #include <unistd.h> 33 #include <fcntl.h> 34 35 #include "rioi.h" 36 #include "genre.h" 37 38 #ifdef HAVE_LIBGEN_H 39 #include <libgen.h> 40 #endif 41 42 #define ID3FLAG_EXTENDED 0x40 43 #define ID3FLAG_FOOTER 0x10 44 45 /* v2.2 v2.3 */ 46 char *ID3_TITLE[2] = {"TT2", "TIT2"}; 47 char *ID3_ARTIST[2] = {"TP1", "TPE1"}; 48 char *ID3_ALBUM[2] = {"TAL", "TALB"}; 49 char *ID3_TRACK[2] = {"TRK", "TRCK"}; 50 char *ID3_YEAR[2] = {"TYE", "TYER"}; 51 char *ID3_GENRE[2] = {"TCO", "TCON"}; 52 char *ID3_ENCODER[2] = {"TEN", "TENC"}; 53 char *ID3_COMMENT[2] = {"COM", "COMM"}; 54 char *ID3_BPM[2] = {"TBP", "TBPM"}; 55 char *ID3_YEARNEW[2] = {"TYE", "TDRC"}; 56 char *ID3_DISC[2] = {"TPA", "TPOS"}; 57 char *ID3_ARTWORK[2] = {"PIC", "APIC"}; 58 59 static int find_id3 (int version, FILE *fh, unsigned char *tag_data, int *tag_datalen, 60 int *id3_len, int *major_version); 61 static void one_pass_parse_id3 (FILE *fh, unsigned char *tag_data, int tag_datalen, int version, 62 int id3v2_majorversion, rio_file_t *mp3_file); 63 static int synchsafe_to_int (unsigned char *buf, int nbytes); 64 65 static int synchsafe_to_int (unsigned char *buf, int nbytes) { 66 int id3v2_len = 0; 67 int error = 0; 68 int i; 69 70 for (i = 0 ; i < nbytes ; i++) { 71 id3v2_len <<= 7; 72 id3v2_len += buf[i] & 0x7f; 73 if (buf[i] & 0xf0) 74 error = 1; 75 } 76 77 if (error) { 78 id3v2_len = 0; 79 for (i = 0 ; i < nbytes ; i++) { 80 id3v2_len <<= 8; 81 id3v2_len += buf[i] & 0xff; 82 } 83 } 84 85 return id3v2_len; 86 } 87 88 int id3v2_size (unsigned char data[14]) { 89 int major_version; 90 unsigned char id3v2_flags; 91 int id3v2_len = 0; 92 int id3v2_extendedlen = 0; 93 int head; 94 95 memcpy (&head, data, 4); 96 head = big32_2_arch32 (head); 97 98 if ((head & 0xffffff00) == 0x49443300) { 99 major_version = head & 0xff; 100 101 id3v2_flags = data[5]; 102 id3v2_len = 10 + synchsafe_to_int (&data[6], 4); 103 104 if (id3v2_flags & ID3FLAG_EXTENDED) { 105 /* Skip extended header */ 106 if (major_version != 3) 107 id3v2_len += synchsafe_to_int (&data[10], 4); 108 else 109 id3v2_len += big32_2_arch32 (((int *)&data[10])[0]); 110 } 111 112 /* total length = 10 (header) + extended header length (flag 0x40) + id3v2len + 10 (footer, if present -- flag 0x10) */ 113 id3v2_len += (id3v2_flags & ID3FLAG_FOOTER) ? 10 : 0; 114 } 115 116 return id3v2_len; 117 } 118 119 /* 120 find_id3 takes in a file descriptor, a pointer to where the tag data is to be put, 121 and a pointer to where the data length is to be put. 122 123 find_id3 returns: 124 0 for no id3 tags 125 1 for id3v1 tag 126 2 for id3v2 tag 127 128 The file descriptor is reset to the start of the file on completion. 129 */ 130 static int find_id3 (int version, FILE *fh, unsigned char *tag_data, int *tag_datalen, 131 int *id3_len, int *major_version) { 132 int head; 133 unsigned char data[10]; 134 135 char id3v2_flags; 136 int id3v2_len; 137 int id3v2_extendedlen; 138 139 fread(&head, 4, 1, fh); 140 141 head = big32_2_arch32(head); 142 143 if (version == 2) { 144 /* version 2 */ 145 if ((head & 0xffffff00) == 0x49443300) { 146 fread(data, 1, 10, fh); 147 148 *major_version = head & 0xff; 149 150 id3v2_flags = data[1]; 151 152 id3v2_len = *id3_len = synchsafe_to_int (&data[2], 4); 153 154 *id3_len += 10; /* total length = id3v2len + 010 + footer (if present) */ 155 *id3_len += (id3v2_flags & 0x10) ? 10 : 0; /* ID3v2 footer */ 156 157 /* the 6th bit of the flag field being set indicates that an 158 extended header is present */ 159 if (id3v2_flags & 0x40) { 160 /* Skip extended header */ 161 id3v2_extendedlen = synchsafe_to_int (&data[6], 4); 162 163 fseek(fh, 0xa + id3v2_extendedlen, SEEK_SET); 164 *tag_datalen = id3v2_len - id3v2_extendedlen; 165 } else { 166 /* Skip standard header */ 167 fseek(fh, 0xa, SEEK_SET); 168 *tag_datalen = id3v2_len; 169 } 170 171 return 2; 172 } 173 } else if (version == 1) { 174 fseek(fh, 0, SEEK_SET); 175 176 /* tag not at beginning? */ 177 if ((head & 0xffffff00) != 0x54414700) { 178 /* maybe end */ 179 fseek(fh, -128, SEEK_END); 180 fread(&head, 1, 4, fh); 181 fseek(fh, -128, SEEK_END); 182 183 head = big32_2_arch32(head); 184 } 185 186 /* version 1 */ 187 if ((head & 0xffffff00) == 0x54414700) { 188 fread(tag_data, 1, 128, fh); 189 190 return 1; 191 } 192 } 193 194 /* no id3 found */ 195 return 0; 196 } 197 198 static char *id3v1_string (unsigned char *unclean) { 199 int i; 200 static char buffer[31]; 201 202 memset (buffer, 0, 31); 203 204 for (i = 0 ; i < 30 && unclean[i] != 0xff ; i++) 205 buffer[i] = unclean[i]; 206 207 for (i = strlen (buffer) - 1 ; i >= 0 && buffer[i] == ' ' ; i--) 208 buffer[i] = '\0'; 209 210 return buffer; 211 } 212 213 /* 214 parse_id3 215 */ 216 static void one_pass_parse_id3 (FILE *fh, unsigned char *tag_data, int tag_datalen, int version, 217 int id3v2_majorversion, rio_file_t *mp3_file) { 218 int i, j; 219 unsigned char *dstp; 220 char *slash; 221 222 if (version == 2) { 223 unsigned char *tag_temp; 224 char genre_temp[4]; 225 char encoding[11]; 226 char identifier[5]; 227 int newv = (id3v2_majorversion > 2) ? 1 : 0; 228 229 memset (identifier, 0, 5); 230 231 for (i = 0 ; i < tag_datalen ; ) { 232 size_t length = 0; 233 234 fread (tag_data, 1, (id3v2_majorversion > 2) ? 10 : 6, fh); 235 236 if (tag_data[0] == 0) 237 return; 238 239 memcpy (identifier, tag_data, newv ? 4 : 3); 240 241 if (id3v2_majorversion > 2) { 242 /* id3v2.3 does not use synchsafe integers in frame headers. */ 243 if (id3v2_majorversion == 3 || strcmp (identifier, "APIC") == 0 || 244 strcmp (identifier, "COMM") == 0 || strcmp (identifier, "COM ") == 0 || 245 strcmp (identifier, "GEOB")) { 246 length = big32_2_arch32(((int *)tag_data)[1]); 247 } else 248 length = synchsafe_to_int (&tag_data[4], 4); 249 250 i += 10 + length; 251 } else { 252 length = (tag_data[3] << 16) | (tag_data[4] << 8) | tag_data[5]; 253 254 i += 6 + length; 255 } 256 257 if (length < 0) { 258 fprintf (stderr, "id3v2 tag data length is < 0... Aborting!\n"); 259 break; 260 } else if (length == 0) 261 continue; 262 263 if (length < 2) { 264 fseek (fh, length, SEEK_CUR); 265 266 continue; 267 } 268 269 if (length > 128) { 270 fseek (fh, length - 128, SEEK_CUR); 271 if (strcmp (identifier, "APIC") != 0 && 272 strcmp (identifier, "PIC") != 0) 273 length = 128; 274 } 275 276 memset (tag_data, 0, 128); 277 fread (tag_data, 1, (length < 128) ? length : 128, fh); 278 279 tag_temp = tag_data; 280 281 /* Get the tag encoding */ 282 switch (*tag_temp) { 283 case 0x00: 284 sprintf (encoding, "ISO-8859-1"); 285 tag_temp++; 286 break; 287 case 0x01: 288 sprintf (encoding, "UTF-16LE"); 289 tag_temp += 3; 290 break; 291 case 0x03: 292 sprintf (encoding, "UTF-16BE"); 293 tag_temp++; 294 break; 295 case 0x04: 296 sprintf (encoding, "UTF-8"); 297 tag_temp++; 298 break; 299 default: 300 sprintf (encoding, "ISO-8859-1"); 301 } 302 303 if (strcmp (identifier, "APIC") != 0 && 304 strcmp (identifier, "PIC") != 0) { 305 for ( ; length && *tag_temp == '\0' ; tag_temp++, length--); 306 for ( ; length && *(tag_temp+length-1) == '\0' ; length--); 307 /* length--; */ 308 } 309 310 if (length <= 0) 311 continue; 312 313 dstp = NULL; 314 315 if (strcmp (identifier, ID3_TITLE[newv]) == 0) { 316 dstp = (unsigned char *)mp3_file->title; 317 length = (length > 63) ? 63 : length; 318 } else if (strcmp (identifier, ID3_ARTIST[newv]) == 0) { 319 dstp = (unsigned char *)mp3_file->artist; 320 length = (length > 63) ? 63 : length; 321 } else if (strcmp (identifier, ID3_TRACK[newv]) == 0) { 322 /* some id3 tags have track/total tracks in the TRK field */ 323 slash = strchr ((char *)tag_temp, '/'); 324 325 if (slash) *slash = 0; 326 327 mp3_file->trackno2 = strtol ((char *)tag_temp, NULL, 10); 328 329 if (slash) *slash = '/'; 330 } else if (strcmp (identifier, ID3_ALBUM[newv]) == 0) { 331 dstp = (unsigned char *)mp3_file->album; 332 length = (length > 63) ? 63 : length; 333 } else if (strcmp (identifier, ID3_YEARNEW[newv]) == 0 || 334 strcmp (identifier, ID3_YEAR[newv]) == 0) { 335 dstp = mp3_file->year2; 336 length = (length > 4) ? 4 : length; 337 } else if (strcmp (identifier, ID3_GENRE[newv]) == 0) { 338 if (tag_temp[0] != '(') { 339 dstp = mp3_file->genre2; 340 length = (length > 22) ? 22 : length; 341 } else { 342 /* 41 is right parenthesis */ 343 for (j = 0 ; (*(tag_temp + 1 + j) != 41) ; j++) { 344 genre_temp[j] = *(tag_temp + 1 + j); 345 } 346 347 genre_temp[j] = 0; 348 349 if (atoi (genre_temp) > 147) 350 continue; 351 352 length = (strlen (genre_table[atoi(genre_temp)]) > 22) ? 22 : strlen (genre_table[atoi(genre_temp)]); 353 memmove (mp3_file->genre2, genre_table[atoi(genre_temp)], length); 354 } 355 } else 356 continue; 357 358 if (dstp) 359 strncpy ((char *)dstp, (char *)tag_temp, length); 360 } 361 } else if (version == 1) { 362 char *tmp; 363 364 if (strlen (mp3_file->title) == 0) { 365 tmp = id3v1_string (&tag_data[3]); 366 strncpy (mp3_file->title, tmp, strlen (tmp)); 367 } 368 369 if (strlen (mp3_file->artist) == 0) { 370 tmp = id3v1_string (&tag_data[33]); 371 strncpy (mp3_file->artist, tmp, strlen (tmp)); 372 } 373 374 if (strlen (mp3_file->album) == 0) { 375 tmp = id3v1_string (&tag_data[63]); 376 strncpy (mp3_file->album, tmp, strlen (tmp)); 377 } 378 379 if (strlen ((char *)mp3_file->genre2) == 0 && tag_data[127] != 0xff) 380 strncpy ((char *)mp3_file->genre2, genre_table[tag_data[127]], strlen (genre_table[tag_data[127]])); 381 382 if (mp3_file->trackno2 == 0) 383 if (tag_data[126] != 0xff) 384 mp3_file->trackno2 = tag_data[126]; 385 } 386 } 387 388 int get_id3_info (char *file_name, rio_file_t *mp3_file) { 389 int tag_datalen = 0, id3_len = 0; 390 unsigned char tag_data[128]; 391 int version; 392 int id3v2_majorversion; 393 int has_v2 = 0; 394 FILE *fh; 395 396 if ((fh = fopen (file_name, "r")) == NULL) 397 return errno; 398 399 /* built-in id3tag reading -- id3v2, id3v1 */ 400 if ((version = find_id3(2, fh, tag_data, &tag_datalen, &id3_len, &id3v2_majorversion)) != 0) { 401 one_pass_parse_id3(fh, tag_data, tag_datalen, version, id3v2_majorversion, mp3_file); 402 has_v2 = 1; 403 } 404 405 /* some mp3's have both tags so check v1 even if v2 is available */ 406 if ((version = find_id3(1, fh, tag_data, &tag_datalen, NULL, &id3v2_majorversion)) != 0) 407 one_pass_parse_id3(fh, tag_data, tag_datalen, version, id3v2_majorversion, mp3_file); 408 409 /* Set the file descriptor at the end of the id3v2 header (if one exists) */ 410 fseek (fh, id3_len, SEEK_SET); 411 412 if (strlen (mp3_file->title) == 0) { 413 char *tfile_name = strdup (file_name); 414 char *tmp = (char *)basename(tfile_name); 415 int i; 416 417 for (i = strlen(tmp) - 1 ; i > 0 ; i--) 418 if (tmp[i] == '.') { 419 tmp[i] = 0; 420 break; 421 } 422 423 memmove (mp3_file->title, tmp, (strlen(tmp) > 63) ? 63 : strlen(tmp)); 424 free (tfile_name); 425 } 426 427 fclose (fh); 428 429 if (has_v2) 430 return 2; 431 else 432 return 1; 433 } 434 435