1 /* @(#)auinfo.c 1.33 10/12/19 Copyright 1998-2010 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)auinfo.c 1.33 10/12/19 Copyright 1998-2010 J. Schilling";
6 #endif
7 /*
8 * Copyright (c) 1998-2010 J. Schilling
9 */
10 /*
11 * The contents of this file are subject to the terms of the
12 * Common Development and Distribution License, Version 1.0 only
13 * (the "License"). You may not use this file except in compliance
14 * with the License.
15 *
16 * See the file CDDL.Schily.txt in this distribution for details.
17 * A copy of the CDDL is also available via the Internet at
18 * http://www.opensource.org/licenses/cddl1.txt
19 *
20 * When distributing Covered Code, include this CDDL HEADER in each
21 * file and include the License file CDDL.Schily.txt from this distribution.
22 */
23
24 #include <schily/mconfig.h>
25 #include <schily/stdlib.h>
26 #include <schily/unistd.h>
27 #include <schily/stat.h>
28 #include <schily/stdio.h>
29 #include <schily/standard.h>
30 #include <schily/string.h>
31 #include <schily/deflts.h>
32 #include <schily/utypes.h>
33 #include <schily/schily.h>
34 #include <schily/nlsdefs.h>
35
36 #include "cdtext.h"
37 #include "cdrecord.h"
38
39 extern int debug;
40 extern int xdebug;
41
42 LOCAL int auinfopen __PR((char *name));
43 EXPORT BOOL auinfosize __PR((char *name, track_t *trackp));
44 EXPORT BOOL auinfhidden __PR((char *name, int track, track_t *trackp));
45 EXPORT void auinfo __PR((char *name, int track, track_t *trackp));
46 EXPORT textptr_t *gettextptr __PR((int track, track_t *trackp));
47 LOCAL char *savestr __PR((char *name));
48 LOCAL char *readtag __PR((char *name));
49 LOCAL char *readtstr __PR((char *name));
50 EXPORT void setmcn __PR((char *mcn, track_t *trackp));
51 LOCAL void isrc_illchar __PR((char *isrc, int c));
52 EXPORT void setisrc __PR((char *isrc, track_t *trackp));
53 EXPORT void setindex __PR((char *tindex, track_t *trackp));
54
55 #ifdef XXX
main(ac,av)56 main(ac, av)
57 int ac;
58 char *av[];
59 {
60 /* auinfo("/etc/default/cdrecord");*/
61 /* auinfo("/mnt2/CD3/audio_01.inf");*/
62 auinfo("/mnt2/CD3/audio_01.wav");
63 }
64 #endif
65
66 LOCAL int
auinfopen(name)67 auinfopen(name)
68 char *name;
69 {
70 char infname[1024];
71 char *p;
72
73 strncpy(infname, name, sizeof (infname)-1);
74 infname[sizeof (infname)-1] = '\0';
75 p = strrchr(infname, '.');
76 if (p != 0 && &p[4] < &name[sizeof (infname)]) {
77 strcpy(&p[1], "inf");
78 }
79
80 return (defltopen(infname));
81 }
82
83 EXPORT BOOL
auinfosize(name,trackp)84 auinfosize(name, trackp)
85 char *name;
86 track_t *trackp;
87 {
88 const char *p;
89 const char *tlp;
90 struct stat sb;
91 long secs;
92 long nsamples;
93 Llong tracksize;
94
95 if (!is_audio(trackp))
96 return (FALSE);
97
98 if ((trackp->flags & TI_USEINFO) == 0)
99 return (FALSE);
100
101 if ((p = strrchr(name, '.')) == NULL)
102 return (FALSE);
103 if (!streql(p, ".inf") && !streql(p, ".INF"))
104 return (FALSE);
105
106 /*
107 * First check if a bad guy tries to call auinfosize()
108 * while STDIN_FILENO is a TTY.
109 */
110 if (isatty(STDIN_FILENO)) {
111 errmsgno(EX_BAD,
112 _("WARNING: Stdin is connected to a terminal.\n"));
113 return (FALSE);
114 }
115
116 if (stat(name, &sb) < 0) /* *.inf file not found */
117 return (FALSE);
118
119 if (sb.st_size > 10000) /* Too large for a *.inf file */
120 return (FALSE);
121
122 if (defltopen(name) < 0) /* Cannot open *.inf file */
123 return (FALSE);
124
125 tlp = p = readtag("Tracklength=");
126 if (p == NULL) { /* Tracklength= Tag not found */
127 errmsgno(EX_BAD,
128 _("WARNING: %s does not contain a 'Tracklength=' tag.\n"),
129 name);
130 defltclose();
131 return (FALSE);
132 }
133
134 p = astol(p, &secs);
135 if (*p != '\0' && *p != ',') {
136 errmsgno(EX_BAD,
137 _("WARNING: %s: 'Tracklength=' contains illegal parameter '%s'.\n"),
138 name, tlp);
139 defltclose();
140 return (FALSE);
141 }
142 if (*p == ',')
143 p++;
144 p = astol(p, &nsamples);
145 if (*p != '\0') {
146 errmsgno(EX_BAD,
147 _("WARNING: %s: 'Tracklength=' contains illegal parameter '%s'.\n"),
148 name, tlp);
149 defltclose();
150 return (FALSE);
151 }
152 tracksize = (secs * 2352) + (nsamples * 4);
153 if (xdebug > 0) {
154 error(_("%s: Tracksize %lld bytes (%ld sectors, %ld samples)\n"),
155 name, tracksize, secs, nsamples);
156 }
157 trackp->itracksize = tracksize;
158 defltclose();
159 return (TRUE);
160 }
161
162 EXPORT BOOL
auinfhidden(name,track,trackp)163 auinfhidden(name, track, trackp)
164 char *name;
165 int track;
166 track_t *trackp;
167 {
168 char *p;
169 long l;
170 long tr = -1;
171 long tno = -1;
172 BOOL isdao = !is_tao(&trackp[0]);
173
174 if (auinfopen(name) != 0)
175 return (FALSE);
176
177 p = readtag("Track="); /* Track no, first track is 1 */
178 if (p && isdao)
179 astol(p, &tr);
180 if (tr != 0)
181 return (FALSE);
182 p = readtag("Tracknumber="); /* Track no, first track >= 1 */
183 if (p && isdao)
184 astol(p, &tno);
185
186 p = readtag("Trackstart=");
187 if (p && isdao) {
188 l = -1L;
189 astol(p, &l);
190 if (track == 1 && tno == 0 && l == 0)
191 return (TRUE);
192 }
193 return (FALSE);
194 }
195
196 EXPORT void
auinfo(name,track,trackp)197 auinfo(name, track, trackp)
198 char *name;
199 int track;
200 track_t *trackp;
201 {
202 char *p;
203 track_t *tp = &trackp[track];
204 textptr_t *txp;
205 long l;
206 long tr = -1;
207 long tno = -1;
208 BOOL isdao = !is_tao(&trackp[0]);
209
210 if (auinfopen(name) != 0)
211 return;
212
213 p = readtstr("CDINDEX_DISCID=");
214 p = readtag("CDDB_DISKID=");
215
216 p = readtag("MCN=");
217 if (p && *p) {
218 setmcn(p, &trackp[0]);
219 txp = gettextptr(0, trackp); /* MCN is isrc for trk 0*/
220 txp->tc_isrc = savestr(p);
221 }
222
223 p = readtag("ISRC=");
224 if (p && *p && track > 0) {
225 setisrc(p, &trackp[track]);
226 txp = gettextptr(track, trackp);
227 txp->tc_isrc = savestr(p);
228 }
229
230 p = readtstr("Albumperformer=");
231 if (p && *p) {
232 txp = gettextptr(0, trackp); /* Album perf. in trk 0*/
233 txp->tc_performer = savestr(p);
234 }
235 p = readtstr("Performer=");
236 if (p && *p && track > 0) {
237 txp = gettextptr(track, trackp);
238 txp->tc_performer = savestr(p);
239 }
240 p = readtstr("Albumtitle=");
241 if (p && *p) {
242 txp = gettextptr(0, trackp); /* Album title in trk 0*/
243 txp->tc_title = savestr(p);
244 }
245 p = readtstr("Tracktitle=");
246 if (p && *p && track > 0) {
247 txp = gettextptr(track, trackp);
248 txp->tc_title = savestr(p);
249 }
250 p = readtstr("Albumsongwriter=");
251 if (p && *p) {
252 txp = gettextptr(0, trackp);
253 txp->tc_songwriter = savestr(p);
254 }
255 p = readtstr("Songwriter=");
256 if (p && *p && track > 0) {
257 txp = gettextptr(track, trackp);
258 txp->tc_songwriter = savestr(p);
259 }
260 p = readtstr("Albumcomposer=");
261 if (p && *p) {
262 txp = gettextptr(0, trackp);
263 txp->tc_composer = savestr(p);
264 }
265 p = readtstr("Composer=");
266 if (p && *p && track > 0) {
267 txp = gettextptr(track, trackp);
268 txp->tc_composer = savestr(p);
269 }
270 p = readtstr("Albumarranger=");
271 if (p && *p) {
272 txp = gettextptr(0, trackp);
273 txp->tc_arranger = savestr(p);
274 }
275 p = readtstr("Arranger=");
276 if (p && *p && track > 0) {
277 txp = gettextptr(track, trackp);
278 txp->tc_arranger = savestr(p);
279 }
280 p = readtstr("Albummessage=");
281 if (p && *p) {
282 txp = gettextptr(0, trackp);
283 txp->tc_message = savestr(p);
284 }
285 p = readtstr("Message=");
286 if (p && *p && track > 0) {
287 txp = gettextptr(track, trackp);
288 txp->tc_message = savestr(p);
289 }
290 p = readtstr("Diskid=");
291 if (p && *p) {
292 txp = gettextptr(0, trackp); /* Disk id is in trk 0*/
293 txp->tc_diskid = savestr(p);
294 }
295 p = readtstr("Albumclosed_info=");
296 if (p && *p) {
297 txp = gettextptr(0, trackp);
298 txp->tc_closed_info = savestr(p);
299 }
300 p = readtstr("Closed_info=");
301 if (p && *p && track > 0) {
302 txp = gettextptr(track, trackp);
303 txp->tc_closed_info = savestr(p);
304 }
305
306 p = readtag("Track="); /* Track no, first track is 1 */
307 if (p && isdao)
308 astol(p, &tr);
309 p = readtag("Tracknumber="); /* Track no, first track >= 1 */
310 if (p && isdao)
311 astol(p, &tno);
312 if (tr < 0 && tno > 0) /* Support old inf files */
313 tr = tno;
314
315 p = readtag("Trackstart=");
316 if (p && isdao) {
317 l = -1L;
318 astol(p, &l);
319 if (track == 1 && tr == 1 && l > 0) {
320 trackp[1].pregapsize = 150 + l;
321 printf(_("Track1 Start: '%s' (%ld)\n"), p, l);
322 }
323 }
324
325 p = readtag("Tracklength=");
326
327 p = readtag("Pre-emphasis=");
328 if (p && *p) {
329 if (strncmp(p, "yes", 3) == 0) {
330 tp->flags |= TI_PREEMP;
331 if ((tp->tracktype & TOC_MASK) == TOC_DA)
332 tp->sectype = SECT_AUDIO_PRE;
333
334 } else if (strncmp(p, "no", 2) == 0) {
335 tp->flags &= ~TI_PREEMP;
336 if ((tp->tracktype & TOC_MASK) == TOC_DA)
337 tp->sectype = SECT_AUDIO_NOPRE;
338 }
339 }
340
341 p = readtag("Channels=");
342 p = readtag("Copy_permitted=");
343 if (p && *p) {
344 /*
345 * -useinfo always wins
346 */
347 tp->flags &= ~(TI_COPY|TI_SCMS);
348
349 if (strncmp(p, "yes", 3) == 0)
350 tp->flags |= TI_COPY;
351 else if (strncmp(p, "no", 2) == 0)
352 tp->flags |= TI_SCMS;
353 else if (strncmp(p, "once", 2) == 0)
354 tp->flags &= ~(TI_COPY|TI_SCMS);
355 }
356 p = readtag("Endianess=");
357 p = readtag("Index=");
358 if (p && *p && isdao)
359 setindex(p, &trackp[track]);
360
361 p = readtag("Index0=");
362 if (p && isdao) {
363 Llong ts;
364 Llong ps;
365
366 l = -2L;
367 astol(p, &l);
368 if (l == -1) {
369 trackp[track+1].pregapsize = 0;
370 } else if (l > 0) {
371 ts = tp->itracksize / tp->isecsize;
372 ps = ts - l;
373 if (ps > 0)
374 trackp[track+1].pregapsize = ps;
375 }
376 }
377 }
378
379 EXPORT textptr_t *
gettextptr(track,trackp)380 gettextptr(track, trackp)
381 int track;
382 track_t *trackp;
383 {
384 register textptr_t *txp;
385
386 txp = (textptr_t *)trackp[track].text;
387 if (txp == NULL) {
388 txp = malloc(sizeof (textptr_t));
389 if (txp == NULL)
390 comerr(_("Cannot malloc CD-Text structure.\n"));
391 fillbytes(txp, sizeof (textptr_t), '\0');
392 trackp[track].text = txp;
393 }
394 return (txp);
395 }
396
397 LOCAL char *
savestr(str)398 savestr(str)
399 char *str;
400 {
401 char *ret;
402
403 ret = malloc(strlen(str)+1);
404 if (ret)
405 strcpy(ret, str);
406 else
407 comerr(_("Cannot malloc auinfo string.\n"));
408 return (ret);
409 }
410
411 LOCAL char *
readtag(name)412 readtag(name)
413 char *name;
414 {
415 register char *p;
416
417 p = defltread(name);
418 if (p) {
419 while (*p == ' ' || *p == '\t')
420 p++;
421 if (debug)
422 printf("%s '%s'\n", name, p);
423 }
424 return (p);
425 }
426
427 LOCAL char *
readtstr(name)428 readtstr(name)
429 char *name;
430 {
431 register char *p;
432 register char *p2;
433
434 p = readtag(name);
435 if (p && *p == '\'') {
436 p2 = ++p;
437 while (*p2 != '\0')
438 p2++;
439 while (p2 > p && *p2 != '\'')
440 p2--;
441 *p2 = '\0';
442 if (debug)
443 printf("%s '%s'\n", name, p);
444 }
445 return (p);
446 }
447
448 /*
449 * Media catalog number is a 13 digit number.
450 */
451 EXPORT void
setmcn(mcn,trackp)452 setmcn(mcn, trackp)
453 char *mcn;
454 track_t *trackp;
455 {
456 register char *p;
457
458 if (strlen(mcn) != 13)
459 comerrno(EX_BAD, _("MCN '%s' has illegal length.\n"), mcn);
460
461 for (p = mcn; *p; p++) {
462 if (*p < '0' || *p > '9')
463 comerrno(EX_BAD, _("MCN '%s' contains illegal character '%c'.\n"), mcn, *p);
464 }
465 p = malloc(14);
466 strcpy(p, mcn);
467 trackp->isrc = p;
468
469 if (debug)
470 printf(_("Track %d MCN: '%s'\n"), (int)trackp->trackno, trackp->isrc);
471 }
472
473 LOCAL char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
474
475 LOCAL void
isrc_illchar(isrc,c)476 isrc_illchar(isrc, c)
477 char *isrc;
478 int c;
479 {
480 errmsgno(EX_BAD, _("ISRC '%s' contains illegal character '%c'.\n"), isrc, c);
481 }
482
483 /*
484 * ISRC is 12 Byte:
485 *
486 * Country code 'C' (alpha) 2 Bytes
487 * Owner code 'O' (alphanumeric) 3 Bytes
488 * Year of record 'Y' (numeric) 2 Bytes
489 * Serial number 'S' (numeric) 5 Bytes
490 *
491 * CC-OOO-YY-SSSSS
492 */
493 EXPORT void
setisrc(isrc,trackp)494 setisrc(isrc, trackp)
495 char *isrc;
496 track_t *trackp;
497 {
498 char ibuf[13];
499 char *ip;
500 char *p;
501 int i;
502 int len;
503
504 if ((len = strlen(isrc)) != 12) {
505 for (p = isrc, i = 0; *p; p++) {
506 if (*p == '-')
507 i++;
508 }
509 if (((len - i) != 12) || i > 3)
510 comerrno(EX_BAD, _("ISRC '%s' has illegal length.\n"), isrc);
511 }
512
513 /*
514 * The country code.
515 */
516 for (p = isrc, ip = ibuf, i = 0; i < 2; p++, i++) {
517 *ip++ = *p;
518 if (!strchr(upper, *p)) {
519 /* goto illchar;*/
520 /*
521 * Flag numbers but accept them.
522 */
523 isrc_illchar(isrc, *p);
524 if (*p >= '0' && *p <= '9')
525 continue;
526 exit(EX_BAD);
527 }
528 }
529 if (*p == '-')
530 p++;
531
532 /*
533 * The owner code.
534 */
535 for (i = 0; i < 3; p++, i++) {
536 *ip++ = *p;
537 if (strchr(upper, *p))
538 continue;
539 if (*p >= '0' && *p <= '9')
540 continue;
541 goto illchar;
542 }
543 if (*p == '-')
544 p++;
545
546 /*
547 * The Year and the recording number (2 + 5 numbers).
548 */
549 for (i = 0; i < 7; p++, i++) {
550 *ip++ = *p;
551 if (*p >= '0' && *p <= '9')
552 continue;
553 if (*p == '-' && i == 2) {
554 ip--;
555 i--;
556 continue;
557 }
558 goto illchar;
559 }
560 *ip = '\0';
561 p = malloc(13);
562 strcpy(p, ibuf);
563 trackp->isrc = p;
564
565 if (debug)
566 printf(_("Track %d ISRC: '%s'\n"), (int)trackp->trackno, trackp->isrc);
567 return;
568 illchar:
569 isrc_illchar(isrc, *p);
570 exit(EX_BAD);
571 }
572
573 EXPORT void
setindex(tindex,trackp)574 setindex(tindex, trackp)
575 char *tindex;
576 track_t *trackp;
577 {
578 char *p;
579 int i;
580 int nindex;
581 long idx;
582 long *idxlist;
583
584 idxlist = malloc(100*sizeof (long));
585 p = tindex;
586 idxlist[0] = 0;
587 i = 0;
588 while (*p) {
589 p = astol(p, &idx);
590 if (*p != '\0' && *p != ' ' && *p != '\t' && *p != ',')
591 goto illchar;
592 i++;
593 if (i > 99)
594 comerrno(EX_BAD, _("Too many indices for track %d\n"), (int)trackp->trackno);
595 idxlist[i] = idx;
596 if (*p == ',')
597 p++;
598 while (*p == ' ' || *p == '\t')
599 p++;
600 }
601 nindex = i;
602
603 if (debug)
604 printf(_("Track %d %d Index: '%s'\n"), (int)trackp->trackno, i, tindex);
605
606 if (debug) {
607 for (i = 0; i <= nindex; i++)
608 printf("%d: %ld\n", i, idxlist[i]);
609 }
610
611 trackp->nindex = nindex;
612 trackp->tindex = idxlist;
613 return;
614 illchar:
615 comerrno(EX_BAD, _("Index '%s' contains illegal character '%c'.\n"), tindex, *p);
616 }
617