1%{ 2/* 3 * libid3tag - ID3 tag manipulation library 4 * Copyright (C) 2000-2003 Underbit Technologies, Inc. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 20 * $Id: compat.gperf,v 1.10 2003/04/19 00:14:33 rob Exp $ 21 */ 22 23# ifdef HAVE_CONFIG_H 24# include "config.h" 25# endif 26 27# include "global.h" 28 29# include <stdlib.h> 30# include <string.h> 31 32# ifdef HAVE_ASSERT_H 33# include <assert.h> 34# endif 35 36# include "id3tag.h" 37# include "compat.h" 38# include "frame.h" 39# include "field.h" 40# include "parse.h" 41# include "ucs4.h" 42 43# define EQ(id) #id, 0 44# define OBSOLETE 0, 0 45# define TX(id) #id, translate_##id 46 47static id3_compat_func_t translate_TCON; 48%} 49struct id3_compat; 50%% 51# 52# ID3v2.2 and ID3v2.3 frames 53# 54# Only obsolete frames or frames with an equivalent ID3v2.4 frame ID are 55# listed here. If a frame ID is not listed, it is assumed that the same 56# frame ID is itself the equivalent ID3v2.4 frame ID. 57# 58# This list may also include frames with new content interpretations; the 59# translation function will rewrite the contents to comply with ID3v2.4. 60# 61BUF, EQ(RBUF) /* Recommended buffer size */ 62CNT, EQ(PCNT) /* Play counter */ 63COM, EQ(COMM) /* Comments */ 64CRA, EQ(AENC) /* Audio encryption */ 65CRM, OBSOLETE /* Encrypted meta frame [obsolete] */ 66EQU, OBSOLETE /* Equalization [obsolete] */ 67EQUA, OBSOLETE /* Equalization [obsolete] */ 68ETC, EQ(ETCO) /* Event timing codes */ 69GEO, EQ(GEOB) /* General encapsulated object */ 70IPL, EQ(TIPL) /* Involved people list */ 71IPLS, EQ(TIPL) /* Involved people list */ 72LNK, EQ(LINK) /* Linked information */ 73MCI, EQ(MCDI) /* Music CD identifier */ 74MLL, EQ(MLLT) /* MPEG location lookup table */ 75PIC, EQ(APIC) /* Attached picture */ 76POP, EQ(POPM) /* Popularimeter */ 77REV, EQ(RVRB) /* Reverb */ 78RVA, OBSOLETE /* Relative volume adjustment [obsolete] */ 79RVAD, OBSOLETE /* Relative volume adjustment [obsolete] */ 80SLT, EQ(SYLT) /* Synchronised lyric/text */ 81STC, EQ(SYTC) /* Synchronised tempo codes */ 82TAL, EQ(TALB) /* Album/movie/show title */ 83TBP, EQ(TBPM) /* BPM (beats per minute) */ 84TCM, EQ(TCOM) /* Composer */ 85TCO, TX(TCON) /* Content type */ 86TCON, TX(TCON) /* Content type */ 87TCR, EQ(TCOP) /* Copyright message */ 88TDA, OBSOLETE /* Date [obsolete] */ 89TDAT, OBSOLETE /* Date [obsolete] */ 90TDY, EQ(TDLY) /* Playlist delay */ 91TEN, EQ(TENC) /* Encoded by */ 92TFT, EQ(TFLT) /* File type */ 93TIM, OBSOLETE /* Time [obsolete] */ 94TIME, OBSOLETE /* Time [obsolete] */ 95TKE, EQ(TKEY) /* Initial key */ 96TLA, EQ(TLAN) /* Language(s) */ 97TLE, EQ(TLEN) /* Length */ 98TMT, EQ(TMED) /* Media type */ 99TOA, EQ(TOPE) /* Original artist(s)/performer(s) */ 100TOF, EQ(TOFN) /* Original filename */ 101TOL, EQ(TOLY) /* Original lyricist(s)/text writer(s) */ 102TOR, EQ(TDOR) /* Original release year [obsolete] */ 103TORY, EQ(TDOR) /* Original release year [obsolete] */ 104TOT, EQ(TOAL) /* Original album/movie/show title */ 105TP1, EQ(TPE1) /* Lead performer(s)/soloist(s) */ 106TP2, EQ(TPE2) /* Band/orchestra/accompaniment */ 107TP3, EQ(TPE3) /* Conductor/performer refinement */ 108TP4, EQ(TPE4) /* Interpreted, remixed, or otherwise modified by */ 109TPA, EQ(TPOS) /* Part of a set */ 110TPB, EQ(TPUB) /* Publisher */ 111TRC, EQ(TSRC) /* ISRC (international standard recording code) */ 112TRD, OBSOLETE /* Recording dates [obsolete] */ 113TRDA, OBSOLETE /* Recording dates [obsolete] */ 114TRK, EQ(TRCK) /* Track number/position in set */ 115TSI, OBSOLETE /* Size [obsolete] */ 116TSIZ, OBSOLETE /* Size [obsolete] */ 117TSS, EQ(TSSE) /* Software/hardware and settings used for encoding */ 118TT1, EQ(TIT1) /* Content group description */ 119TT2, EQ(TIT2) /* Title/songname/content description */ 120TT3, EQ(TIT3) /* Subtitle/description refinement */ 121TXT, EQ(TEXT) /* Lyricist/text writer */ 122TXX, EQ(TXXX) /* User defined text information frame */ 123TYE, OBSOLETE /* Year [obsolete] */ 124TYER, OBSOLETE /* Year [obsolete] */ 125UFI, EQ(UFID) /* Unique file identifier */ 126ULT, EQ(USLT) /* Unsynchronised lyric/text transcription */ 127WAF, EQ(WOAF) /* Official audio file webpage */ 128WAR, EQ(WOAR) /* Official artist/performer webpage */ 129WAS, EQ(WOAS) /* Official audio source webpage */ 130WCM, EQ(WCOM) /* Commercial information */ 131WCP, EQ(WCOP) /* Copyright/legal information */ 132WPB, EQ(WPUB) /* Publishers official webpage */ 133WXX, EQ(WXXX) /* User defined URL link frame */ 134%% 135 136static 137int translate_TCON(struct id3_frame *frame, char const *oldid, 138 id3_byte_t const *data, id3_length_t length) 139{ 140 id3_byte_t const *end; 141 enum id3_field_textencoding encoding; 142 id3_ucs4_t *string = 0, *ptr, *endptr; 143 int result = 0; 144 145 /* translate old TCON syntax into multiple strings */ 146 147 assert(frame->nfields == 2); 148 149 encoding = ID3_FIELD_TEXTENCODING_ISO_8859_1; 150 151 end = data + length; 152 153 if (id3_field_parse(&frame->fields[0], &data, end - data, &encoding) == -1) 154 goto fail; 155 156 string = id3_parse_string(&data, end - data, encoding, 0); 157 if (string == 0) 158 goto fail; 159 160 ptr = string; 161 while (*ptr == '(') { 162 if (*++ptr == '(') 163 break; 164 165 endptr = ptr; 166 while (*endptr && *endptr != ')') 167 ++endptr; 168 169 if (*endptr) 170 *endptr++ = 0; 171 172 if (id3_field_addstring(&frame->fields[1], ptr) == -1) 173 goto fail; 174 175 ptr = endptr; 176 } 177 178 if (*ptr && id3_field_addstring(&frame->fields[1], ptr) == -1) 179 goto fail; 180 181 if (0) { 182 fail: 183 result = -1; 184 } 185 186 if (string) 187 free(string); 188 189 return result; 190} 191 192/* 193 * NAME: compat->fixup() 194 * DESCRIPTION: finish compatibility translations 195 */ 196int id3_compat_fixup(struct id3_tag *tag) 197{ 198 struct id3_frame *frame; 199 unsigned int index; 200 id3_ucs4_t timestamp[17] = { 0 }; 201 int result = 0; 202 203 /* create a TDRC frame from obsolete TYER/TDAT/TIME frames */ 204 205 /* 206 * TYE/TYER: YYYY 207 * TDA/TDAT: DDMM 208 * TIM/TIME: HHMM 209 * 210 * TDRC: yyyy-MM-ddTHH:mm 211 */ 212 213 index = 0; 214 while ((frame = id3_tag_findframe(tag, ID3_FRAME_OBSOLETE, index++))) { 215 char const *id; 216 id3_byte_t const *data, *end; 217 id3_length_t length; 218 enum id3_field_textencoding encoding; 219 id3_ucs4_t *string; 220 221 id = id3_field_getframeid(&frame->fields[0]); 222 assert(id); 223 224 if (strcmp(id, "TYER") != 0 && strcmp(id, "YTYE") != 0 && 225 strcmp(id, "TDAT") != 0 && strcmp(id, "YTDA") != 0 && 226 strcmp(id, "TIME") != 0 && strcmp(id, "YTIM") != 0) 227 continue; 228 229 data = id3_field_getbinarydata(&frame->fields[1], &length); 230 assert(data); 231 232 if (length < 1) 233 continue; 234 235 end = data + length; 236 237 encoding = id3_parse_uint(&data, 1); 238 string = id3_parse_string(&data, end - data, encoding, 0); 239 240 if (id3_ucs4_length(string) < 4) { 241 free(string); 242 continue; 243 } 244 245 if (strcmp(id, "TYER") == 0 || 246 strcmp(id, "YTYE") == 0) { 247 timestamp[0] = string[0]; 248 timestamp[1] = string[1]; 249 timestamp[2] = string[2]; 250 timestamp[3] = string[3]; 251 } 252 else if (strcmp(id, "TDAT") == 0 || 253 strcmp(id, "YTDA") == 0) { 254 timestamp[4] = '-'; 255 timestamp[5] = string[2]; 256 timestamp[6] = string[3]; 257 timestamp[7] = '-'; 258 timestamp[8] = string[0]; 259 timestamp[9] = string[1]; 260 } 261 else { /* TIME or YTIM */ 262 timestamp[10] = 'T'; 263 timestamp[11] = string[0]; 264 timestamp[12] = string[1]; 265 timestamp[13] = ':'; 266 timestamp[14] = string[2]; 267 timestamp[15] = string[3]; 268 } 269 270 free(string); 271 } 272 273 if (timestamp[0]) { 274 id3_ucs4_t *strings; 275 276 frame = id3_frame_new("TDRC"); 277 if (frame == 0) 278 goto fail; 279 280 strings = timestamp; 281 282 if (id3_field_settextencoding(&frame->fields[0], 283 ID3_FIELD_TEXTENCODING_ISO_8859_1) == -1 || 284 id3_field_setstrings(&frame->fields[1], 1, &strings) == -1 || 285 id3_tag_attachframe(tag, frame) == -1) { 286 id3_frame_delete(frame); 287 goto fail; 288 } 289 } 290 291 if (0) { 292 fail: 293 result = -1; 294 } 295 296 return result; 297} 298