1 /* @(#)cd_text.c 1.11 10/12/19 Copyright 2000-2001 Heiko Eissfeldt, Copyright 2006-2010 J. Schilling */
2
3 /*
4 * This is an include file!
5 */
6 /*
7 * The contents of this file are subject to the terms of the
8 * Common Development and Distribution License, Version 1.0 only
9 * (the "License"). You may not use this file except in compliance
10 * with the License.
11 *
12 * See the file CDDL.Schily.txt in this distribution for details.
13 * A copy of the CDDL is also available via the Internet at
14 * http://www.opensource.org/licenses/cddl1.txt
15 *
16 * When distributing Covered Code, include this CDDL HEADER in each
17 * file and include the License file CDDL.Schily.txt from this distribution.
18 */
19
20 /* *************** CD-Text special treatment ******************************* */
21
22 typedef struct {
23 unsigned char headerfield[4];
24 unsigned char textdatafield[12];
25 unsigned char crcfield[2];
26 } cdtextpackdata;
27
28 static unsigned short crctab[1<<8] = { /* as calculated by initcrctab() */
29 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
30 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
31 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
32 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
33 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
34 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
35 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
36 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
37 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
38 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
39 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
40 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
41 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
42 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
43 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
44 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
45 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
46 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
47 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
48 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
49 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
50 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
51 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
52 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
53 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
54 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
55 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
56 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
57 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
58 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
59 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
60 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
61 };
62
63 #define SUBSIZE 18*8
64
65 static unsigned short updcrc __PR((unsigned int p_crc,
66 unsigned char *cp,
67 size_t cnt));
68
69 static unsigned short
updcrc(p_crc,cp,cnt)70 updcrc(p_crc, cp, cnt)
71 unsigned int p_crc;
72 register unsigned char *cp;
73 register size_t cnt;
74 {
75 register unsigned short crc = (unsigned short)p_crc;
76
77 while (cnt--) {
78 crc = (crc<<8) ^ crctab[(crc>>(16-8)) ^ (*cp++)];
79 }
80 return (crc);
81 }
82
83 static unsigned short calcCRC __PR((unsigned char *buf, unsigned bsize));
84
85 static unsigned short
calcCRC(buf,bsize)86 calcCRC(buf, bsize)
87 unsigned char *buf;
88 unsigned bsize;
89 {
90 return (updcrc(0x0, (unsigned char *)buf, bsize));
91 }
92
93 static unsigned char fliptab[8] = {
94 0x01,
95 0x02,
96 0x04,
97 0x08,
98 0x10,
99 0x20,
100 0x40,
101 0x80,
102 };
103
104 static int flip_error_corr __PR((unsigned char *b, int crc));
105
106 static int
flip_error_corr(b,crc)107 flip_error_corr(b, crc)
108 unsigned char *b;
109 int crc;
110 {
111 if (crc != 0) {
112 int i;
113
114 for (i = 0; i < SUBSIZE; i++) {
115 char c;
116
117 c = fliptab[i%8];
118 b[i / 8] ^= c;
119 if ((crc = calcCRC(b, SUBSIZE/8)) == 0) {
120 return (crc);
121 }
122 b[i / 8] ^= c;
123 }
124 }
125 return (crc & 0xffff);
126 }
127
128
129 static int cdtext_crc_ok __PR((cdtextpackdata *c));
130
131 static int
cdtext_crc_ok(c)132 cdtext_crc_ok(c)
133 cdtextpackdata *c;
134 {
135 int crc;
136 int retval;
137
138 c->crcfield[0] ^= 0xff;
139 c->crcfield[1] ^= 0xff;
140 crc = calcCRC(((unsigned char *)c), 18);
141 retval = (0 == flip_error_corr((unsigned char *)c, crc));
142 c->crcfield[0] ^= 0xff;
143 c->crcfield[1] ^= 0xff;
144 #if 0
145 fprintf(stderr, "%02x %02x %02x %02x ",
146 c->headerfield[0], c->headerfield[1],
147 c->headerfield[2], c->headerfield[3]);
148 fprintf(stderr,
149 "%c %c %c %c %c %c %c %c %c %c %c %c ",
150 c->textdatafield[0],
151 c->textdatafield[1],
152 c->textdatafield[2],
153 c->textdatafield[3],
154 c->textdatafield[4],
155 c->textdatafield[5],
156 c->textdatafield[6],
157 c->textdatafield[7],
158 c->textdatafield[8],
159 c->textdatafield[9],
160 c->textdatafield[10],
161 c->textdatafield[11]);
162 fprintf(stderr, "%02x %02x \n",
163 c->crcfield[0],
164 c->crcfield[1]);
165 #endif
166 return (retval);
167 }
168
169 #define DETAILED 0
170
171 #if DETAILED
172 static void dump_binary __PR((cdtextpackdata *c));
173
174 static void
dump_binary(c)175 dump_binary(c)
176 cdtextpackdata *c;
177 {
178 fprintf(stderr, _(": header fields %02x %02x %02x "),
179 c->headerfield[1], c->headerfield[2], c->headerfield[3]);
180 fprintf(stderr,
181 "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
182 c->textdatafield[0],
183 c->textdatafield[1],
184 c->textdatafield[2],
185 c->textdatafield[3],
186 c->textdatafield[4],
187 c->textdatafield[5],
188 c->textdatafield[6],
189 c->textdatafield[7],
190 c->textdatafield[8],
191 c->textdatafield[9],
192 c->textdatafield[10],
193 c->textdatafield[11]);
194 }
195 #endif
196
197 static int process_header __PR((cdtextpackdata *c, unsigned tracknr,
198 int dbcc, unsigned char *line));
199
200 static int
process_header(c,tracknr,dbcc,line)201 process_header(c, tracknr, dbcc, line)
202 cdtextpackdata *c;
203 unsigned tracknr;
204 int dbcc;
205 unsigned char *line;
206 {
207 switch ((int)c->headerfield[0]) {
208
209 case 0x80: /* Title of album or track */
210 #if DETAILED
211 fprintf(stderr, _("Title"));
212 #endif
213 if (tracknr > 0 && tracknr < 100 &&
214 global.tracktitle[tracknr] == NULL) {
215 unsigned len;
216
217 len = strlen((char *)line);
218
219 if (len > 0)
220 global.tracktitle[tracknr] = malloc(len + 1);
221 if (global.tracktitle[tracknr] != NULL) {
222 memcpy(global.tracktitle[tracknr], line, len);
223 global.tracktitle[tracknr][len] = '\0';
224 }
225 } else if (tracknr == 0 &&
226 global.disctitle == NULL) {
227 unsigned len;
228
229 len = strlen((char *)line);
230
231 if (len > 0)
232 global.disctitle = malloc(len + 1);
233 if (global.disctitle != NULL) {
234 memcpy(global.disctitle, line, len);
235 global.disctitle[len] = '\0';
236 }
237 }
238 break;
239
240 case 0x81: /* Name(s) of the performer(s) */
241 #if DETAILED
242 fprintf(stderr, _("Performer(s)"));
243 #endif
244 if (tracknr > 0 && tracknr < 100 &&
245 global.trackperformer[tracknr] == NULL) {
246 unsigned len;
247
248 len = strlen((char *)line);
249
250 if (len > 0)
251 global.trackperformer[tracknr] = malloc(len + 1);
252
253 if (global.trackperformer[tracknr] != NULL) {
254 memcpy(global.trackperformer[tracknr], line,
255 len);
256 global.trackperformer[tracknr][len] = '\0';
257 }
258 } else if (tracknr == 0 &&
259 global.performer == NULL) {
260 unsigned len;
261
262 len = strlen((char *)line);
263
264 if (len > 0)
265 global.performer = malloc(len + 1);
266 if (global.performer != NULL) {
267 memcpy(global.performer, line, len);
268 global.performer[len] = '\0';
269 }
270 }
271 break;
272
273 case 0x82: /* Name(s) of the songwriter(s) */
274 #if DETAILED
275 fprintf(stderr, _("Songwriter(s)"));
276 #endif
277 if (tracknr > 0 && tracknr < 100 &&
278 global.tracksongwriter[tracknr] == NULL) {
279 unsigned len;
280
281 len = strlen((char *)line);
282
283 if (len > 0)
284 global.tracksongwriter[tracknr] = malloc(len + 1);
285
286 if (global.tracksongwriter[tracknr] != NULL) {
287 memcpy(global.tracksongwriter[tracknr], line,
288 len);
289 global.tracksongwriter[tracknr][len] = '\0';
290 }
291 } else if (tracknr == 0 &&
292 global.songwriter == NULL) {
293 unsigned len;
294
295 len = strlen((char *)line);
296
297 if (len > 0)
298 global.songwriter = malloc(len + 1);
299 if (global.songwriter != NULL) {
300 memcpy(global.songwriter, line, len);
301 global.songwriter[len] = '\0';
302 }
303 }
304 break;
305
306 case 0x83: /* Name(s) of the composer(s) */
307 #if DETAILED
308 fprintf(stderr, _("Composer(s)"));
309 #endif
310 if (tracknr > 0 && tracknr < 100 &&
311 global.trackcomposer[tracknr] == NULL) {
312 unsigned len;
313
314 len = strlen((char *)line);
315
316 if (len > 0)
317 global.trackcomposer[tracknr] = malloc(len + 1);
318
319 if (global.trackcomposer[tracknr] != NULL) {
320 memcpy(global.trackcomposer[tracknr], line,
321 len);
322 global.trackcomposer[tracknr][len] = '\0';
323 }
324 } else if (tracknr == 0 &&
325 global.composer == NULL) {
326 unsigned len;
327
328 len = strlen((char *)line);
329
330 if (len > 0)
331 global.composer = malloc(len + 1);
332 if (global.composer != NULL) {
333 memcpy(global.composer, line, len);
334 global.composer[len] = '\0';
335 }
336 }
337 break;
338
339 case 0x84: /* Name(s) of the arranger(s) */
340 #if DETAILED
341 fprintf(stderr, _("Arranger(s)"));
342 #endif
343 if (tracknr > 0 && tracknr < 100 &&
344 global.trackarranger[tracknr] == NULL) {
345 unsigned len;
346
347 len = strlen((char *)line);
348
349 if (len > 0)
350 global.trackarranger[tracknr] = malloc(len + 1);
351
352 if (global.trackarranger[tracknr] != NULL) {
353 memcpy(global.trackarranger[tracknr], line,
354 len);
355 global.trackarranger[tracknr][len] = '\0';
356 }
357 } else if (tracknr == 0 &&
358 global.arranger == NULL) {
359 unsigned len;
360
361 len = strlen((char *)line);
362
363 if (len > 0)
364 global.arranger = malloc(len + 1);
365 if (global.arranger != NULL) {
366 memcpy(global.arranger, line, len);
367 global.arranger[len] = '\0';
368 }
369 }
370 break;
371
372 case 0x85: /* Message from content provider and/or artist */
373 #if DETAILED
374 fprintf(stderr, _("Message"));
375 #endif
376 if (tracknr > 0 && tracknr < 100 &&
377 global.trackmessage[tracknr] == NULL) {
378 unsigned len;
379
380 len = strlen((char *)line);
381
382 if (len > 0)
383 global.trackmessage[tracknr] = malloc(len + 1);
384
385 if (global.trackmessage[tracknr] != NULL) {
386 memcpy(global.trackmessage[tracknr], line,
387 len);
388 global.trackmessage[tracknr][len] = '\0';
389 }
390 } else if (tracknr == 0 &&
391 global.message == NULL) {
392 unsigned len;
393
394 len = strlen((char *)line);
395
396 if (len > 0)
397 global.message = malloc(len + 1);
398 if (global.message != NULL) {
399 memcpy(global.message, line, len);
400 global.message[len] = '\0';
401 }
402 }
403 break;
404
405 case 0x86: /* Disc Identification and information */
406 #if DETAILED
407 fprintf(stderr, _("Disc identification"));
408 #endif
409 if (tracknr == 0 && line[0] != '\0') {
410 fprintf(stderr, _("Disc identification: %s\n"), line);
411 }
412 break;
413
414 case 0x87: /* Genre Identification and information */
415 #if DETAILED
416 fprintf(stderr, _("Genre identification"));
417 #endif
418 break;
419
420 case 0x8d: /* Closed information */
421 #if DETAILED
422 fprintf(stderr, _("Closed information"));
423 #endif
424 if (tracknr > 0 && tracknr < 100 &&
425 global.trackclosed_info[tracknr] == NULL) {
426 unsigned len;
427
428 len = strlen((char *)line);
429
430 if (len > 0)
431 global.trackclosed_info[tracknr] = malloc(len + 1);
432
433 if (global.trackclosed_info[tracknr] != NULL) {
434 memcpy(global.trackclosed_info[tracknr], line,
435 len);
436 global.trackclosed_info[tracknr][len] = '\0';
437 }
438 } else if (tracknr == 0 &&
439 global.closed_info == NULL) {
440 unsigned len;
441
442 len = strlen((char *)line);
443
444 if (len > 0)
445 global.closed_info = malloc(len + 1);
446 if (global.closed_info != NULL) {
447 memcpy(global.closed_info, line, len);
448 global.closed_info[len] = '\0';
449 }
450 }
451 break;
452
453 case 0x8e: /* UPC/EAN code or ISRC code */
454 #if DETAILED
455 fprintf(stderr, _("UPC or ISRC"));
456 #endif
457 if (tracknr > 0 && tracknr < 100) {
458 Set_ISRC(tracknr, line);
459 } else if (tracknr == 0 && line[0] != '\0') {
460 Set_MCN(line);
461 }
462 break;
463
464 case 0x88: /* Table of Content information */
465 #if DETAILED
466 fprintf(stderr, _("Table of Content identification"));
467 dump_binary(c);
468 #endif
469 return (0);
470
471 case 0x89: /* Second Table of Content information */
472 #if DETAILED
473 fprintf(stderr, _("Second Table of Content identification"));
474 dump_binary(c);
475 #endif
476 return (0);
477
478 case 0x8f: /* Size information of the block */
479 #if DETAILED == 0
480 break;
481 #else
482 switch (tracknr) {
483
484 case 0:
485 fprintf(outfp,
486 _("first track is %d, last track is %d\n"),
487 c->textdatafield[1],
488 c->textdatafield[2]);
489 if (c->textdatafield[3] & 0x80) {
490 fprintf(outfp,
491 _("Program Area CD Text information available\n"));
492 if (c->textdatafield[3] & 0x40) {
493 fprintf(outfp, _("Program Area copy protection available\n"));
494 }
495 }
496 if (c->textdatafield[3] & 0x07) {
497 fprintf(outfp,
498 _("message information is %scopyrighted\n"),
499 c->textdatafield[3] & 0x04 ?
500 "": _("not "));
501 fprintf(outfp,
502 _("Names of performer/songwriter/composer/arranger(s) are %scopyrighted\n"),
503 c->textdatafield[3] & 0x02 ?
504 "": _("not "));
505 fprintf(outfp,
506 _("album and track names are %scopyrighted\n"),
507 c->textdatafield[3] & 0x01 ?
508 "": _("not "));
509 }
510 fprintf(outfp,
511 _("%d packs with album/track names\n"),
512 c->textdatafield[4]);
513 fprintf(outfp,
514 _("%d packs with performer names\n"),
515 c->textdatafield[5]);
516 fprintf(outfp,
517 _("%d packs with songwriter names\n"),
518 c->textdatafield[6]);
519 fprintf(outfp,
520 _("%d packs with composer names\n"),
521 c->textdatafield[7]);
522 fprintf(outfp,
523 _("%d packs with arranger names\n"),
524 c->textdatafield[8]);
525 fprintf(outfp,
526 _("%d packs with artist or content provider messages\n"),
527 c->textdatafield[9]);
528 fprintf(outfp,
529 _("%d packs with disc identification information\n"),
530 c->textdatafield[10]);
531 fprintf(outfp,
532 _("%d packs with genre identification/information\n"),
533 c->textdatafield[11]);
534 break;
535
536 case 1:
537 fprintf(outfp,
538 _("%d packs with table of contents information\n"),
539 c->textdatafield[0]);
540 fprintf(outfp,
541 _("%d packs with second table of contents information\n"),
542 c->textdatafield[1]);
543 fprintf(outfp,
544 _("%d packs with reserved information\n"),
545 c->textdatafield[2]);
546 fprintf(outfp,
547 _("%d packs with reserved information\n"),
548 c->textdatafield[3]);
549 fprintf(outfp,
550 _("%d packs with reserved information\n"),
551 c->textdatafield[4]);
552 fprintf(outfp,
553 _("%d packs with closed information\n"),
554 c->textdatafield[5]);
555 fprintf(outfp,
556 _("%d packs with UPC/EAN ISRC information\n"),
557 c->textdatafield[6]);
558 fprintf(outfp,
559 _("%d packs with size information\n"),
560 c->textdatafield[7]);
561 fprintf(outfp,
562 _("last sequence numbers for blocks 1-8: %d %d %d %d "),
563 c->textdatafield[8],
564 c->textdatafield[9],
565 c->textdatafield[10],
566 c->textdatafield[11]);
567 break;
568
569 case 2:
570 fprintf(outfp, "%d %d %d %d\n",
571 c->textdatafield[0],
572 c->textdatafield[1],
573 c->textdatafield[2],
574 c->textdatafield[3]);
575 fprintf(outfp,
576 _("Language codes for blocks 1-8: %d %d %d %d %d %d %d %d\n"),
577 c->textdatafield[4],
578 c->textdatafield[5],
579 c->textdatafield[6],
580 c->textdatafield[7],
581 c->textdatafield[8],
582 c->textdatafield[9],
583 c->textdatafield[10],
584 c->textdatafield[11]);
585 break;
586 }
587
588 fprintf(stderr, _("Blocksize"));
589 dump_binary(c);
590 return (0);
591
592 #if !defined DEBUG_CDTEXT
593 default:
594 #else
595 }
596 #endif
597
598 fprintf(stderr, _(": header fields %02x %02x %02x "),
599 c->headerfield[1], c->headerfield[2],
600 c->headerfield[3]);
601 #endif /* DETAILED */
602
603 #if !defined DEBUG_CDTEXT
604 }
605 #if DETAILED
606 if (tracknr == 0) {
607 fprintf(stderr, _(" for album : ->"));
608 } else {
609 fprintf(stderr, _(" for track %2u: ->"), tracknr);
610 }
611 fputs((char *)line, stderr);
612 fputs("<-", stderr);
613 #endif
614
615 if (dbcc != 0) {
616 #else
617 {
618 #endif
619 /* EMPTY */
620 #if DETAILED
621 fprintf(stderr,
622 " %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
623 c->textdatafield[0],
624 c->textdatafield[1],
625 c->textdatafield[2],
626 c->textdatafield[3],
627 c->textdatafield[4],
628 c->textdatafield[5],
629 c->textdatafield[6],
630 c->textdatafield[7],
631 c->textdatafield[8],
632 c->textdatafield[9],
633 c->textdatafield[10],
634 c->textdatafield[11]);
635 #endif
636 }
637 return (0);
638 }
639