annotate src/libid3tag-0.15.1b/compat.c @ 1:05aa0afa9217

Bring in flac, ogg, vorbis
author Chris Cannam
date Tue, 19 Mar 2013 17:37:49 +0000
parents c7265573341e
children
rev   line source
Chris@0 1 /* C code produced by gperf version 3.0.1 */
Chris@0 2 /* Command-line: gperf -tCcTonD -K id -N id3_compat_lookup -s -3 -k '*' compat.gperf */
Chris@0 3
Chris@0 4 #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
Chris@0 5 && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
Chris@0 6 && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
Chris@0 7 && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
Chris@0 8 && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
Chris@0 9 && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
Chris@0 10 && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
Chris@0 11 && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
Chris@0 12 && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
Chris@0 13 && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
Chris@0 14 && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
Chris@0 15 && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
Chris@0 16 && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
Chris@0 17 && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
Chris@0 18 && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
Chris@0 19 && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
Chris@0 20 && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
Chris@0 21 && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
Chris@0 22 && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
Chris@0 23 && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
Chris@0 24 && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
Chris@0 25 && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
Chris@0 26 && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
Chris@0 27 /* The character set is not based on ISO-646. */
Chris@0 28 error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
Chris@0 29 #endif
Chris@0 30
Chris@0 31 #line 1 "compat.gperf"
Chris@0 32
Chris@0 33 /*
Chris@0 34 * libid3tag - ID3 tag manipulation library
Chris@0 35 * Copyright (C) 2000-2004 Underbit Technologies, Inc.
Chris@0 36 *
Chris@0 37 * This program is free software; you can redistribute it and/or modify
Chris@0 38 * it under the terms of the GNU General Public License as published by
Chris@0 39 * the Free Software Foundation; either version 2 of the License, or
Chris@0 40 * (at your option) any later version.
Chris@0 41 *
Chris@0 42 * This program is distributed in the hope that it will be useful,
Chris@0 43 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Chris@0 44 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Chris@0 45 * GNU General Public License for more details.
Chris@0 46 *
Chris@0 47 * You should have received a copy of the GNU General Public License
Chris@0 48 * along with this program; if not, write to the Free Software
Chris@0 49 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Chris@0 50 *
Chris@0 51 * Id: compat.gperf,v 1.11 2004/01/23 09:41:32 rob Exp
Chris@0 52 */
Chris@0 53
Chris@0 54 # ifdef HAVE_CONFIG_H
Chris@0 55 # include "config.h"
Chris@0 56 # endif
Chris@0 57
Chris@0 58 # include "global.h"
Chris@0 59
Chris@0 60 # include <stdlib.h>
Chris@0 61 # include <string.h>
Chris@0 62
Chris@0 63 # ifdef HAVE_ASSERT_H
Chris@0 64 # include <assert.h>
Chris@0 65 # endif
Chris@0 66
Chris@0 67 # include "id3tag.h"
Chris@0 68 # include "compat.h"
Chris@0 69 # include "frame.h"
Chris@0 70 # include "field.h"
Chris@0 71 # include "parse.h"
Chris@0 72 # include "ucs4.h"
Chris@0 73
Chris@0 74 # define EQ(id) #id, 0
Chris@0 75 # define OBSOLETE 0, 0
Chris@0 76 # define TX(id) #id, translate_##id
Chris@0 77
Chris@0 78 static id3_compat_func_t translate_TCON;
Chris@0 79
Chris@0 80 #define TOTAL_KEYWORDS 73
Chris@0 81 #define MIN_WORD_LENGTH 3
Chris@0 82 #define MAX_WORD_LENGTH 4
Chris@0 83 #define MIN_HASH_VALUE 6
Chris@0 84 #define MAX_HASH_VALUE 127
Chris@0 85 /* maximum key range = 122, duplicates = 0 */
Chris@0 86
Chris@0 87 #ifdef __GNUC__
Chris@0 88 __inline
Chris@0 89 #else
Chris@0 90 #ifdef __cplusplus
Chris@0 91 inline
Chris@0 92 #endif
Chris@0 93 #endif
Chris@0 94 static unsigned int
Chris@0 95 hash (str, len)
Chris@0 96 register const char *str;
Chris@0 97 register unsigned int len;
Chris@0 98 {
Chris@0 99 static const unsigned char asso_values[] =
Chris@0 100 {
Chris@0 101 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 102 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 103 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 104 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 105 128, 128, 128, 128, 128, 128, 128, 128, 128, 64,
Chris@0 106 58, 20, 15, 128, 128, 128, 128, 128, 128, 128,
Chris@0 107 128, 128, 128, 128, 128, 10, 18, 3, 6, 1,
Chris@0 108 47, 0, 128, 42, 62, 30, 31, 0, 19, 52,
Chris@0 109 10, 24, 8, 30, 5, 3, 30, 8, 25, 47,
Chris@0 110 3, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 111 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 112 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 113 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 114 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 115 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 116 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 117 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 118 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 119 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 120 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 121 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 122 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 123 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 124 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 125 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 126 128, 128, 128, 128, 128, 128, 128
Chris@0 127 };
Chris@0 128 register int hval = 0;
Chris@0 129
Chris@0 130 switch (len)
Chris@0 131 {
Chris@0 132 default:
Chris@0 133 hval += asso_values[(unsigned char)str[3]];
Chris@0 134 /*FALLTHROUGH*/
Chris@0 135 case 3:
Chris@0 136 hval += asso_values[(unsigned char)str[2]];
Chris@0 137 /*FALLTHROUGH*/
Chris@0 138 case 2:
Chris@0 139 hval += asso_values[(unsigned char)str[1]+1];
Chris@0 140 /*FALLTHROUGH*/
Chris@0 141 case 1:
Chris@0 142 hval += asso_values[(unsigned char)str[0]];
Chris@0 143 break;
Chris@0 144 }
Chris@0 145 return hval;
Chris@0 146 }
Chris@0 147
Chris@0 148 #ifdef __GNUC__
Chris@0 149 __inline
Chris@0 150 #endif
Chris@0 151 const struct id3_compat *
Chris@0 152 id3_compat_lookup (str, len)
Chris@0 153 register const char *str;
Chris@0 154 register unsigned int len;
Chris@0 155 {
Chris@0 156 static const struct id3_compat wordlist[] =
Chris@0 157 {
Chris@0 158 #line 97 "compat.gperf"
Chris@0 159 {"TLE", EQ(TLEN) /* Length */},
Chris@0 160 #line 68 "compat.gperf"
Chris@0 161 {"ETC", EQ(ETCO) /* Event timing codes */},
Chris@0 162 #line 126 "compat.gperf"
Chris@0 163 {"ULT", EQ(USLT) /* Unsynchronised lyric/text transcription */},
Chris@0 164 #line 123 "compat.gperf"
Chris@0 165 {"TYE", OBSOLETE /* Year [obsolete] */},
Chris@0 166 #line 92 "compat.gperf"
Chris@0 167 {"TFT", EQ(TFLT) /* File type */},
Chris@0 168 #line 84 "compat.gperf"
Chris@0 169 {"TCM", EQ(TCOM) /* Composer */},
Chris@0 170 #line 66 "compat.gperf"
Chris@0 171 {"EQU", OBSOLETE /* Equalization [obsolete] */},
Chris@0 172 #line 63 "compat.gperf"
Chris@0 173 {"COM", EQ(COMM) /* Comments */},
Chris@0 174 #line 130 "compat.gperf"
Chris@0 175 {"WCM", EQ(WCOM) /* Commercial information */},
Chris@0 176 #line 96 "compat.gperf"
Chris@0 177 {"TLA", EQ(TLAN) /* Language(s) */},
Chris@0 178 #line 88 "compat.gperf"
Chris@0 179 {"TDA", OBSOLETE /* Date [obsolete] */},
Chris@0 180 #line 124 "compat.gperf"
Chris@0 181 {"TYER", OBSOLETE /* Year [obsolete] */},
Chris@0 182 #line 83 "compat.gperf"
Chris@0 183 {"TBP", EQ(TBPM) /* BPM (beats per minute) */},
Chris@0 184 #line 87 "compat.gperf"
Chris@0 185 {"TCR", EQ(TCOP) /* Copyright message */},
Chris@0 186 #line 104 "compat.gperf"
Chris@0 187 {"TOT", EQ(TOAL) /* Original album/movie/show title */},
Chris@0 188 #line 89 "compat.gperf"
Chris@0 189 {"TDAT", OBSOLETE /* Date [obsolete] */},
Chris@0 190 #line 67 "compat.gperf"
Chris@0 191 {"EQUA", OBSOLETE /* Equalization [obsolete] */},
Chris@0 192 #line 102 "compat.gperf"
Chris@0 193 {"TOR", EQ(TDOR) /* Original release year [obsolete] */},
Chris@0 194 #line 131 "compat.gperf"
Chris@0 195 {"WCP", EQ(WCOP) /* Copyright/legal information */},
Chris@0 196 #line 99 "compat.gperf"
Chris@0 197 {"TOA", EQ(TOPE) /* Original artist(s)/performer(s) */},
Chris@0 198 #line 78 "compat.gperf"
Chris@0 199 {"RVA", OBSOLETE /* Relative volume adjustment [obsolete] */},
Chris@0 200 #line 120 "compat.gperf"
Chris@0 201 {"TT3", EQ(TIT3) /* Subtitle/description refinement */},
Chris@0 202 #line 98 "compat.gperf"
Chris@0 203 {"TMT", EQ(TMED) /* Media type */},
Chris@0 204 #line 76 "compat.gperf"
Chris@0 205 {"POP", EQ(POPM) /* Popularimeter */},
Chris@0 206 #line 74 "compat.gperf"
Chris@0 207 {"MLL", EQ(MLLT) /* MPEG location lookup table */},
Chris@0 208 #line 79 "compat.gperf"
Chris@0 209 {"RVAD", OBSOLETE /* Relative volume adjustment [obsolete] */},
Chris@0 210 #line 65 "compat.gperf"
Chris@0 211 {"CRM", OBSOLETE /* Encrypted meta frame [obsolete] */},
Chris@0 212 #line 128 "compat.gperf"
Chris@0 213 {"WAR", EQ(WOAR) /* Official artist/performer webpage */},
Chris@0 214 #line 80 "compat.gperf"
Chris@0 215 {"SLT", EQ(SYLT) /* Synchronised lyric/text */},
Chris@0 216 #line 81 "compat.gperf"
Chris@0 217 {"STC", EQ(SYTC) /* Synchronised tempo codes */},
Chris@0 218 #line 95 "compat.gperf"
Chris@0 219 {"TKE", EQ(TKEY) /* Initial key */},
Chris@0 220 #line 111 "compat.gperf"
Chris@0 221 {"TRC", EQ(TSRC) /* ISRC (international standard recording code) */},
Chris@0 222 #line 109 "compat.gperf"
Chris@0 223 {"TPA", EQ(TPOS) /* Part of a set */},
Chris@0 224 #line 117 "compat.gperf"
Chris@0 225 {"TSS", EQ(TSSE) /* Software/hardware and settings used for encoding */},
Chris@0 226 #line 112 "compat.gperf"
Chris@0 227 {"TRD", OBSOLETE /* Recording dates [obsolete] */},
Chris@0 228 #line 64 "compat.gperf"
Chris@0 229 {"CRA", EQ(AENC) /* Audio encryption */},
Chris@0 230 #line 108 "compat.gperf"
Chris@0 231 {"TP4", EQ(TPE4) /* Interpreted, remixed, or otherwise modified by */},
Chris@0 232 #line 125 "compat.gperf"
Chris@0 233 {"UFI", EQ(UFID) /* Unique file identifier */},
Chris@0 234 #line 101 "compat.gperf"
Chris@0 235 {"TOL", EQ(TOLY) /* Original lyricist(s)/text writer(s) */},
Chris@0 236 #line 110 "compat.gperf"
Chris@0 237 {"TPB", EQ(TPUB) /* Publisher */},
Chris@0 238 #line 73 "compat.gperf"
Chris@0 239 {"MCI", EQ(MCDI) /* Music CD identifier */},
Chris@0 240 #line 107 "compat.gperf"
Chris@0 241 {"TP3", EQ(TPE3) /* Conductor/performer refinement */},
Chris@0 242 #line 132 "compat.gperf"
Chris@0 243 {"WPB", EQ(WPUB) /* Publishers official webpage */},
Chris@0 244 #line 113 "compat.gperf"
Chris@0 245 {"TRDA", OBSOLETE /* Recording dates [obsolete] */},
Chris@0 246 #line 115 "compat.gperf"
Chris@0 247 {"TSI", OBSOLETE /* Size [obsolete] */},
Chris@0 248 #line 90 "compat.gperf"
Chris@0 249 {"TDY", EQ(TDLY) /* Playlist delay */},
Chris@0 250 #line 82 "compat.gperf"
Chris@0 251 {"TAL", EQ(TALB) /* Album/movie/show title */},
Chris@0 252 #line 116 "compat.gperf"
Chris@0 253 {"TSIZ", OBSOLETE /* Size [obsolete] */},
Chris@0 254 #line 129 "compat.gperf"
Chris@0 255 {"WAS", EQ(WOAS) /* Official audio source webpage */},
Chris@0 256 #line 121 "compat.gperf"
Chris@0 257 {"TXT", EQ(TEXT) /* Lyricist/text writer */},
Chris@0 258 #line 62 "compat.gperf"
Chris@0 259 {"CNT", EQ(PCNT) /* Play counter */},
Chris@0 260 #line 100 "compat.gperf"
Chris@0 261 {"TOF", EQ(TOFN) /* Original filename */},
Chris@0 262 #line 85 "compat.gperf"
Chris@0 263 {"TCO", TX(TCON) /* Content type */},
Chris@0 264 #line 114 "compat.gperf"
Chris@0 265 {"TRK", EQ(TRCK) /* Track number/position in set */},
Chris@0 266 #line 119 "compat.gperf"
Chris@0 267 {"TT2", EQ(TIT2) /* Title/songname/content description */},
Chris@0 268 #line 93 "compat.gperf"
Chris@0 269 {"TIM", OBSOLETE /* Time [obsolete] */},
Chris@0 270 #line 94 "compat.gperf"
Chris@0 271 {"TIME", OBSOLETE /* Time [obsolete] */},
Chris@0 272 #line 103 "compat.gperf"
Chris@0 273 {"TORY", EQ(TDOR) /* Original release year [obsolete] */},
Chris@0 274 #line 91 "compat.gperf"
Chris@0 275 {"TEN", EQ(TENC) /* Encoded by */},
Chris@0 276 #line 118 "compat.gperf"
Chris@0 277 {"TT1", EQ(TIT1) /* Content group description */},
Chris@0 278 #line 127 "compat.gperf"
Chris@0 279 {"WAF", EQ(WOAF) /* Official audio file webpage */},
Chris@0 280 #line 75 "compat.gperf"
Chris@0 281 {"PIC", EQ(APIC) /* Attached picture */},
Chris@0 282 #line 122 "compat.gperf"
Chris@0 283 {"TXX", EQ(TXXX) /* User defined text information frame */},
Chris@0 284 #line 133 "compat.gperf"
Chris@0 285 {"WXX", EQ(WXXX) /* User defined URL link frame */},
Chris@0 286 #line 86 "compat.gperf"
Chris@0 287 {"TCON", TX(TCON) /* Content type */},
Chris@0 288 #line 77 "compat.gperf"
Chris@0 289 {"REV", EQ(RVRB) /* Reverb */},
Chris@0 290 #line 106 "compat.gperf"
Chris@0 291 {"TP2", EQ(TPE2) /* Band/orchestra/accompaniment */},
Chris@0 292 #line 105 "compat.gperf"
Chris@0 293 {"TP1", EQ(TPE1) /* Lead performer(s)/soloist(s) */},
Chris@0 294 #line 61 "compat.gperf"
Chris@0 295 {"BUF", EQ(RBUF) /* Recommended buffer size */},
Chris@0 296 #line 70 "compat.gperf"
Chris@0 297 {"IPL", EQ(TIPL) /* Involved people list */},
Chris@0 298 #line 69 "compat.gperf"
Chris@0 299 {"GEO", EQ(GEOB) /* General encapsulated object */},
Chris@0 300 #line 72 "compat.gperf"
Chris@0 301 {"LNK", EQ(LINK) /* Linked information */},
Chris@0 302 #line 71 "compat.gperf"
Chris@0 303 {"IPLS", EQ(TIPL) /* Involved people list */}
Chris@0 304 };
Chris@0 305
Chris@0 306 static const short lookup[] =
Chris@0 307 {
Chris@0 308 -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7,
Chris@0 309 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, -1,
Chris@0 310 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
Chris@0 311 -1, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
Chris@0 312 48, 49, -1, -1, 50, -1, 51, 52, -1, 53, 54, 55, 56, -1,
Chris@0 313 57, 58, 59, 60, -1, 61, -1, 62, -1, -1, 63, -1, 64, -1,
Chris@0 314 -1, 65, -1, 66, -1, -1, -1, -1, -1, 67, -1, 68, -1, 69,
Chris@0 315 -1, 70, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
Chris@0 316 -1, 71, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
Chris@0 317 -1, 72
Chris@0 318 };
Chris@0 319
Chris@0 320 if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
Chris@0 321 {
Chris@0 322 register int key = hash (str, len);
Chris@0 323
Chris@0 324 if (key <= MAX_HASH_VALUE && key >= 0)
Chris@0 325 {
Chris@0 326 register int index = lookup[key];
Chris@0 327
Chris@0 328 if (index >= 0)
Chris@0 329 {
Chris@0 330 register const char *s = wordlist[index].id;
Chris@0 331
Chris@0 332 if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0')
Chris@0 333 return &wordlist[index];
Chris@0 334 }
Chris@0 335 }
Chris@0 336 }
Chris@0 337 return 0;
Chris@0 338 }
Chris@0 339 #line 134 "compat.gperf"
Chris@0 340
Chris@0 341
Chris@0 342 static
Chris@0 343 int translate_TCON(struct id3_frame *frame, char const *oldid,
Chris@0 344 id3_byte_t const *data, id3_length_t length)
Chris@0 345 {
Chris@0 346 id3_byte_t const *end;
Chris@0 347 enum id3_field_textencoding encoding;
Chris@0 348 id3_ucs4_t *string = 0, *ptr, *endptr;
Chris@0 349 int result = 0;
Chris@0 350
Chris@0 351 /* translate old TCON syntax into multiple strings */
Chris@0 352
Chris@0 353 assert(frame->nfields == 2);
Chris@0 354
Chris@0 355 encoding = ID3_FIELD_TEXTENCODING_ISO_8859_1;
Chris@0 356
Chris@0 357 end = data + length;
Chris@0 358
Chris@0 359 if (id3_field_parse(&frame->fields[0], &data, end - data, &encoding) == -1)
Chris@0 360 goto fail;
Chris@0 361
Chris@0 362 string = id3_parse_string(&data, end - data, encoding, 0);
Chris@0 363 if (string == 0)
Chris@0 364 goto fail;
Chris@0 365
Chris@0 366 ptr = string;
Chris@0 367 while (*ptr == '(') {
Chris@0 368 if (*++ptr == '(')
Chris@0 369 break;
Chris@0 370
Chris@0 371 endptr = ptr;
Chris@0 372 while (*endptr && *endptr != ')')
Chris@0 373 ++endptr;
Chris@0 374
Chris@0 375 if (*endptr)
Chris@0 376 *endptr++ = 0;
Chris@0 377
Chris@0 378 if (id3_field_addstring(&frame->fields[1], ptr) == -1)
Chris@0 379 goto fail;
Chris@0 380
Chris@0 381 ptr = endptr;
Chris@0 382 }
Chris@0 383
Chris@0 384 if (*ptr && id3_field_addstring(&frame->fields[1], ptr) == -1)
Chris@0 385 goto fail;
Chris@0 386
Chris@0 387 if (0) {
Chris@0 388 fail:
Chris@0 389 result = -1;
Chris@0 390 }
Chris@0 391
Chris@0 392 if (string)
Chris@0 393 free(string);
Chris@0 394
Chris@0 395 return result;
Chris@0 396 }
Chris@0 397
Chris@0 398 /*
Chris@0 399 * NAME: compat->fixup()
Chris@0 400 * DESCRIPTION: finish compatibility translations
Chris@0 401 */
Chris@0 402 int id3_compat_fixup(struct id3_tag *tag)
Chris@0 403 {
Chris@0 404 struct id3_frame *frame;
Chris@0 405 unsigned int index;
Chris@0 406 id3_ucs4_t timestamp[17] = { 0 };
Chris@0 407 int result = 0;
Chris@0 408
Chris@0 409 /* create a TDRC frame from obsolete TYER/TDAT/TIME frames */
Chris@0 410
Chris@0 411 /*
Chris@0 412 * TYE/TYER: YYYY
Chris@0 413 * TDA/TDAT: DDMM
Chris@0 414 * TIM/TIME: HHMM
Chris@0 415 *
Chris@0 416 * TDRC: yyyy-MM-ddTHH:mm
Chris@0 417 */
Chris@0 418
Chris@0 419 index = 0;
Chris@0 420 while ((frame = id3_tag_findframe(tag, ID3_FRAME_OBSOLETE, index++))) {
Chris@0 421 char const *id;
Chris@0 422 id3_byte_t const *data, *end;
Chris@0 423 id3_length_t length;
Chris@0 424 enum id3_field_textencoding encoding;
Chris@0 425 id3_ucs4_t *string;
Chris@0 426
Chris@0 427 id = id3_field_getframeid(&frame->fields[0]);
Chris@0 428 assert(id);
Chris@0 429
Chris@0 430 if (strcmp(id, "TYER") != 0 && strcmp(id, "YTYE") != 0 &&
Chris@0 431 strcmp(id, "TDAT") != 0 && strcmp(id, "YTDA") != 0 &&
Chris@0 432 strcmp(id, "TIME") != 0 && strcmp(id, "YTIM") != 0)
Chris@0 433 continue;
Chris@0 434
Chris@0 435 data = id3_field_getbinarydata(&frame->fields[1], &length);
Chris@0 436 assert(data);
Chris@0 437
Chris@0 438 if (length < 1)
Chris@0 439 continue;
Chris@0 440
Chris@0 441 end = data + length;
Chris@0 442
Chris@0 443 encoding = id3_parse_uint(&data, 1);
Chris@0 444 string = id3_parse_string(&data, end - data, encoding, 0);
Chris@0 445
Chris@0 446 if (id3_ucs4_length(string) < 4) {
Chris@0 447 free(string);
Chris@0 448 continue;
Chris@0 449 }
Chris@0 450
Chris@0 451 if (strcmp(id, "TYER") == 0 ||
Chris@0 452 strcmp(id, "YTYE") == 0) {
Chris@0 453 timestamp[0] = string[0];
Chris@0 454 timestamp[1] = string[1];
Chris@0 455 timestamp[2] = string[2];
Chris@0 456 timestamp[3] = string[3];
Chris@0 457 }
Chris@0 458 else if (strcmp(id, "TDAT") == 0 ||
Chris@0 459 strcmp(id, "YTDA") == 0) {
Chris@0 460 timestamp[4] = '-';
Chris@0 461 timestamp[5] = string[2];
Chris@0 462 timestamp[6] = string[3];
Chris@0 463 timestamp[7] = '-';
Chris@0 464 timestamp[8] = string[0];
Chris@0 465 timestamp[9] = string[1];
Chris@0 466 }
Chris@0 467 else { /* TIME or YTIM */
Chris@0 468 timestamp[10] = 'T';
Chris@0 469 timestamp[11] = string[0];
Chris@0 470 timestamp[12] = string[1];
Chris@0 471 timestamp[13] = ':';
Chris@0 472 timestamp[14] = string[2];
Chris@0 473 timestamp[15] = string[3];
Chris@0 474 }
Chris@0 475
Chris@0 476 free(string);
Chris@0 477 }
Chris@0 478
Chris@0 479 if (timestamp[0]) {
Chris@0 480 id3_ucs4_t *strings;
Chris@0 481
Chris@0 482 frame = id3_frame_new("TDRC");
Chris@0 483 if (frame == 0)
Chris@0 484 goto fail;
Chris@0 485
Chris@0 486 strings = timestamp;
Chris@0 487
Chris@0 488 if (id3_field_settextencoding(&frame->fields[0],
Chris@0 489 ID3_FIELD_TEXTENCODING_ISO_8859_1) == -1 ||
Chris@0 490 id3_field_setstrings(&frame->fields[1], 1, &strings) == -1 ||
Chris@0 491 id3_tag_attachframe(tag, frame) == -1) {
Chris@0 492 id3_frame_delete(frame);
Chris@0 493 goto fail;
Chris@0 494 }
Chris@0 495 }
Chris@0 496
Chris@0 497 if (0) {
Chris@0 498 fail:
Chris@0 499 result = -1;
Chris@0 500 }
Chris@0 501
Chris@0 502 return result;
Chris@0 503 }