%{
/*
* libid3tag - ID3 tag manipulation library
* Copyright (C) 2000-2004 Underbit Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: compat.gperf,v 1.11 2004/01/23 09:41:32 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include "global.h"
# include <stdlib.h>
# include <string.h>
# ifdef HAVE_ASSERT_H
# include <assert.h>
# endif
# include "id3tag.h"
# include "compat.h"
# include "frame.h"
# include "field.h"
# include "parse.h"
# include "ucs4.h"
# define EQ(id) #id, 0
# define OBSOLETE 0, 0
# define TX(id) #id, translate_##id
static id3_compat_func_t translate_TCON;
%}
struct id3_compat;
%%
#
# ID3v2.2 and ID3v2.3 frames
#
# Only obsolete frames or frames with an equivalent ID3v2.4 frame ID are
# listed here. If a frame ID is not listed, it is assumed that the same
# frame ID is itself the equivalent ID3v2.4 frame ID.
#
# This list may also include frames with new content interpretations; the
# translation function will rewrite the contents to comply with ID3v2.4.
#
BUF, EQ(RBUF) /* Recommended buffer size */
CNT, EQ(PCNT) /* Play counter */
COM, EQ(COMM) /* Comments */
CRA, EQ(AENC) /* Audio encryption */
CRM, OBSOLETE /* Encrypted meta frame [obsolete] */
EQU, OBSOLETE /* Equalization [obsolete] */
EQUA, OBSOLETE /* Equalization [obsolete] */
ETC, EQ(ETCO) /* Event timing codes */
GEO, EQ(GEOB) /* General encapsulated object */
IPL, EQ(TIPL) /* Involved people list */
IPLS, EQ(TIPL) /* Involved people list */
LNK, EQ(LINK) /* Linked information */
MCI, EQ(MCDI) /* Music CD identifier */
MLL, EQ(MLLT) /* MPEG location lookup table */
PIC, EQ(APIC) /* Attached picture */
POP, EQ(POPM) /* Popularimeter */
REV, EQ(RVRB) /* Reverb */
RVA, OBSOLETE /* Relative volume adjustment [obsolete] */
RVAD, OBSOLETE /* Relative volume adjustment [obsolete] */
SLT, EQ(SYLT) /* Synchronised lyric/text */
STC, EQ(SYTC) /* Synchronised tempo codes */
TAL, EQ(TALB) /* Album/movie/show title */
TBP, EQ(TBPM) /* BPM (beats per minute) */
TCM, EQ(TCOM) /* Composer */
TCO, TX(TCON) /* Content type */
TCON, TX(TCON) /* Content type */
TCR, EQ(TCOP) /* Copyright message */
TDA, OBSOLETE /* Date [obsolete] */
TDAT, OBSOLETE /* Date [obsolete] */
TDY, EQ(TDLY) /* Playlist delay */
TEN, EQ(TENC) /* Encoded by */
TFT, EQ(TFLT) /* File type */
TIM, OBSOLETE /* Time [obsolete] */
TIME, OBSOLETE /* Time [obsolete] */
TKE, EQ(TKEY) /* Initial key */
TLA, EQ(TLAN) /* Language(s) */
TLE, EQ(TLEN) /* Length */
TMT, EQ(TMED) /* Media type */
TOA, EQ(TOPE) /* Original artist(s)/performer(s) */
TOF, EQ(TOFN) /* Original filename */
TOL, EQ(TOLY) /* Original lyricist(s)/text writer(s) */
TOR, EQ(TDOR) /* Original release year [obsolete] */
TORY, EQ(TDOR) /* Original release year [obsolete] */
TOT, EQ(TOAL) /* Original album/movie/show title */
TP1, EQ(TPE1) /* Lead performer(s)/soloist(s) */
TP2, EQ(TPE2) /* Band/orchestra/accompaniment */
TP3, EQ(TPE3) /* Conductor/performer refinement */
TP4, EQ(TPE4) /* Interpreted, remixed, or otherwise modified by */
TPA, EQ(TPOS) /* Part of a set */
TPB, EQ(TPUB) /* Publisher */
TRC, EQ(TSRC) /* ISRC (international standard recording code) */
TRD, OBSOLETE /* Recording dates [obsolete] */
TRDA, OBSOLETE /* Recording dates [obsolete] */
TRK, EQ(TRCK) /* Track number/position in set */
TSI, OBSOLETE /* Size [obsolete] */
TSIZ, OBSOLETE /* Size [obsolete] */
TSS, EQ(TSSE) /* Software/hardware and settings used for encoding */
TT1, EQ(TIT1) /* Content group description */
TT2, EQ(TIT2) /* Title/songname/content description */
TT3, EQ(TIT3) /* Subtitle/description refinement */
TXT, EQ(TEXT) /* Lyricist/text writer */
TXX, EQ(TXXX) /* User defined text information frame */
TYE, OBSOLETE /* Year [obsolete] */
TYER, OBSOLETE /* Year [obsolete] */
UFI, EQ(UFID) /* Unique file identifier */
ULT, EQ(USLT) /* Unsynchronised lyric/text transcription */
WAF, EQ(WOAF) /* Official audio file webpage */
WAR, EQ(WOAR) /* Official artist/performer webpage */
WAS, EQ(WOAS) /* Official audio source webpage */
WCM, EQ(WCOM) /* Commercial information */
WCP, EQ(WCOP) /* Copyright/legal information */
WPB, EQ(WPUB) /* Publishers official webpage */
WXX, EQ(WXXX) /* User defined URL link frame */
%%
static
int translate_TCON(struct id3_frame *frame, char const *oldid,
id3_byte_t const *data, id3_length_t length)
{
id3_byte_t const *end;
enum id3_field_textencoding encoding;
id3_ucs4_t *string = 0, *ptr, *endptr;
int result = 0;
/* translate old TCON syntax into multiple strings */
assert(frame->nfields == 2);
encoding = ID3_FIELD_TEXTENCODING_ISO_8859_1;
end = data + length;
if (id3_field_parse(&frame->fields[0], &data, end - data, &encoding) == -1)
goto fail;
string = id3_parse_string(&data, end - data, encoding, 0);
if (string == 0)
goto fail;
ptr = string;
while (*ptr == '(') {
if (*++ptr == '(')
break;
endptr = ptr;
while (*endptr && *endptr != ')')
++endptr;
if (*endptr)
*endptr++ = 0;
if (id3_field_addstring(&frame->fields[1], ptr) == -1)
goto fail;
ptr = endptr;
}
if (*ptr && id3_field_addstring(&frame->fields[1], ptr) == -1)
goto fail;
if (0) {
fail:
result = -1;
}
if (string)
free(string);
return result;
}
/*
* NAME: compat->fixup()
* DESCRIPTION: finish compatibility translations
*/
int id3_compat_fixup(struct id3_tag *tag)
{
struct id3_frame *frame;
unsigned int index;
id3_ucs4_t timestamp[17] = { 0 };
int result = 0;
/* create a TDRC frame from obsolete TYER/TDAT/TIME frames */
/*
* TYE/TYER: YYYY
* TDA/TDAT: DDMM
* TIM/TIME: HHMM
*
* TDRC: yyyy-MM-ddTHH:mm
*/
index = 0;
while ((frame = id3_tag_findframe(tag, ID3_FRAME_OBSOLETE, index++))) {
char const *id;
id3_byte_t const *data, *end;
id3_length_t length;
enum id3_field_textencoding encoding;
id3_ucs4_t *string;
id = id3_field_getframeid(&frame->fields[0]);
assert(id);
if (strcmp(id, "TYER") != 0 && strcmp(id, "YTYE") != 0 &&
strcmp(id, "TDAT") != 0 && strcmp(id, "YTDA") != 0 &&
strcmp(id, "TIME") != 0 && strcmp(id, "YTIM") != 0)
continue;
data = id3_field_getbinarydata(&frame->fields[1], &length);
assert(data);
if (length < 1)
continue;
end = data + length;
encoding = id3_parse_uint(&data, 1);
string = id3_parse_string(&data, end - data, encoding, 0);
if (id3_ucs4_length(string) < 4) {
free(string);
continue;
}
if (strcmp(id, "TYER") == 0 ||
strcmp(id, "YTYE") == 0) {
timestamp[0] = string[0];
timestamp[1] = string[1];
timestamp[2] = string[2];
timestamp[3] = string[3];
}
else if (strcmp(id, "TDAT") == 0 ||
strcmp(id, "YTDA") == 0) {
timestamp[4] = '-';
timestamp[5] = string[2];
timestamp[6] = string[3];
timestamp[7] = '-';
timestamp[8] = string[0];
timestamp[9] = string[1];
}
else { /* TIME or YTIM */
timestamp[10] = 'T';
timestamp[11] = string[0];
timestamp[12] = string[1];
timestamp[13] = ':';
timestamp[14] = string[2];
timestamp[15] = string[3];
}
free(string);
}
if (timestamp[0]) {
id3_ucs4_t *strings;
frame = id3_frame_new("TDRC");
if (frame == 0)
goto fail;
strings = timestamp;
if (id3_field_settextencoding(&frame->fields[0],
ID3_FIELD_TEXTENCODING_ISO_8859_1) == -1 ||
id3_field_setstrings(&frame->fields[1], 1, &strings) == -1 ||
id3_tag_attachframe(tag, frame) == -1) {
id3_frame_delete(frame);
goto fail;
}
}
if (0) {
fail:
result = -1;
}
return result;
}