Imported Upstream version 1.1.11
[platform/upstream/cdrkit.git] / icedax / cd_text.c
1 /*
2  * This file has been modified for the cdrkit suite.
3  *
4  * The behaviour and appearence of the program code below can differ to a major
5  * extent from the version distributed by the original author(s).
6  *
7  * For details, see Changelog file distributed with the cdrkit package. If you
8  * received this file from another source then ask the distributing person for
9  * a log of modifications.
10  *
11  */
12
13 /* @(#)cd_text.c        1.5 03/12/31 Copyright 2000-2001 Heiko Eissfeldt */
14
15 /* This is an include file! */
16 /**************** CD-Text special treatment **********************************/
17
18 typedef struct {
19         unsigned char headerfield[4];
20         unsigned char textdatafield[12];
21         unsigned char crcfield[2];
22 } cdtextpackdata;
23
24 static unsigned short crctab[1<<8] = { /* as calculated by initcrctab() */
25     0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
26     0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
27     0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
28     0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
29     0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
30     0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
31     0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
32     0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
33     0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
34     0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
35     0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
36     0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
37     0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
38     0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
39     0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
40     0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
41     0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
42     0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
43     0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
44     0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
45     0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
46     0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
47     0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
48     0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
49     0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
50     0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
51     0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
52     0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
53     0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
54     0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
55     0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
56     0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0,
57     };
58
59 #define SUBSIZE 18*8
60
61 static unsigned short updcrc(unsigned int p_crc, register unsigned char *cp,
62                                                           register size_t cnt);
63
64 static unsigned short updcrc(unsigned int p_crc, register unsigned char *cp, 
65                              register size_t cnt)
66 {
67       register unsigned short crc = (unsigned short)p_crc;
68       while( cnt-- ) {
69             crc = (crc<<8) ^ crctab[(crc>>(16-8)) ^ (*cp++)];
70       }
71       return( crc );
72 }
73
74 static unsigned short calcCRC(unsigned char *buf, unsigned bsize);
75
76 static unsigned short calcCRC(unsigned char *buf, unsigned bsize)
77 {
78       return updcrc( 0x0, (unsigned char *)buf, bsize );
79 }
80
81 static unsigned char    fliptab[8] = {
82         0x01,
83         0x02,
84         0x04,
85         0x08,
86         0x10,
87         0x20,
88         0x40,
89         0x80,
90 };
91
92 static int flip_error_corr(unsigned char *b, int crc);
93
94 static int flip_error_corr(unsigned char *b, int crc)
95 {
96   if (crc != 0) {
97     int i;
98     for (i = 0; i < SUBSIZE; i++) {
99       char      c;
100
101       c = fliptab[i%8];
102       b[i / 8] ^= c;
103       if ((crc = calcCRC(b, SUBSIZE/8)) == 0) {
104         return crc;
105       }
106       b[i / 8] ^= c;
107     }
108   }
109   return crc & 0xffff;
110 }
111
112
113 static int cdtext_crc_ok(cdtextpackdata *c);
114
115 static int cdtext_crc_ok(cdtextpackdata *c)
116 {
117         int crc;
118         int retval;
119
120         c->crcfield[0] ^= 0xff;
121         c->crcfield[1] ^= 0xff;
122         crc = calcCRC(((unsigned char *)c), 18);
123         retval = (0 == flip_error_corr((unsigned char *)c, crc));
124         c->crcfield[0] ^= 0xff;
125         c->crcfield[1] ^= 0xff;
126 #if     0
127           fprintf(stderr, "%02x %02x %02x %02x  ",
128                           c->headerfield[0], c->headerfield[1], c->headerfield[2], c->headerfield[3]);
129           fprintf(stderr,
130 "%c %c %c %c %c %c %c %c %c %c %c %c  "
131                         , c->textdatafield[0]
132                         , c->textdatafield[1]
133                         , c->textdatafield[2]
134                         , c->textdatafield[3]
135                         , c->textdatafield[4]
136                         , c->textdatafield[5]
137                         , c->textdatafield[6]
138                         , c->textdatafield[7]
139                         , c->textdatafield[8]
140                         , c->textdatafield[9]
141                         , c->textdatafield[10]
142                         , c->textdatafield[11]
143                  );
144           fprintf(stderr, "%02x %02x \n"
145                         , c->crcfield[0]
146                         , c->crcfield[1]
147                 );
148 #endif
149         return retval;
150 }
151
152 #define DETAILED 0
153
154 #if     DETAILED
155 static void dump_binary(cdtextpackdata *c);
156
157 static void dump_binary(cdtextpackdata *c)
158 {
159           fprintf(stderr, ": header fields %02x %02x %02x  ",
160                           c->headerfield[1], c->headerfield[2], c->headerfield[3]);
161           fprintf(stderr,
162 "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x"
163                         , c->textdatafield[0]
164                         , c->textdatafield[1]
165                         , c->textdatafield[2]
166                         , c->textdatafield[3]
167                         , c->textdatafield[4]
168                         , c->textdatafield[5]
169                         , c->textdatafield[6]
170                         , c->textdatafield[7]
171                         , c->textdatafield[8]
172                         , c->textdatafield[9]
173                         , c->textdatafield[10]
174                         , c->textdatafield[11]
175                  );
176 }
177 #endif
178
179 static int process_header(cdtextpackdata *c, unsigned tracknr, int dbcc, 
180                                                                   unsigned char *line);
181
182 static int process_header(cdtextpackdata *c, unsigned tracknr, int dbcc, 
183                           unsigned char *line)
184 {
185       switch ((int)c->headerfield[0]) {
186
187         case 0x80: /* Title of album or track */
188 #if     DETAILED
189           fprintf (stderr, "Title");
190 #endif
191           if (tracknr > 0 && tracknr < 100
192             && global.tracktitle[tracknr] == NULL) {
193             unsigned len;
194
195             len = strlen((char *)line);
196
197             if (len > 0)
198                 global.tracktitle[tracknr] = malloc(len + 1);
199             if (global.tracktitle[tracknr] != NULL) {
200                memcpy(global.tracktitle[tracknr], line, len);
201                global.tracktitle[tracknr][len] = '\0';
202             }
203           } else 
204           if (tracknr == 0
205             && global.disctitle == NULL) {
206             unsigned len;
207
208             len = strlen((char *)line);
209
210             if (len > 0)
211                 global.disctitle = malloc(len + 1);
212             if (global.disctitle != NULL) {
213                memcpy(global.disctitle, line, len);
214                global.disctitle[len] = '\0';
215             }
216           }
217         break;
218         case 0x81: /* Name(s) of the performer(s) */
219 #if     DETAILED
220           fprintf(stderr, "Performer(s)");
221 #endif
222           if (tracknr > 0 && tracknr < 100
223             && global.trackcreator[tracknr] == NULL) {
224             unsigned len;
225
226             len = strlen((char *)line);
227
228             if (len > 0)
229                 global.trackcreator[tracknr] = malloc(len + 1);
230
231             if (global.trackcreator[tracknr] != NULL) {
232                memcpy(global.trackcreator[tracknr], line, len);
233                global.trackcreator[tracknr][len] = '\0';
234             }
235           } else 
236           if (tracknr == 0
237             && global.creator == NULL) {
238             unsigned len;
239
240             len = strlen((char *)line);
241
242             if (len > 0)
243                 global.creator = malloc(len + 1);
244             if (global.creator != NULL) {
245                memcpy(global.creator, line, len);
246                global.creator[len] = '\0';
247             }
248           }
249         break;
250         case 0x82: /* Name(s) of the songwriter(s) */
251 #if     DETAILED
252           fprintf(stderr, "Songwriter(s)");
253 #endif
254         break;
255         case 0x83: /* Name(s) of the composer(s) */
256 #if     DETAILED
257           fprintf(stderr, "Composer(s)");
258 #endif
259         break;
260         case 0x84: /* Name(s) of the arranger(s) */
261 #if     DETAILED
262           fprintf(stderr, "Arranger(s)");
263 #endif
264         break;
265         case 0x85: /* Message from content provider and/or artist */
266 #if     DETAILED
267           fprintf(stderr, "Message");
268 #endif
269         break;
270         case 0x86: /* Disc Identification and information */
271 #if     DETAILED
272           fprintf(stderr, "Disc identification");
273 #endif
274           if (tracknr == 0 && line[0] != '\0') {
275             fprintf(stderr, "Disc identification: %s\n", line);
276           }
277         break;
278         case 0x87: /* Genre Identification and information */
279 #if     DETAILED
280           fprintf(stderr, "Genre identification");
281 #endif
282         break;
283         case 0x8e: /* UPC/EAN code or ISRC code */
284 #if     DETAILED
285           fprintf(stderr, "UPC or ISRC");
286 #endif
287           if (tracknr > 0 && tracknr < 100) {
288             Set_ISRC(tracknr, line);
289           } else
290           if (tracknr == 0 && line[0] != '\0') {
291             Set_MCN(line);
292           }
293         break;
294         case 0x88: /* Table of Content information */
295 #if     DETAILED
296           fprintf(stderr, "Table of Content identification");
297           dump_binary(c); 
298 #endif
299         return 0;
300         case 0x89: /* Second Table of Content information */
301 #if     DETAILED
302           fprintf(stderr, "Second Table of Content identification");
303           dump_binary(c); 
304 #endif
305         return 0;
306         case 0x8f: /* Size information of the block */
307 #if     DETAILED == 0
308           break;
309 #else
310           switch (tracknr) {
311             case 0:
312           fprintf(stderr, "first track is %d, last track is %d\n", 
313                         c->textdatafield[1],
314                         c->textdatafield[2]);
315           if (c->textdatafield[3] & 0x80) {
316                 fprintf(stderr, "Program Area CD Text information available\n");
317                 if (c->textdatafield[3] & 0x40) {
318                   fprintf(stderr, "Program Area copy protection available\n");
319                 }
320           }
321           if (c->textdatafield[3] & 0x07) {
322                 fprintf(stderr, "message information is %scopyrighted\n", 
323                         c->textdatafield[3] & 0x04 ? "": "not ");
324                 fprintf(stderr, "Names of performer/songwriter/composer/arranger(s) are %scopyrighted\n", 
325                         c->textdatafield[3] & 0x02 ? "": "not ");
326                 fprintf(stderr, "album and track names are %scopyrighted\n", 
327                         c->textdatafield[3] & 0x01 ? "": "not ");
328           }
329           fprintf(stderr, "%d packs with album/track names\n", c->textdatafield[4]);
330           fprintf(stderr, "%d packs with performer names\n", c->textdatafield[5]);
331           fprintf(stderr, "%d packs with songwriter names\n", c->textdatafield[6]);
332           fprintf(stderr, "%d packs with composer names\n", c->textdatafield[7]);
333           fprintf(stderr, "%d packs with arranger names\n", c->textdatafield[8]);
334           fprintf(stderr, "%d packs with artist or content provider messages\n", c->textdatafield[9]);
335           fprintf(stderr, "%d packs with disc identification information\n", c->textdatafield[10]);
336           fprintf(stderr, "%d packs with genre identification/information\n", c->textdatafield[11]);
337           break;
338         case 1:
339           fprintf(stderr, "%d packs with table of contents information\n", c->textdatafield[0]);
340           fprintf(stderr, "%d packs with second table of contents information\n", c->textdatafield[1]);
341           fprintf(stderr, "%d packs with reserved information\n", c->textdatafield[2]);
342           fprintf(stderr, "%d packs with reserved information\n", c->textdatafield[3]);
343           fprintf(stderr, "%d packs with reserved information\n", c->textdatafield[4]);
344           fprintf(stderr, "%d packs with closed information\n", c->textdatafield[5]);
345           fprintf(stderr, "%d packs with UPC/EAN ISRC information\n", c->textdatafield[6]);
346           fprintf(stderr, "%d packs with size information\n", c->textdatafield[7]);
347           fprintf(stderr, "last sequence numbers for blocks 1-8: %d %d %d %d "
348                  ,c->textdatafield[8]
349                  ,c->textdatafield[9]
350                  ,c->textdatafield[10]
351                  ,c->textdatafield[11]
352                 );
353           break;
354         case 2:
355           fprintf(stderr, "%d %d %d %d\n"
356                  ,c->textdatafield[0]
357                  ,c->textdatafield[1]
358                  ,c->textdatafield[2]
359                  ,c->textdatafield[3]
360                 );
361           fprintf(stderr, "Language codes for blocks 1-8: %d %d %d %d %d %d %d %d\n"
362                  ,c->textdatafield[4]
363                  ,c->textdatafield[5]
364                  ,c->textdatafield[6]
365                  ,c->textdatafield[7]
366                  ,c->textdatafield[8]
367                  ,c->textdatafield[9]
368                  ,c->textdatafield[10]
369                  ,c->textdatafield[11]
370                 );
371           break;
372         }
373         fprintf(stderr, "Blocksize");
374         dump_binary(c); 
375         return 0;
376 #if !defined DEBUG_CDTEXT
377         default:
378 #else
379       }
380 #endif
381       fprintf(stderr, ": header fields %02x %02x %02x  ",
382               c->headerfield[1], c->headerfield[2], c->headerfield[3]);
383 #endif /* DETAILED */
384
385 #if !defined DEBUG_CDTEXT
386       }
387 #if     DETAILED
388       if (tracknr == 0) {
389             fprintf(stderr, " for album   : ->");
390       } else {
391             fprintf(stderr, " for track %2u: ->", tracknr);
392       }
393       fputs ((char *) line, stderr);
394       fputs ("<-", stderr);
395 #endif
396
397       if (dbcc != 0) {
398 #else
399       {
400 #endif
401       /* EMPTY */
402 #if     DETAILED
403           fprintf(stderr,
404 "  %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x"
405                         , c->textdatafield[0]
406                         , c->textdatafield[1]
407                         , c->textdatafield[2]
408                         , c->textdatafield[3]
409                         , c->textdatafield[4]
410                         , c->textdatafield[5]
411                         , c->textdatafield[6]
412                         , c->textdatafield[7]
413                         , c->textdatafield[8]
414                         , c->textdatafield[9]
415                         , c->textdatafield[10]
416                         , c->textdatafield[11]
417                  );
418 #endif
419       }
420       return 0;
421 }