Imported Upstream version 1.1.11
[platform/upstream/cdrkit.git] / wodim / auinfo.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 /* @(#)auinfo.c 1.23 04/03/01 Copyright 1998-2004 J. Schilling */
14 /*
15  *      Copyright (c) 1998-2004 J. Schilling
16  */
17 /*
18  * This program is free software; you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License version 2
20  * as published by the Free Software Foundation.
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License along with
28  * this program; see the file COPYING.  If not, write to the Free Software
29  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30  */
31
32 #include <mconfig.h>
33 #include <stdxlib.h>
34 #include <unixstd.h>
35 #include <statdefs.h>
36 #include <stdio.h>
37 #include <standard.h>
38 #include <strdefs.h>
39 #include <deflts.h>
40 #include <utypes.h>
41 #include <schily.h>
42
43 #include "cdtext.h"
44 #include "wodim.h"
45
46 extern  int     debug;
47 extern  int     xdebug;
48
49 BOOL                    auinfosize(char *name, track_t *trackp);
50 void                    auinfo(char *name, int track, track_t *trackp);
51 textptr_t       *gettextptr(int track, track_t *trackp);
52 static char *savestr(char *name);
53 static char *readtag(char *name);
54 static char *readtstr(char *name);
55 void                    setmcn(char *mcn, track_t *trackp);
56 static void     isrc_illchar(char *isrc, int c);
57 void                    setisrc(char *isrc, track_t *trackp);
58 void                    setindex(char *tindex, track_t *trackp);
59
60 #ifdef  XXX
61 int 
62 main(int argc, char *argv[])
63 {
64 /*      auinfo("/etc/default/cdrecord");*/
65 /*      auinfo("/mnt2/CD3/audio_01.inf");*/
66         auinfo("/mnt2/CD3/audio_01.wav");
67 }
68 #endif
69
70 BOOL 
71 auinfosize(char *name, track_t *trackp)
72 {
73         const   char    *p;
74         const   char    *tlp;
75         struct stat     sb;
76         long            secs;
77         long            nsamples;
78         Llong           tracksize;
79
80         if (!is_audio(trackp))
81                 return (FALSE);
82
83         if ((trackp->flags & TI_USEINFO) == 0)
84                 return (FALSE);
85
86         if ((p = strrchr(name, '.')) == NULL)
87                 return (FALSE);
88         if (!streql(p, ".inf") && !streql(p, ".INF"))
89                 return (FALSE);
90
91         /*
92          * First check if a bad guy tries to call auinfosize()
93          * while STDIN_FILENO is a TTY.
94          */
95         if (isatty(STDIN_FILENO)) {
96                 errmsgno(EX_BAD,
97                         "WARNING: Stdin is connected to a terminal.\n");
98                 return (FALSE);
99         }
100
101         if (stat(name, &sb) < 0)        /* *.inf file not found         */
102                 return (FALSE);
103
104         if (sb.st_size > 10000)         /* Too large for a *.inf file   */
105                 return (FALSE);
106
107         if (cfg_open(name) < 0) /* Cannot open *.inf file       */
108                 return (FALSE);
109
110         tlp = p = readtag("Tracklength");
111         if (p == NULL) {                /* Tracklength= Tag not found   */
112                 errmsgno(EX_BAD,
113                         "WARNING: %s does not contain a 'Tracklength=' tag.\n",
114                         name);
115                 cfg_close();
116                 return (FALSE);
117         }
118
119         p = astol(p, &secs);
120         if (*p != '\0' && *p != ',') {
121                 errmsgno(EX_BAD,
122                         "WARNING: %s: 'Tracklength=' contains illegal parameter '%s'.\n",
123                         name, tlp);
124                 cfg_close();
125                 return (FALSE);
126         }
127         if (*p == ',')
128                 p++;
129         p = astol(p, &nsamples);
130         if (*p != '\0') {
131                 errmsgno(EX_BAD,
132                         "WARNING: %s: 'Tracklength=' contains illegal parameter '%s'.\n",
133                         name, tlp);
134                 cfg_close();
135                 return (FALSE);
136         }
137         tracksize = (secs * 2352) + (nsamples * 4);
138         if (xdebug > 0) {
139                 fprintf(stderr, "%s: Tracksize %lld bytes (%ld sectors, %ld samples)\n",
140                         name, tracksize, secs, nsamples);
141         }
142         trackp->itracksize = tracksize;
143         cfg_close();
144         return (TRUE);
145 }
146
147 void 
148 auinfo(char *name, int track, track_t *trackp)
149 {
150         char    infname[1024];
151         char    *p;
152         track_t *tp = &trackp[track];
153         textptr_t *txp;
154         long    l;
155         long    tno = -1;
156         BOOL    isdao = !is_tao(&trackp[0]);
157
158         strncpy(infname, name, sizeof (infname)-1);
159         infname[sizeof (infname)-1] = '\0';
160         p = strrchr(infname, '.');
161         if (p != 0 && &p[4] < &name[sizeof (infname)]) {
162                 strcpy(&p[1], "inf");
163         }
164
165         if (cfg_open(infname) == 0) {
166
167                 p = readtstr("CDINDEX_DISCID");
168                 p = readtag("CDDB_DISKID");
169
170                 p = readtag("MCN");
171                 if (p && *p) {
172                         setmcn(p, &trackp[0]);
173                         txp = gettextptr(0, trackp); /* MCN is isrc for trk 0*/
174                         txp->tc_isrc = savestr(p);
175                 }
176
177                 p = readtag("ISRC");
178                 if (p && *p) {
179                         setisrc(p, &trackp[track]);
180                         txp = gettextptr(track, trackp);
181                         txp->tc_isrc = savestr(p);
182                 }
183
184                 p = readtstr("Albumperformer");
185                 if (p && *p) {
186                         txp = gettextptr(0, trackp); /* Album perf. in trk 0*/
187                         txp->tc_performer = savestr(p);
188                 }
189                 p = readtstr("Performer");
190                 if (p && *p) {
191                         txp = gettextptr(track, trackp);
192                         txp->tc_performer = savestr(p);
193                 }
194                 p = readtstr("Albumtitle");
195                 if (p && *p) {
196                         txp = gettextptr(0, trackp); /* Album title in trk 0*/
197                         txp->tc_title = savestr(p);
198                 }
199                 p = readtstr("Tracktitle");
200                 if (p && *p) {
201                         txp = gettextptr(track, trackp);
202                         txp->tc_title = savestr(p);
203                 }
204                 p = readtstr("Songwriter");
205                 if (p && *p) {
206                         txp = gettextptr(track, trackp);
207                         txp->tc_songwriter = savestr(p);
208                 }
209                 p = readtstr("Composer");
210                 if (p && *p) {
211                         txp = gettextptr(track, trackp);
212                         txp->tc_composer = savestr(p);
213                 }
214                 p = readtstr("Arranger");
215                 if (p && *p) {
216                         txp = gettextptr(track, trackp);
217                         txp->tc_arranger = savestr(p);
218                 }
219                 p = readtstr("Message");
220                 if (p && *p) {
221                         txp = gettextptr(track, trackp);
222                         txp->tc_message = savestr(p);
223                 }
224                 p = readtstr("Diskid");
225                 if (p && *p) {
226                         txp = gettextptr(0, trackp); /* Disk id is in trk 0*/
227                         txp->tc_title = savestr(p);
228                 }
229                 p = readtstr("Closed_info");
230                 if (p && *p) {
231                         txp = gettextptr(track, trackp);
232                         txp->tc_closed_info = savestr(p);
233                 }
234
235                 p = readtag("Tracknumber");
236                 if (p && isdao)
237                         astol(p, &tno);
238
239                 p = readtag("Trackstart");
240                 if (p && isdao) {
241                         l = -1L;
242                         astol(p, &l);
243                         if (track == 1 && tno == 1 && l > 0) {
244                                 trackp[1].pregapsize = 150 + l;
245                                 printf("Track1 Start: '%s' (%ld)\n", p, l);
246                         }
247                 }
248
249                 p = readtag("Tracklength");
250
251                 p = readtag("Pre-emphasis");
252                 if (p && *p) {
253                         if (strncmp(p, "yes", 3) == 0) {
254                                 tp->flags |= TI_PREEMP;
255                                 if ((tp->tracktype & TOC_MASK) == TOC_DA)
256                                         tp->sectype = SECT_AUDIO_PRE;
257
258                         } else if (strncmp(p, "no", 2) == 0) {
259                                 tp->flags &= ~TI_PREEMP;
260                                 if ((tp->tracktype & TOC_MASK) == TOC_DA)
261                                         tp->sectype = SECT_AUDIO_NOPRE;
262                         }
263                 }
264
265                 p = readtag("Channels");
266                 p = readtag("Copy_permitted");
267                 if (p && *p) {
268                         /*
269                          * -useinfo always wins
270                          */
271                         tp->flags &= ~(TI_COPY|TI_SCMS);
272
273                         if (strncmp(p, "yes", 3) == 0)
274                                 tp->flags |= TI_COPY;
275                         else if (strncmp(p, "no", 2) == 0)
276                                 tp->flags |= TI_SCMS;
277                         else if (strncmp(p, "once", 2) == 0)
278                                 tp->flags &= ~(TI_COPY|TI_SCMS);
279                 }
280                 p = readtag("Endianess");
281                 p = readtag("Index");
282                 if (p && *p && isdao)
283                         setindex(p, &trackp[track]);
284
285                 p = readtag("Index0");
286                 if (p && isdao) {
287                         Llong ts;
288                         Llong ps;
289
290                         l = -2L;
291                         astol(p, &l);
292                         if (l == -1) {
293                                 trackp[track+1].pregapsize = 0;
294                         } else if (l > 0) {
295                                 ts = tp->itracksize / tp->isecsize;
296                                 ps = ts - l;
297                                 if (ps > 0)
298                                         trackp[track+1].pregapsize = ps;
299                         }
300                 }
301         }
302
303 }
304
305 textptr_t *
306 gettextptr(int track, track_t *trackp)
307 {
308         register textptr_t *txp;
309
310         txp = (textptr_t *)trackp[track].text;
311         if (txp == NULL) {
312                 txp = malloc(sizeof (textptr_t));
313                 if (txp == NULL)
314                         comerr("Cannot malloc CD-Text structure.\n");
315                 fillbytes(txp, sizeof (textptr_t), '\0');
316                 trackp[track].text = txp;
317         }
318         return (txp);
319 }
320
321 static char *
322 savestr(char *str)
323 {
324         char    *ret;
325
326         ret = malloc(strlen(str)+1);
327         if (ret)
328                 strcpy(ret, str);
329         else
330                 comerr("Cannot malloc auinfo string.\n");
331         return (ret);
332 }
333
334 static char *
335 readtag(char *name)
336 {
337         register char   *p;
338
339   p = cfg_get(name);
340   if (debug)
341      printf("%s '%s'\n", name, p);
342   return (p);
343 }
344
345 static char *
346 readtstr(char *name)
347 {
348         register char   *p;
349         register char   *p2;
350
351         p = readtag(name);
352         if (p && *p == '\'') {
353                 p2 = ++p;
354                 while (*p2 != '\0')
355                         p2++;
356                 while (p2 > p && *p2 != '\'')
357                         p2--;
358                 *p2 = '\0';
359                 if (debug)
360                         printf("%s      '%s'\n", name, p);
361         }
362         return (p);
363 }
364
365 /*
366  * Media catalog number is a 13 digit number.
367  */
368 void 
369 setmcn(char *mcn, track_t *trackp)
370 {
371         register char   *p;
372
373         if (strlen(mcn) != 13)
374                 comerrno(EX_BAD, "MCN '%s' has illegal length.\n", mcn);
375
376         for (p = mcn; *p; p++) {
377                 if (*p < '0' || *p > '9')
378                         comerrno(EX_BAD, "MCN '%s' contains illegal character '%c'.\n", mcn, *p);
379         }
380         p = malloc(14);
381         strcpy(p, mcn);
382         trackp->isrc = p;
383
384         if (debug)
385                 printf("Track %d MCN: '%s'\n", (int)trackp->trackno, trackp->isrc);
386 }
387
388 static  char    upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
389
390 static void 
391 isrc_illchar(char *isrc, int c)
392 {
393         errmsgno(EX_BAD, "ISRC '%s' contains illegal character '%c'.\n", isrc, c);
394 }
395
396 /*
397  * ISRC is 12 Byte:
398  *
399  *      Country code   'C' (alpha)        2 Bytes
400  *      Owner code     'O' (alphanumeric) 3 Bytes
401  *      Year of record 'Y' (numeric)      2 Bytes
402  *      Serial number  'S' (numeric)      5 Bytes
403  *
404  *      CC-OOO-YY-SSSSS
405  */
406 void 
407 setisrc(char *isrc, track_t *trackp)
408 {
409         char    ibuf[13];
410         char    *ip;
411         char    *p;
412         int     i;
413         int     len;
414
415         if ((len = strlen(isrc)) != 12) {
416                 for (p = isrc, i = 0; *p; p++) {
417                         if (*p == '-')
418                                 i++;
419                 }
420                 if (((len - i) != 12) || i > 3)
421                         comerrno(EX_BAD, "ISRC '%s' has illegal length.\n", isrc);
422         }
423
424         /*
425          * The country code.
426          */
427         for (p = isrc, ip = ibuf, i = 0; i < 2; p++, i++) {
428                 *ip++ = *p;
429                 if (!strchr(upper, *p)) {
430 /*                      goto illchar;*/
431                         /*
432                          * Flag numbers but accept them.
433                          */
434                         isrc_illchar(isrc, *p);
435                         if (*p >= '0' && *p <= '9')
436                                 continue;
437                         exit(EX_BAD);
438                 }
439         }
440         if (*p == '-')
441                 p++;
442
443         /*
444          * The owner code.
445          */
446         for (i = 0; i < 3; p++, i++) {
447                 *ip++ = *p;
448                 if (strchr(upper, *p))
449                         continue;
450                 if (*p >= '0' && *p <= '9')
451                         continue;
452                 goto illchar;
453         }
454         if (*p == '-')
455                 p++;
456
457         /*
458          * The Year and the recording number (2 + 5 numbers).
459          */
460         for (i = 0; i < 7; p++, i++) {
461                 *ip++ = *p;
462                 if (*p >= '0' && *p <= '9')
463                         continue;
464                 if (*p == '-' && i == 2) {
465                         ip--;
466                         i--;
467                         continue;
468                 }
469                 goto illchar;
470         }
471         *ip = '\0';
472         p = malloc(13);
473         strcpy(p, ibuf);
474         trackp->isrc = p;
475
476         if (debug)
477                 printf("Track %d ISRC: '%s'\n", (int)trackp->trackno, trackp->isrc);
478         return;
479 illchar:
480         isrc_illchar(isrc, *p);
481         exit(EX_BAD);
482 }
483
484 void 
485 setindex(char *tindex, track_t *trackp)
486 {
487         char    *p;
488         int     i;
489         int     nindex;
490         long    idx;
491         long    *idxlist;
492
493         idxlist = malloc(100*sizeof (long));
494         p = tindex;
495         idxlist[0] = 0;
496         i = 0;
497         while (*p) {
498                 p = astol(p, &idx);
499                 if (*p != '\0' && *p != ' ' && *p != '\t' && *p != ',')
500                         goto illchar;
501                 i++;
502                 if (i > 99)
503                         comerrno(EX_BAD, "Too many indices for track %d\n", (int)trackp->trackno);
504                 idxlist[i] = idx;
505                 if (*p == ',')
506                         p++;
507                 while (*p == ' ' || *p == '\t')
508                         p++;
509         }
510         nindex = i;
511
512         if (debug)
513                 printf("Track %d %d Index: '%s'\n", (int)trackp->trackno, i, tindex);
514
515         if (debug) {
516                 for (i = 0; i <= nindex; i++)
517                         printf("%d: %ld\n", i, idxlist[i]);
518         }
519
520         trackp->nindex = nindex;
521         trackp->tindex = idxlist;
522         return;
523 illchar:
524         comerrno(EX_BAD, "Index '%s' contains illegal character '%c'.\n", tindex, *p);
525 }