1 /*
2 * cdinfo - CD Information Management Library
3 *
4 * Copyright (C) 1993-2004 Ti Kan
5 * E-mail: xmcd@amb.org
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 */
22 #ifndef lint
23 static char *_cdinfo_i_c_ident_ = "@(#)cdinfo_i.c 7.190 04/04/20";
24 #endif
25
26 #ifdef __VMS
27 typedef char * caddr_t;
28 #endif
29
30 #define _CDINFO_INTERN /* Expose internal function protos in cdinfo.h */
31 #define XMCD_CDDB /* Enable correct includes in CDDB2API.h */
32
33 #include "common_d/appenv.h"
34 #include "common_d/version.h"
35 #include "common_d/util.h"
36 #include "libdi_d/libdi.h"
37 #include "cdda_d/cdda.h"
38 #include "cdinfo_d/cdinfo.h"
39 #include "cddb_d/CDDB2API.h"
40 #if defined(_AIX) || defined(__QNX__)
41 #include <sys/select.h>
42 #endif
43
44
45 /* Time interval to run workproc while waiting for I/O */
46 #define CDINFO_WAIT_SEC 0
47 #define CDINFO_WAIT_USEC 200000
48
49
50 extern appdata_t app_data;
51 extern FILE *errfp;
52
53 /* Internal data not to be used outside of libcdinfo */
54 cdinfo_client_t *cdinfo_clinfo; /* Client info */
55 cdinfo_incore_t *cdinfo_dbp; /* In core CD info struct */
56 cdinfo_cddb_t *cdinfo_cddbp; /* Opened CDDB handle */
57 w_ent_t *cdinfo_discog, /* Local discog menu ptr */
58 *cdinfo_scddb; /* Search CDDB menu ptr */
59 bool_t cdinfo_ischild; /* Is a child process */
60
61 STATIC bool_t cdinfo_ctrl_initted = FALSE,
62 /* CDDB ctrl initialized */
63 cdinfo_genurl_initted = FALSE,
64 /* Gen URLs list initialized */
65 cdinfo_glist_initted = FALSE,
66 /* Genre list initialized */
67 cdinfo_relist_initted = FALSE,
68 /* Region list initialized */
69 cdinfo_langlist_initted = FALSE,
70 /* Language list initialized */
71 cdinfo_rolist_initted = FALSE,
72 /* Role list initialized */
73 cdinfo_user_regd = FALSE;
74 /* User registered */
75
76 /* Data structure used for checking wwwwarp.cfg entries */
77 typedef struct w_entchk {
78 w_ent_t *ent;
79 struct w_entchk *next;
80 } w_entchk_t;
81
82 STATIC w_entchk_t *cdinfo_wentchk_head = NULL;
83
84
85 /* Data structure for play lists */
86 typedef struct playls {
87 char *path; /* File path string */
88 struct playls *prev; /* List link pointer */
89 struct playls *next; /* List link pointer */
90 struct playls *prev2; /* Sorted list link pointer */
91 struct playls *next2; /* Sorted list link pointer */
92 } playls_t;
93
94
95 /* CDDB1 to CDDB2 genre mapping table - This assumes that the
96 * CDDB2 genre ID is invariant.
97 */
98 struct {
99 char *cddb1_genre; /* CDDB1 category name */
100 char *cddb2_genre; /* CDDB2 genre ID */
101 } cdinfo_genre_map[] = {
102 { "blues", "32" /* Blues -> General Blues */ },
103 { "classical", "46" /* Classical -> General Classical */ },
104 { "country", "60" /* Country -> General Country */ },
105 { "data", "71" /* Data -> General Data */ },
106 { "folk", "96" /* Folk -> General Folk */ },
107 { "jazz", "160" /* Jazz -> General Jazz */ },
108 { "misc", "221" /* Unclassifiable -> General Unclass */ },
109 { "newage", "169" /* New Age -> General New Age */ },
110 { "reggae", "246" /* Reggae -> General Reggae */ },
111 { "rock", "191" /* Rock -> General Rock */ },
112 { "soundtrack", "214" /* Sountrack -> General Soundtrack */ },
113 { "unclass", "221" /* Unclassifiable -> General Unclass */ },
114 { NULL, NULL }
115 };
116
117
118 /***********************
119 * internal routines *
120 ***********************/
121
122
123 /*
124 * cdinfo_line_filter
125 * Given a string, process it such that becomes only one
126 * single line (i.e., filter out all text including and
127 * following any newline character). A newline character
128 * is denotes as the characters '\' and 'n' (NOT '\n').
129 * Used for handling local CD info file data.
130 *
131 * Arg:
132 * str - The string to be processed
133 *
134 * Return:
135 * Nothing. The input string may be modified.
136 */
137 STATIC void
cdinfo_line_filter(char * str)138 cdinfo_line_filter(char *str)
139 {
140 if (str == NULL)
141 return;
142
143 for (; *str != '\0'; str++) {
144 if (*str == '\\' && *(str+1) == 'n') {
145 *str = '\0';
146 break;
147 }
148 }
149 }
150
151
152 /*
153 * cdinfo_concatstr
154 * Concatenate two text strings with special handling for newline
155 * and tab character translations. s1 will be dynamically allocated
156 * or reallocated as needed, and must not point to statically-allocated
157 * or stack space. Used for handling local CD info file data.
158 *
159 * Args:
160 * s1 - Location of the pointer to the first text string.
161 * s2 - The second text string.
162 *
163 * Return:
164 * TRUE - success
165 * FALSE - failure
166 */
167 STATIC bool_t
cdinfo_concatstr(char ** s1,char * s2)168 cdinfo_concatstr(char **s1, char *s2)
169 {
170 int n;
171 char *str;
172 bool_t proc_slash;
173
174 if (s1 == NULL || s2 == NULL)
175 return FALSE;
176
177 if (*s1 == NULL) {
178 *s1 = (char *) MEM_ALLOC("s1", strlen(s2) + 1);
179 if (*s1 != NULL)
180 *s1[0] = '\0';
181 }
182 else {
183 *s1 = (char *) MEM_REALLOC("s1", *s1,
184 strlen(*s1) + strlen(s2) + 1);
185 }
186 if (*s1 == NULL)
187 return FALSE;
188
189 /* Concatenate the two strings, with special handling for newline
190 * and tab characters.
191 */
192 str = *s1;
193 proc_slash = FALSE;
194 n = strlen(str);
195 str += n;
196
197 if (n > 0 && *(str - 1) == '\\') {
198 proc_slash = TRUE; /* Handle broken escape sequences */
199 str--;
200 }
201
202 for (; *s2 != '\0'; str++, s2++) {
203 if (*s2 == '\\') {
204 if (proc_slash) {
205 proc_slash = FALSE;
206 continue;
207 }
208 proc_slash = TRUE;
209 s2++;
210 }
211
212 if (proc_slash) {
213 proc_slash = FALSE;
214
215 switch (*s2) {
216 case 'n':
217 *str = '\n';
218 break;
219 case 't':
220 *str = '\t';
221 break;
222 case '\\':
223 *str = '\\';
224 break;
225 case '\0':
226 *str = '\\';
227 s2--;
228 break;
229 default:
230 *str++ = '\\';
231 *str = *s2;
232 break;
233 }
234 }
235 else
236 *str = *s2;
237 }
238 *str = '\0';
239
240 return TRUE;
241 }
242
243
244 /*
245 * cdinfo_sort_playlist
246 * Given a linked list of playls_t structures, sort them
247 * alphabetically based on the path field. The sorted list head
248 * is returned. The original list links are not modified.
249 * To traverse the sorted list, use returned listhead and follow the
250 * next2 pointers of the playls_t structure.
251 *
252 * Args:
253 * listhead - The original playlist head pointer.
254 *
255 * Return:
256 * The sorted playlist head pointer.
257 */
258 STATIC playls_t *
cdinfo_sort_playlist(playls_t * listhead)259 cdinfo_sort_playlist(playls_t *listhead)
260 {
261 playls_t *hp,
262 *sp,
263 *sp2;
264
265 for (sp = hp = listhead; sp != NULL; sp = sp->next) {
266 for (sp2 = hp; sp2 != NULL; sp2 = sp2->next2) {
267 if (sp == sp2)
268 continue;
269
270 if (strcmp(sp->path, sp2->path) > 0)
271 continue;
272
273 sp->prev2 = sp2->prev2;
274 sp->next2 = sp2;
275
276 if (sp2 == hp)
277 hp = sp;
278 else
279 sp2->prev2->next2 = sp;
280
281 break;
282 }
283 }
284
285 return (hp);
286 }
287
288
289 /*
290 * cdinfo_onterm
291 * Signal handler for SIGTERM
292 *
293 * Args:
294 * signo - The signal number
295 *
296 * Return:
297 * Nothing.
298 */
299 void
cdinfo_onterm(int signo)300 cdinfo_onterm(int signo)
301 {
302 (void) util_signal(signo, SIG_IGN);
303 DBGPRN(DBG_CDI)(errfp, "\ncdinfo_onterm: SIGTERM received\n");
304
305 /* Close CDDB connection if necessary */
306 if (cdinfo_cddbp != NULL)
307 cdinfo_closecddb(cdinfo_cddbp);
308 _exit(0);
309 }
310
311
312 /*
313 * cdinfo_sum
314 * Convert an integer to its text string representation, and
315 * compute its checksum. Used by cdinfo_discid.
316 *
317 * Args:
318 * n - The integer value.
319 *
320 * Return:
321 * The integer checksum.
322 */
323 int
cdinfo_sum(int n)324 cdinfo_sum(int n)
325 {
326 int ret;
327
328 /* For backward compatibility this algorithm must not change */
329 for (ret = 0; n > 0; n /= 10)
330 ret += n % 10;
331
332 return (ret);
333 }
334
335
336 /*
337 * cdinfo_free_glist
338 * Deallocate genre list.
339 *
340 * Args:
341 * None
342 *
343 * Return:
344 * Nothing
345 */
346 STATIC void
cdinfo_free_glist(void)347 cdinfo_free_glist(void)
348 {
349 cdinfo_genre_t *p,
350 *q,
351 *a,
352 *b;
353
354 for (p = q = cdinfo_dbp->genrelist; p != NULL; p = q) {
355 q = p->next;
356
357 if (p->id != NULL)
358 MEM_FREE(p->id);
359 if (p->name != NULL)
360 MEM_FREE(p->name);
361
362 for (a = b = p->child; a != NULL; a = b) {
363 b = a->next;
364
365 if (a->id != NULL)
366 MEM_FREE(a->id);
367 if (a->name != NULL)
368 MEM_FREE(a->name);
369
370 MEM_FREE(a);
371 }
372
373 MEM_FREE(p);
374 }
375
376 cdinfo_dbp->genrelist = NULL;
377 }
378
379
380 /*
381 * cdinfo_free_relist
382 * Deallocate region list.
383 *
384 * Args:
385 * None
386 *
387 * Return:
388 * Nothing
389 */
390 STATIC void
cdinfo_free_relist(void)391 cdinfo_free_relist(void)
392 {
393 cdinfo_region_t *p,
394 *q;
395
396 for (p = q = cdinfo_dbp->regionlist; p != NULL; p = q) {
397 q = p->next;
398
399 if (p->id != NULL)
400 MEM_FREE(p->id);
401 if (p->name != NULL)
402 MEM_FREE(p->name);
403
404 MEM_FREE(p);
405 }
406 cdinfo_dbp->regionlist = NULL;
407 }
408
409
410 /*
411 * cdinfo_free_langlist
412 * Deallocate language list.
413 *
414 * Args:
415 * None
416 *
417 * Return:
418 * Nothing
419 */
420 STATIC void
cdinfo_free_langlist(void)421 cdinfo_free_langlist(void)
422 {
423 cdinfo_lang_t *p,
424 *q;
425
426 for (p = q = cdinfo_dbp->langlist; p != NULL; p = q) {
427 q = p->next;
428
429 if (p->id != NULL)
430 MEM_FREE(p->id);
431 if (p->name != NULL)
432 MEM_FREE(p->name);
433
434 MEM_FREE(p);
435 }
436 cdinfo_dbp->langlist = NULL;
437 }
438
439
440 /*
441 * cdinfo_free_rolist
442 * Deallocate role list.
443 *
444 * Args:
445 * None
446 *
447 * Return:
448 * Nothing
449 */
450 STATIC void
cdinfo_free_rolist(void)451 cdinfo_free_rolist(void)
452 {
453 cdinfo_role_t *p,
454 *q,
455 *a,
456 *b;
457
458 for (p = q = cdinfo_dbp->rolelist; p != NULL; p = q) {
459 q = p->next;
460
461 if (p->id != NULL)
462 MEM_FREE(p->id);
463 if (p->name != NULL)
464 MEM_FREE(p->name);
465
466 for (a = b = p->child; a != NULL; a = b) {
467 b = a->next;
468 if (a->id != NULL)
469 MEM_FREE(a->id);
470 if (a->name != NULL)
471 MEM_FREE(a->name);
472 MEM_FREE(a);
473 }
474
475 MEM_FREE(p);
476 }
477
478 cdinfo_dbp->rolelist = NULL;
479 }
480
481
482 /*
483 * cdinfo_set_errstr
484 * Set the error message string in the incore structure based on the
485 * CDDB service result code.
486 *
487 * Args:
488 * code - The CDDB result code
489 *
490 * Return:
491 * Nothing
492 */
493 /*ARGSUSED*/
494 STATIC void
cdinfo_set_errstr(CddbResult code)495 cdinfo_set_errstr(CddbResult code)
496 {
497 if (code == Cddb_OK)
498 return;
499
500 if (cdinfo_dbp->cddb_errstr != NULL)
501 MEM_FREE(cdinfo_dbp->cddb_errstr);
502
503 cdinfo_dbp->cddb_errstr = (char *) MEM_ALLOC(
504 "CddbErrorString", ERR_BUF_SZ
505 );
506 if (cdinfo_dbp->cddb_errstr == NULL)
507 return;
508
509 cdinfo_dbp->cddb_errstr[0] = '\0';
510
511 CddbGetErrorString(code, cdinfo_dbp->cddb_errstr, ERR_BUF_SZ);
512
513 if (cdinfo_dbp->cddb_errstr[0] == '\0') {
514 MEM_FREE(cdinfo_dbp->cddb_errstr);
515 cdinfo_dbp->cddb_errstr = NULL;
516 }
517 else {
518 DBGPRN(DBG_CDI)(errfp, "%s\n", cdinfo_dbp->cddb_errstr);
519 }
520 }
521
522
523 #ifndef SYNCHRONOUS
524
525 /*
526 * cdinfo_waitio
527 * Check if read data is pending. If no data and a workproc is
528 * specified, then call workproc. Keep waiting until there is
529 * data or until timeout.
530 *
531 * Args:
532 * pp - Pointer to the cdinfo_pipe_t structure
533 * tmout - Timeout interval (in seconds). If set to 0, no
534 * timeout will occur.
535 *
536 * Return:
537 * TRUE - There is data pending.
538 */
539 STATIC bool_t
cdinfo_waitio(cdinfo_pipe_t * pp,int tmout)540 cdinfo_waitio(cdinfo_pipe_t *pp, int tmout)
541 {
542 int ret;
543 fd_set rfds;
544 fd_set efds;
545 struct timeval to;
546 time_t start = 0,
547 now;
548
549 if (tmout > 0)
550 start = time(NULL);
551
552 do {
553 errno = 0;
554 FD_ZERO(&efds);
555 FD_ZERO(&rfds);
556 FD_SET(pp->r.fd, &rfds);
557
558 to.tv_sec = CDINFO_WAIT_SEC;
559 to.tv_usec = CDINFO_WAIT_USEC;
560 #ifdef __hpux
561 ret = select(pp->r.fd+1, (int *) &rfds,
562 NULL, (int *) &efds, &to);
563 #else
564 ret = select(pp->r.fd+1, &rfds, NULL, &efds, &to);
565 #endif
566
567 if (tmout > 0 && ret == 0) {
568 now = time(NULL);
569 if ((now - start) > tmout) {
570 /* Timeout */
571 DBGPRN(DBG_CDI)(errfp,
572 "Timed out waiting for data.\n");
573 errno = ETIME;
574 ret = -1;
575 }
576 }
577
578 if (ret == 0 && !cdinfo_ischild &&
579 cdinfo_clinfo->workproc != NULL)
580 cdinfo_clinfo->workproc(cdinfo_clinfo->arg);
581
582 } while (ret == 0);
583
584 /* Hack: some implementations of select() does not work
585 * on non-socket file descriptors, so just fake a
586 * success status.
587 */
588 return TRUE;
589 }
590
591
592 /*
593 * cdinfo_getc
594 * Return a character from the file stream. Perform buffered
595 * read from file if necessary.
596 *
597 * Args:
598 * pp - Pointer to the cdinfo_pipe_t structure.
599 *
600 * Return:
601 * The character, or -1 on EOF or failure.
602 */
603 STATIC int
cdinfo_getc(cdinfo_pipe_t * pp)604 cdinfo_getc(cdinfo_pipe_t *pp)
605 {
606 static int i = 0;
607
608 /* Do some work every 10 characters read */
609 if (!cdinfo_ischild && (i % 10) == 0 &&
610 cdinfo_clinfo->workproc != NULL)
611 cdinfo_clinfo->workproc(cdinfo_clinfo->arg);
612
613 if (++i > 100)
614 i = 0; /* Reset count */
615
616 if (pp->r.cache == NULL) {
617 /* Allocate read cache */
618 pp->r.cache = (unsigned char *) MEM_ALLOC(
619 "read_cache", CDINFO_CACHESZ
620 );
621 if (pp->r.cache == NULL)
622 return -1;
623 }
624
625 if (pp->r.pos == pp->r.cnt) {
626 /* Wait for data */
627 if (!cdinfo_waitio(pp, 0))
628 return -1;
629
630 /* Load cache */
631 pp->r.cnt = read(pp->r.fd, pp->r.cache, CDINFO_CACHESZ);
632 if (pp->r.cnt <= 0) {
633 pp->r.cnt = pp->r.pos;
634 return -1;
635 }
636 pp->r.pos = 1;
637 }
638 else {
639 pp->r.pos++;
640 }
641
642 return ((int) pp->r.cache[pp->r.pos - 1]);
643 }
644
645
646 /*
647 * cdinfo_gets
648 * Read a line of text from the stream. The read terminates
649 * when it encounters a newline character, EOF, or if len
650 * characters have been read.
651 *
652 * Args:
653 * pp - The pipe descriptor obtained via cdinfo_openpipe()
654 * buf - Pointer to return string buffer
655 * len - Maximum number of characters to read
656 *
657 * Return:
658 * TRUE - Successfully read a line of text
659 * FALSE - Reached EOF or read failure
660 */
661 STATIC bool_t
cdinfo_gets(cdinfo_pipe_t * pp,char * buf,int len)662 cdinfo_gets(cdinfo_pipe_t *pp, char *buf, int len)
663 {
664 int tot = 0,
665 c = 0;
666
667 while ((c = cdinfo_getc(pp)) > 0) {
668 *buf = (char) c;
669
670 tot++;
671 buf++;
672 len--;
673
674 if (c == '\n') {
675 /* Translate CR-LF into just LF */
676 if (*(buf-2) == '\r') {
677 *(buf-2) = '\n';
678 *(buf-1) = '\0';
679 tot--;
680 buf--;
681 }
682 break;
683 }
684
685 if (len <= 0)
686 break;
687 }
688 *buf = '\0';
689 return ((bool_t) (tot > 0));
690 }
691
692
693 /*
694 * cdinfo_puts
695 * Write a text string into the pipe.
696 *
697 * Args:
698 * pp - The pipe descriptor obtained via cdinfo_openpipe()
699 * buf - Pointer to string buffer
700 *
701 * Return:
702 * TRUE - Success
703 * FALSE - Failure
704 */
705 STATIC bool_t
cdinfo_puts(cdinfo_pipe_t * pp,char * buf)706 cdinfo_puts(cdinfo_pipe_t *pp, char *buf)
707 {
708 char prevchar;
709 bool_t done;
710
711 if (buf == NULL)
712 return FALSE;
713
714 if (pp->w.cache == NULL) {
715 /* Allocate write cache */
716 pp->w.cache = (unsigned char *) MEM_ALLOC(
717 "write_cache", CDINFO_CACHESZ
718 );
719 if (pp->w.cache == NULL)
720 return FALSE;
721 }
722
723 prevchar = '\0';
724 done = FALSE;
725
726 while (!done) {
727 if (*buf == '\0') {
728 /* Insert a newline at end of string if the
729 * string doesn't already have one
730 */
731 if (prevchar != '\n')
732 buf = "\n";
733 else
734 break;
735 }
736
737 if (pp->w.pos == CDINFO_CACHESZ) {
738 unsigned char *p;
739 int resid,
740 n = 0;
741
742 /* Flush write cache */
743 p = pp->w.cache;
744 for (resid = pp->w.pos; resid > 0; resid -= n) {
745 if ((n = write(pp->w.fd, p, resid)) < 0) {
746 pp->w.pos = 0;
747 return FALSE;
748 }
749 p += n;
750 }
751 pp->w.pos = 0;
752 }
753
754 pp->w.cache[pp->w.pos] = (unsigned char) *buf;
755 pp->w.pos++;
756 prevchar = *buf;
757 buf++;
758 }
759
760 return TRUE;
761 }
762
763
764 /*
765 * cdinfo_getline
766 * Read a line from pipe buffer and allocate data structure element
767 * to store the data. This version is used for single-line character
768 * string elements.
769 *
770 * Args:
771 * pp - Pointer to cdinfo_pipe_t
772 * name - Name of element
773 * ptr - Incore CD info structure element location
774 *
775 * Return:
776 * TRUE - success
777 * FALSE - failure
778 */
779 /*ARGSUSED*/
780 STATIC bool_t
cdinfo_getline(cdinfo_pipe_t * pp,char * name,char ** ptr)781 cdinfo_getline(cdinfo_pipe_t *pp, char *name, char **ptr)
782 {
783 size_t n;
784 bool_t ret = FALSE;
785 static char buf[2048];
786
787 while ((ret = cdinfo_gets(pp, buf, sizeof(buf))) == TRUE) {
788 if (buf[0] == '\n')
789 /* Null string */
790 return TRUE;
791
792 n = strlen(buf);
793
794 if (buf[n-1] == '\n') {
795 buf[n-1] = '\0'; /* Zap newline */
796 ret = TRUE;
797 }
798 else
799 ret = FALSE;
800
801 if (*ptr == NULL) {
802 *ptr = (char *) MEM_ALLOC(name, n + 1);
803 if (*ptr != NULL)
804 *ptr[0] = '\0';
805 }
806 else {
807 *ptr = (char *) MEM_REALLOC(name, *ptr,
808 strlen(*ptr) + n + 1);
809 }
810
811 if (*ptr == NULL) {
812 CDINFO_FATAL(app_data.str_nomemory);
813 return FALSE;
814 }
815 (void) strcat(*ptr, buf);
816
817 if (ret)
818 break;
819 }
820
821 return (ret);
822 }
823
824
825 /*
826 * cdinfo_getmultiline
827 * Read lines from pipe buffer and allocate data structure
828 * element to store the data. This version is used for multi-line
829 * character string elements.
830 *
831 * Args:
832 * pp - Pointer to cdinfo_pipe_t
833 * name - Name of element
834 * ptr - Incore CD info structure element location
835 *
836 * Return:
837 * TRUE - success
838 * FALSE - failure
839 */
840 /*ARGSUSED*/
841 STATIC bool_t
cdinfo_getmultiline(cdinfo_pipe_t * pp,char * name,char ** ptr)842 cdinfo_getmultiline(cdinfo_pipe_t *pp, char *name, char **ptr)
843 {
844 bool_t ret;
845 char *cp;
846 static char buf[2048];
847
848 while ((ret = cdinfo_gets(pp, buf, sizeof(buf))) == TRUE) {
849 if (strncmp(buf, XMCD_PIPESIG, strlen(XMCD_PIPESIG)) == 0) {
850 /* End of multi-line */
851 if (*ptr != NULL) {
852 /* Zap the last newline */
853 cp = *ptr + strlen(*ptr) - 1;
854 if (*cp == '\n')
855 *cp = '\0';
856 }
857 break;
858 }
859
860 if (*ptr == NULL) {
861 *ptr = (char *) MEM_ALLOC(name, strlen(buf) + 1);
862 if (*ptr != NULL)
863 *ptr[0] = '\0';
864 }
865 else {
866 *ptr = (char *) MEM_REALLOC(name, *ptr,
867 strlen(*ptr) +
868 strlen(buf) + 1);
869 }
870
871 if (*ptr == NULL) {
872 CDINFO_FATAL(app_data.str_nomemory);
873 return FALSE;
874 }
875 (void) strcat(*ptr, buf);
876 }
877
878 return (ret);
879 }
880
881
882 /*
883 * cdinfo_geturl_ents
884 * Read URL elements from pipe, used by the parent.
885 *
886 * Args:
887 * pp - Pointer to cdinfo_pipe_t
888 * key - match element key string
889 *
890 * Return:
891 * TRUE - success
892 * FALSE - failure
893 */
894 STATIC bool_t
cdinfo_geturl_ents(cdinfo_pipe_t * pp,char * key)895 cdinfo_geturl_ents(cdinfo_pipe_t *pp, char *key)
896 {
897 static cdinfo_url_t *p,
898 *q = NULL;
899
900 if (strcmp(key, ".gen.new") == 0) {
901 p = (cdinfo_url_t *)(void *) MEM_ALLOC("cdinfo_url_t",
902 sizeof(cdinfo_url_t)
903 );
904 if (p == NULL) {
905 CDINFO_FATAL(app_data.str_nomemory);
906 return FALSE;
907 }
908 (void) memset(p, 0, sizeof(cdinfo_url_t));
909
910 p->wtype = WTYPE_GEN;
911
912 if (cdinfo_dbp->gen_url_list == NULL)
913 cdinfo_dbp->gen_url_list = q = p;
914 else {
915 q->next = p;
916 q = p;
917 }
918
919 cdinfo_genurl_initted = TRUE;
920 }
921 else if (strcmp(key, ".gen.type") == 0) {
922 if (!cdinfo_getline(pp, "url.gen.type", &p->type))
923 return FALSE;
924 }
925 else if (strcmp(key, ".gen.href") == 0) {
926 if (!cdinfo_getline(pp, "url.gen.href", &p->href))
927 return FALSE;
928 }
929 else if (strcmp(key, ".gen.displink") == 0) {
930 if (!cdinfo_getline(pp, "url.gen.displink", &p->displink))
931 return FALSE;
932 }
933 else if (strcmp(key, ".gen.disptext") == 0) {
934 if (!cdinfo_getline(pp, "url.gen.disptext", &p->disptext))
935 return FALSE;
936 }
937 else if (strcmp(key, ".gen.categ") == 0) {
938 if (!cdinfo_getline(pp, "url.gen.categ", &p->categ))
939 return FALSE;
940 }
941 else if (strcmp(key, ".gen.size") == 0) {
942 if (!cdinfo_getline(pp, "url.gen.size", &p->size))
943 return FALSE;
944 }
945 else if (strcmp(key, ".gen.weight") == 0) {
946 if (!cdinfo_getline(pp, "url.gen.weight", &p->weight))
947 return FALSE;
948 }
949 else if (strcmp(key, ".disc.new") == 0) {
950 p = (cdinfo_url_t *)(void *) MEM_ALLOC("cdinfo_url_t",
951 sizeof(cdinfo_url_t)
952 );
953 if (p == NULL) {
954 CDINFO_FATAL(app_data.str_nomemory);
955 return FALSE;
956 }
957 (void) memset(p, 0, sizeof(cdinfo_url_t));
958
959 p->wtype = WTYPE_ALBUM;
960
961 if (cdinfo_dbp->disc_url_list == NULL)
962 cdinfo_dbp->disc_url_list = q = p;
963 else {
964 q->next = p;
965 q = p;
966 }
967 }
968 else if (strcmp(key, ".disc.type") == 0) {
969 if (!cdinfo_getline(pp, "url.disc.type", &p->type))
970 return FALSE;
971 }
972 else if (strcmp(key, ".disc.href") == 0) {
973 if (!cdinfo_getline(pp, "url.disc.href", &p->href))
974 return FALSE;
975 }
976 else if (strcmp(key, ".disc.displink") == 0) {
977 if (!cdinfo_getline(pp, "url.disc.displink", &p->displink))
978 return FALSE;
979 }
980 else if (strcmp(key, ".disc.disptext") == 0) {
981 if (!cdinfo_getline(pp, "url.disc.disptext", &p->disptext))
982 return FALSE;
983 }
984 else if (strcmp(key, ".disc.categ") == 0) {
985 if (!cdinfo_getline(pp, "url.disc.categ", &p->categ))
986 return FALSE;
987 }
988 else if (strcmp(key, ".disc.size") == 0) {
989 if (!cdinfo_getline(pp, "url.disc.size", &p->size))
990 return FALSE;
991 }
992 else if (strcmp(key, ".disc.weight") == 0) {
993 if (!cdinfo_getline(pp, "url.disc.weight", &p->weight))
994 return FALSE;
995 }
996
997 return TRUE;
998 }
999
1000
1001 /*
1002 * cdinfo_getctrl_ents
1003 * Read CDDB control information from pipe, used by the parent.
1004 *
1005 * Args:
1006 * pp - Pointer to cdinfo_pipe_t
1007 * key - control element key string
1008 *
1009 * Return:
1010 * TRUE - success
1011 * FALSE - failure
1012 */
1013 STATIC bool_t
cdinfo_getctrl_ents(cdinfo_pipe_t * pp,char * key)1014 cdinfo_getctrl_ents(cdinfo_pipe_t *pp, char *key)
1015 {
1016 if (strcmp(key, ".ver") == 0) {
1017 if (!cdinfo_getline(pp, "control.ver",
1018 &cdinfo_dbp->ctrl_ver))
1019 return FALSE;
1020 }
1021
1022 cdinfo_ctrl_initted = TRUE;
1023 return TRUE;
1024 }
1025
1026
1027 /*
1028 * cdinfo_getglist_ents
1029 * Read genre list elements from pipe, used by the parent.
1030 *
1031 * Args:
1032 * pp - Pointer to cdinfo_pipe_t
1033 * key - genre element key string
1034 *
1035 * Return:
1036 * TRUE - success
1037 * FALSE - failure
1038 */
1039 STATIC bool_t
cdinfo_getglist_ents(cdinfo_pipe_t * pp,char * key)1040 cdinfo_getglist_ents(cdinfo_pipe_t *pp, char *key)
1041 {
1042 cdinfo_genre_t *p;
1043 static cdinfo_genre_t *gp = NULL,
1044 *sgp = NULL;
1045
1046 if (strcmp(key, ".new") == 0) {
1047 p = (cdinfo_genre_t *)(void *) MEM_ALLOC("genre",
1048 sizeof(cdinfo_genre_t)
1049 );
1050 if (p == NULL) {
1051 CDINFO_FATAL(app_data.str_nomemory);
1052 return FALSE;
1053 }
1054 (void) memset(p, 0, sizeof(cdinfo_genre_t));
1055
1056 if (cdinfo_dbp->genrelist == NULL)
1057 cdinfo_dbp->genrelist = gp = p;
1058 else {
1059 gp->next = p;
1060 gp = p;
1061 }
1062 sgp = NULL;
1063 }
1064 else if (strcmp(key, ".id") == 0) {
1065 if (!cdinfo_getline(pp, "genre.id", &gp->id)) {
1066 gp = sgp = NULL;
1067 cdinfo_free_glist();
1068 return FALSE;
1069 }
1070 }
1071 else if (strcmp(key, ".name") == 0) {
1072 if (!cdinfo_getline(pp, "genre.name", &gp->name)) {
1073 gp = sgp = NULL;
1074 cdinfo_free_glist();
1075 return FALSE;
1076 }
1077 }
1078 else if (strcmp(key, ".subgenre.new") == 0) {
1079 p = (cdinfo_genre_t *)(void *) MEM_ALLOC("genre",
1080 sizeof(cdinfo_genre_t)
1081 );
1082 if (p == NULL) {
1083 CDINFO_FATAL(app_data.str_nomemory);
1084 return FALSE;
1085 }
1086 (void) memset(p, 0, sizeof(cdinfo_genre_t));
1087
1088 p->parent = gp;
1089 if (sgp == NULL)
1090 gp->child = sgp = p;
1091 else {
1092 sgp->next = p;
1093 sgp = p;
1094 }
1095 }
1096 else if (strcmp(key, ".subgenre.id") == 0) {
1097 if (!cdinfo_getline(pp, "subgenre.id", &sgp->id)) {
1098 gp = sgp = NULL;
1099 cdinfo_free_glist();
1100 return FALSE;
1101 }
1102 }
1103 else if (strcmp(key, ".subgenre.name") == 0) {
1104 if (!cdinfo_getline(pp, "subgenre.name", &sgp->name)) {
1105 gp = sgp = NULL;
1106 cdinfo_free_glist();
1107 return FALSE;
1108 }
1109 }
1110
1111 cdinfo_glist_initted = TRUE;
1112 return TRUE;
1113 }
1114
1115
1116 /*
1117 * cdinfo_getrelist_ents
1118 * Read region list elements from pipe, used by the parent.
1119 *
1120 * Args:
1121 * pp - Pointer to cdinfo_pipe_t
1122 * key - region element key string
1123 *
1124 * Return:
1125 * TRUE - success
1126 * FALSE - failure
1127 */
1128 STATIC bool_t
cdinfo_getrelist_ents(cdinfo_pipe_t * pp,char * key)1129 cdinfo_getrelist_ents(cdinfo_pipe_t *pp, char *key)
1130 {
1131 cdinfo_region_t *p;
1132 static cdinfo_region_t *rp = NULL;
1133
1134 if (strcmp(key, ".new") == 0) {
1135 p = (cdinfo_region_t *)(void *) MEM_ALLOC("region",
1136 sizeof(cdinfo_region_t)
1137 );
1138 if (p == NULL) {
1139 CDINFO_FATAL(app_data.str_nomemory);
1140 return FALSE;
1141 }
1142 (void) memset(p, 0, sizeof(cdinfo_region_t));
1143
1144 if (cdinfo_dbp->regionlist == NULL)
1145 cdinfo_dbp->regionlist = rp = p;
1146 else {
1147 rp->next = p;
1148 rp = p;
1149 }
1150 }
1151 else if (strcmp(key, ".id") == 0) {
1152 if (!cdinfo_getline(pp, "region.id", &rp->id)) {
1153 rp = NULL;
1154 cdinfo_free_relist();
1155 return FALSE;
1156 }
1157 }
1158 else if (strcmp(key, ".name") == 0) {
1159 if (!cdinfo_getline(pp, "region.name", &rp->name)) {
1160 rp = NULL;
1161 cdinfo_free_relist();
1162 return FALSE;
1163 }
1164 }
1165
1166 cdinfo_relist_initted = TRUE;
1167 return TRUE;
1168 }
1169
1170
1171 /*
1172 * cdinfo_getlanglist_ents
1173 * Read language list elements from pipe, used by the parent.
1174 *
1175 * Args:
1176 * pp - Pointer to cdinfo_pipe_t
1177 * key - language element key string
1178 *
1179 * Return:
1180 * TRUE - success
1181 * FALSE - failure
1182 */
1183 STATIC bool_t
cdinfo_getlanglist_ents(cdinfo_pipe_t * pp,char * key)1184 cdinfo_getlanglist_ents(cdinfo_pipe_t *pp, char *key)
1185 {
1186 cdinfo_lang_t *p;
1187 static cdinfo_lang_t *lp = NULL;
1188
1189 if (strcmp(key, ".new") == 0) {
1190 p = (cdinfo_lang_t *)(void *) MEM_ALLOC("language",
1191 sizeof(cdinfo_lang_t)
1192 );
1193 if (p == NULL) {
1194 CDINFO_FATAL(app_data.str_nomemory);
1195 return FALSE;
1196 }
1197 (void) memset(p, 0, sizeof(cdinfo_lang_t));
1198
1199 if (cdinfo_dbp->langlist == NULL)
1200 cdinfo_dbp->langlist = lp = p;
1201 else {
1202 lp->next = p;
1203 lp = p;
1204 }
1205 }
1206 else if (strcmp(key, ".id") == 0) {
1207 if (!cdinfo_getline(pp, "lang.id", &lp->id)) {
1208 lp = NULL;
1209 cdinfo_free_langlist();
1210 return FALSE;
1211 }
1212 }
1213 else if (strcmp(key, ".name") == 0) {
1214 if (!cdinfo_getline(pp, "lang.name", &lp->name)) {
1215 lp = NULL;
1216 cdinfo_free_langlist();
1217 return FALSE;
1218 }
1219 }
1220
1221 cdinfo_langlist_initted = TRUE;
1222 return TRUE;
1223 }
1224
1225
1226 /*
1227 * cdinfo_getrolist_ents
1228 * Read role list elements from pipe, used by the parent.
1229 *
1230 * Args:
1231 * pp - Pointer to cdinfo_pipe_t
1232 * key - role element key string
1233 *
1234 * Return:
1235 * TRUE - success
1236 * FALSE - failure
1237 */
1238 STATIC bool_t
cdinfo_getrolist_ents(cdinfo_pipe_t * pp,char * key)1239 cdinfo_getrolist_ents(cdinfo_pipe_t *pp, char *key)
1240 {
1241 cdinfo_role_t *p;
1242 static cdinfo_role_t *rp = NULL,
1243 *srp = NULL;
1244
1245 if (strcmp(key, ".new") == 0) {
1246 p = (cdinfo_role_t *)(void *) MEM_ALLOC("role",
1247 sizeof(cdinfo_role_t)
1248 );
1249 if (p == NULL) {
1250 CDINFO_FATAL(app_data.str_nomemory);
1251 return FALSE;
1252 }
1253 (void) memset(p, 0, sizeof(cdinfo_role_t));
1254
1255 if (cdinfo_dbp->rolelist == NULL)
1256 cdinfo_dbp->rolelist = rp = p;
1257 else {
1258 rp->next = p;
1259 rp = p;
1260 }
1261 srp = NULL;
1262 }
1263 else if (strcmp(key, ".id") == 0) {
1264 if (!cdinfo_getline(pp, "role.id", &rp->id)) {
1265 rp = srp = NULL;
1266 cdinfo_free_rolist();
1267 return FALSE;
1268 }
1269 }
1270 else if (strcmp(key, ".name") == 0) {
1271 if (!cdinfo_getline(pp, "role.name", &rp->name)) {
1272 rp = srp = NULL;
1273 cdinfo_free_rolist();
1274 return FALSE;
1275 }
1276 }
1277 else if (strcmp(key, ".subrole.new") == 0) {
1278 p = (cdinfo_role_t *)(void *) MEM_ALLOC("role",
1279 sizeof(cdinfo_role_t)
1280 );
1281 if (p == NULL) {
1282 CDINFO_FATAL(app_data.str_nomemory);
1283 return FALSE;
1284 }
1285 (void) memset(p, 0, sizeof(cdinfo_role_t));
1286
1287 p->parent = rp;
1288 if (srp == NULL)
1289 rp->child = srp = p;
1290 else {
1291 srp->next = p;
1292 srp = p;
1293 }
1294 }
1295 else if (strcmp(key, ".subrole.id") == 0) {
1296 if (!cdinfo_getline(pp, "subrole.id", &srp->id)) {
1297 rp = srp = NULL;
1298 cdinfo_free_rolist();
1299 return FALSE;
1300 }
1301 }
1302 else if (strcmp(key, ".subrole.name") == 0) {
1303 if (!cdinfo_getline(pp, "subrole.name", &srp->name)) {
1304 rp = srp = NULL;
1305 cdinfo_free_rolist();
1306 return FALSE;
1307 }
1308 }
1309 cdinfo_rolist_initted = TRUE;
1310 return TRUE;
1311 }
1312
1313
1314 /*
1315 * cdinfo_getmatch_ents
1316 * Read multiple match elements from pipe, used by the parent.
1317 *
1318 * Args:
1319 * pp - Pointer to cdinfo_pipe_t
1320 * key - match element key string
1321 *
1322 * Return:
1323 * TRUE - success
1324 * FALSE - failure
1325 */
1326 STATIC bool_t
cdinfo_getmatch_ents(cdinfo_pipe_t * pp,char * key)1327 cdinfo_getmatch_ents(cdinfo_pipe_t *pp, char *key)
1328 {
1329 cdinfo_match_t *p;
1330 static cdinfo_match_t *mp = NULL;
1331
1332 if (strcmp(key, ".new") == 0) {
1333 p = (cdinfo_match_t *)(void *) MEM_ALLOC("match",
1334 sizeof(cdinfo_match_t)
1335 );
1336 if (p == NULL) {
1337 CDINFO_FATAL(app_data.str_nomemory);
1338 return FALSE;
1339 }
1340 (void) memset(p, 0, sizeof(cdinfo_match_t));
1341
1342 if (cdinfo_dbp->matchlist == NULL)
1343 cdinfo_dbp->matchlist = mp = p;
1344 else {
1345 mp->next = p;
1346 mp = p;
1347 }
1348 }
1349 else if (strcmp(key, ".artist") == 0) {
1350 if (!cdinfo_getline(pp, "match.artist", &mp->artist)) {
1351 mp = NULL;
1352 cdinfo_free_matchlist();
1353 return FALSE;
1354 }
1355 }
1356 else if (strcmp(key, ".title") == 0) {
1357 if (!cdinfo_getline(pp, "match.title", &mp->title)) {
1358 mp = NULL;
1359 cdinfo_free_matchlist();
1360 return FALSE;
1361 }
1362 }
1363 else if (strcmp(key, ".genre") == 0) {
1364 if (!cdinfo_getline(pp, "match.genre", &mp->genre)) {
1365 mp = NULL;
1366 cdinfo_free_matchlist();
1367 return FALSE;
1368 }
1369 }
1370
1371 return TRUE;
1372 }
1373
1374
1375 /*
1376 * cdinfo_getuserreg_ents
1377 * Read user registration related elements from pipe, used by the parent.
1378 *
1379 * Args:
1380 * pp - Pointer to cdinfo_pipe_t
1381 * key - userreg element key string
1382 *
1383 * Return:
1384 * TRUE - success
1385 * FALSE - failure
1386 */
1387 STATIC bool_t
cdinfo_getuserreg_ents(cdinfo_pipe_t * pp,char * key)1388 cdinfo_getuserreg_ents(cdinfo_pipe_t *pp, char *key)
1389 {
1390 char *str;
1391
1392 if (strcmp(key, ".handle") == 0) {
1393 if (cdinfo_dbp->userreg.handle != NULL) {
1394 MEM_FREE(cdinfo_dbp->userreg.handle);
1395 cdinfo_dbp->userreg.handle = NULL;
1396 }
1397 if (!cdinfo_getline(pp, "userreg.handle",
1398 &cdinfo_dbp->userreg.handle))
1399 return FALSE;
1400 }
1401 else if (strcmp(key, ".hint") == 0) {
1402 if (cdinfo_dbp->userreg.hint != NULL) {
1403 MEM_FREE(cdinfo_dbp->userreg.hint);
1404 cdinfo_dbp->userreg.hint = NULL;
1405 }
1406 if (!cdinfo_getline(pp, "userreg.hint",
1407 &cdinfo_dbp->userreg.hint))
1408 return FALSE;
1409 }
1410 else if (strcmp(key, ".email") == 0) {
1411 if (cdinfo_dbp->userreg.email != NULL) {
1412 MEM_FREE(cdinfo_dbp->userreg.email);
1413 cdinfo_dbp->userreg.email = NULL;
1414 }
1415 if (!cdinfo_getline(pp, "userreg.email",
1416 &cdinfo_dbp->userreg.email))
1417 return FALSE;
1418 }
1419 else if (strcmp(key, ".region") == 0) {
1420 if (cdinfo_dbp->userreg.region != NULL) {
1421 MEM_FREE(cdinfo_dbp->userreg.region);
1422 cdinfo_dbp->userreg.region = NULL;
1423 }
1424 if (!cdinfo_getline(pp, "userreg.region",
1425 &cdinfo_dbp->userreg.region))
1426 return FALSE;
1427 }
1428 else if (strcmp(key, ".postal") == 0) {
1429 if (cdinfo_dbp->userreg.postal != NULL) {
1430 MEM_FREE(cdinfo_dbp->userreg.postal);
1431 cdinfo_dbp->userreg.postal = NULL;
1432 }
1433 if (!cdinfo_getline(pp, "userreg.postal",
1434 &cdinfo_dbp->userreg.postal))
1435 return FALSE;
1436 }
1437 else if (strcmp(key, ".age") == 0) {
1438 if (cdinfo_dbp->userreg.age != NULL) {
1439 MEM_FREE(cdinfo_dbp->userreg.age);
1440 cdinfo_dbp->userreg.age = NULL;
1441 }
1442 if (!cdinfo_getline(pp, "userreg.age",
1443 &cdinfo_dbp->userreg.age))
1444 return FALSE;
1445 }
1446 else if (strcmp(key, ".gender") == 0) {
1447 if (cdinfo_dbp->userreg.gender != NULL) {
1448 MEM_FREE(cdinfo_dbp->userreg.gender);
1449 cdinfo_dbp->userreg.gender = NULL;
1450 }
1451 if (!cdinfo_getline(pp, "userreg.gender",
1452 &cdinfo_dbp->userreg.gender))
1453 return FALSE;
1454 }
1455 else if (strcmp(key, ".allowemail") == 0) {
1456 str = NULL;
1457 if (!cdinfo_getline(pp, "userreg.allowemail", &str))
1458 return FALSE;
1459 if (str != NULL) {
1460 if (*str == '1')
1461 cdinfo_dbp->userreg.allowemail = TRUE;
1462 MEM_FREE(str);
1463 }
1464 }
1465 else if (strcmp(key, ".allowstats") == 0) {
1466 str = NULL;
1467 if (!cdinfo_getline(pp, "userreg.allowstats", &str))
1468 return FALSE;
1469 if (str != NULL) {
1470 if (*str == '1')
1471 cdinfo_dbp->userreg.allowemail = TRUE;
1472 MEM_FREE(str);
1473 }
1474 }
1475
1476 cdinfo_user_regd = TRUE;
1477 return TRUE;
1478 }
1479
1480
1481 /*
1482 * cdinfo_getdisc_ents
1483 * Read disc related elements from pipe, used by the parent.
1484 *
1485 * Args:
1486 * pp - Pointer to cdinfo_pipe_t
1487 * key - disc element key string
1488 *
1489 * Return:
1490 * TRUE - success
1491 * FALSE - failure
1492 */
1493 STATIC bool_t
cdinfo_getdisc_ents(cdinfo_pipe_t * pp,char * key)1494 cdinfo_getdisc_ents(cdinfo_pipe_t *pp, char *key)
1495 {
1496 char *str;
1497 cdinfo_credit_t *p;
1498 cdinfo_segment_t *q;
1499 static cdinfo_credit_t *cp = NULL;
1500 static cdinfo_segment_t *sp = NULL;
1501
1502 if (strcmp(key, ".flags") == 0) {
1503 str = NULL;
1504 if (!cdinfo_getline(pp, "disc.flags", &str))
1505 return FALSE;
1506 if (str != NULL) {
1507 (void) sscanf(str, "%x", &cdinfo_dbp->flags);
1508 MEM_FREE(str);
1509 }
1510 }
1511 else if (strcmp(key, ".compilation") == 0) {
1512 str = NULL;
1513 if (!cdinfo_getline(pp, "disc.compilation", &str))
1514 return FALSE;
1515 if (str != NULL) {
1516 if (*str == '1')
1517 cdinfo_dbp->disc.compilation = TRUE;
1518 MEM_FREE(str);
1519 }
1520 }
1521 else if (strcmp(key, ".artistfname.dispname") == 0) {
1522 if (!cdinfo_getline(pp, "disc.artistfname.dispname",
1523 &cdinfo_dbp->disc.artistfname.dispname))
1524 return FALSE;
1525 }
1526 else if (strcmp(key, ".artistfname.lastname") == 0) {
1527 if (!cdinfo_getline(pp, "disc.artistfname.lastname",
1528 &cdinfo_dbp->disc.artistfname.lastname))
1529 return FALSE;
1530 }
1531 else if (strcmp(key, ".artistfname.firstname") == 0) {
1532 if (!cdinfo_getline(pp, "disc.artistfname.firstname",
1533 &cdinfo_dbp->disc.artistfname.firstname))
1534 return FALSE;
1535 }
1536 else if (strcmp(key, ".artistfname.the") == 0) {
1537 if (!cdinfo_getline(pp, "disc.artistfname.the",
1538 &cdinfo_dbp->disc.artistfname.the))
1539 return FALSE;
1540 }
1541 else if (strcmp(key, ".artist") == 0) {
1542 if (!cdinfo_getline(pp,
1543 "disc.artist", &cdinfo_dbp->disc.artist))
1544 return FALSE;
1545 }
1546 else if (strcmp(key, ".title") == 0) {
1547 if (!cdinfo_getline(pp, "disc.title", &cdinfo_dbp->disc.title))
1548 return FALSE;
1549 }
1550 else if (strcmp(key, ".sorttitle") == 0) {
1551 if (!cdinfo_getline(pp, "disc.sorttitle",
1552 &cdinfo_dbp->disc.sorttitle))
1553 return FALSE;
1554 }
1555 else if (strcmp(key, ".title_the") == 0) {
1556 if (!cdinfo_getline(pp, "disc.title_the",
1557 &cdinfo_dbp->disc.title_the))
1558 return FALSE;
1559 }
1560 else if (strcmp(key, ".year") == 0) {
1561 if (!cdinfo_getline(pp, "disc.year", &cdinfo_dbp->disc.year))
1562 return FALSE;
1563 }
1564 else if (strcmp(key, ".label") == 0) {
1565 if (!cdinfo_getline(pp, "disc.label", &cdinfo_dbp->disc.label))
1566 return FALSE;
1567 }
1568 else if (strcmp(key, ".genre") == 0) {
1569 if (!cdinfo_getline(pp, "disc.genre", &cdinfo_dbp->disc.genre))
1570 return FALSE;
1571 }
1572 else if (strcmp(key, ".genre2") == 0) {
1573 if (!cdinfo_getline(pp, "disc.genre2",
1574 &cdinfo_dbp->disc.genre2))
1575 return FALSE;
1576 }
1577 else if (strcmp(key, ".dnum") == 0) {
1578 if (!cdinfo_getline(pp, "disc.dnum", &cdinfo_dbp->disc.dnum))
1579 return FALSE;
1580 }
1581 else if (strcmp(key, ".tnum") == 0) {
1582 if (!cdinfo_getline(pp, "disc.tnum", &cdinfo_dbp->disc.tnum))
1583 return FALSE;
1584 }
1585 else if (strcmp(key, ".region") == 0) {
1586 if (!cdinfo_getline(pp,
1587 "disc.region", &cdinfo_dbp->disc.region))
1588 return FALSE;
1589 }
1590 else if (strcmp(key, ".lang") == 0) {
1591 if (!cdinfo_getline(pp, "disc.lang", &cdinfo_dbp->disc.lang))
1592 return FALSE;
1593 }
1594 else if (strcmp(key, ".notes") == 0) {
1595 if (!cdinfo_getmultiline(pp, "disc.notes",
1596 &cdinfo_dbp->disc.notes))
1597 return FALSE;
1598 }
1599 else if (strcmp(key, ".mediaid") == 0) {
1600 if (!cdinfo_getline(pp, "disc.mediaid",
1601 &cdinfo_dbp->disc.mediaid))
1602 return FALSE;
1603 }
1604 else if (strcmp(key, ".muiid") == 0) {
1605 if (!cdinfo_getline(pp,
1606 "disc.muiid", &cdinfo_dbp->disc.muiid))
1607 return FALSE;
1608 }
1609 else if (strcmp(key, ".titleuid") == 0) {
1610 if (!cdinfo_getline(pp, "disc.titleuid",
1611 &cdinfo_dbp->disc.titleuid))
1612 return FALSE;
1613 }
1614 else if (strcmp(key, ".revision") == 0) {
1615 if (!cdinfo_getline(pp, "disc.revision",
1616 &cdinfo_dbp->disc.revision))
1617 return FALSE;
1618 }
1619 else if (strcmp(key, ".revtag") == 0) {
1620 if (!cdinfo_getline(pp,
1621 "disc.revtag", &cdinfo_dbp->disc.revtag))
1622 return FALSE;
1623 }
1624 else if (strcmp(key, ".certifier") == 0) {
1625 if (!cdinfo_getline(pp, "disc.certifier",
1626 &cdinfo_dbp->disc.certifier))
1627 return FALSE;
1628 }
1629 else if (strcmp(key, ".credit.new") == 0) {
1630 p = (cdinfo_credit_t *)(void *) MEM_ALLOC("cdinfo_credit_t",
1631 sizeof(cdinfo_credit_t)
1632 );
1633 if (p == NULL) {
1634 CDINFO_FATAL(app_data.str_nomemory);
1635 return FALSE;
1636 }
1637 (void) memset(p, 0, sizeof(cdinfo_credit_t));
1638
1639 if (cdinfo_dbp->disc.credit_list == NULL) {
1640 cdinfo_dbp->disc.credit_list = p;
1641 p->prev = NULL;
1642 }
1643 else {
1644 cp->next = p;
1645 p->prev = cp;
1646 }
1647 cp = p;
1648 p->next = NULL;
1649 }
1650 else if (strcmp(key, ".credit.role") == 0) {
1651 str = NULL;
1652 if (!cdinfo_getline(pp, "disc.credit.role", &str))
1653 return FALSE;
1654 if (str != NULL) {
1655 cp->crinfo.role = cdinfo_role(str);
1656 MEM_FREE(str);
1657 }
1658 }
1659 else if (strcmp(key, ".credit.name") == 0) {
1660 if (!cdinfo_getline(pp, "disc.credit.name",
1661 &cp->crinfo.name))
1662 return FALSE;
1663 }
1664 else if (strcmp(key, ".credit.fullname.dispname") == 0) {
1665 if (!cdinfo_getline(pp, "disc.credit.fullname.dispname",
1666 &cp->crinfo.fullname.dispname))
1667 return FALSE;
1668 }
1669 else if (strcmp(key, ".credit.fullname.lastname") == 0) {
1670 if (!cdinfo_getline(pp, "disc.credit.fullname.lastname",
1671 &cp->crinfo.fullname.lastname))
1672 return FALSE;
1673 }
1674 else if (strcmp(key, ".credit.fullname.firstname") == 0) {
1675 if (!cdinfo_getline(pp, "disc.credit.fullname.firstname",
1676 &cp->crinfo.fullname.firstname))
1677 return FALSE;
1678 }
1679 else if (strcmp(key, ".credit.fullname.the") == 0) {
1680 if (!cdinfo_getline(pp, "disc.credit.fullname.the",
1681 &cp->crinfo.fullname.the))
1682 return FALSE;
1683 }
1684 else if (strcmp(key, ".credit.notes") == 0) {
1685 if (!cdinfo_getmultiline(pp, "disc.credit.notes",
1686 &cp->notes))
1687 return FALSE;
1688 }
1689 else if (strcmp(key, ".segment.new") == 0) {
1690 q = (cdinfo_segment_t *)(void *) MEM_ALLOC("cdinfo_segment_t",
1691 sizeof(cdinfo_segment_t)
1692 );
1693 if (q == NULL) {
1694 CDINFO_FATAL(app_data.str_nomemory);
1695 return FALSE;
1696 }
1697 (void) memset(q, 0, sizeof(cdinfo_segment_t));
1698
1699 if (cdinfo_dbp->disc.segment_list == NULL) {
1700 cdinfo_dbp->disc.segment_list = q;
1701 q->prev = NULL;
1702 }
1703 else {
1704 sp->next = q;
1705 q->prev = sp;
1706 }
1707 sp = q;
1708 q->next = NULL;
1709 }
1710 else if (strcmp(key, ".segment.name") == 0) {
1711 if (!cdinfo_getline(pp, "disc.segment.name",
1712 &sp->name))
1713 return FALSE;
1714 }
1715 else if (strcmp(key, ".segment.notes") == 0) {
1716 if (!cdinfo_getmultiline(pp, "disc.segment.notes",
1717 &sp->notes))
1718 return FALSE;
1719 }
1720 else if (strcmp(key, ".segment.start_track") == 0) {
1721 if (!cdinfo_getline(pp, "disc.segment.start_track",
1722 &sp->start_track))
1723 return FALSE;
1724 }
1725 else if (strcmp(key, ".segment.start_frame") == 0) {
1726 if (!cdinfo_getline(pp, "disc.segment.start_frame",
1727 &sp->start_frame))
1728 return FALSE;
1729 }
1730 else if (strcmp(key, ".segment.end_track") == 0) {
1731 if (!cdinfo_getline(pp, "disc.segment.end_track",
1732 &sp->end_track))
1733 return FALSE;
1734 }
1735 else if (strcmp(key, ".segment.end_frame") == 0) {
1736 if (!cdinfo_getline(pp, "disc.segment.end_frame",
1737 &sp->end_frame))
1738 return FALSE;
1739 }
1740 else if (strcmp(key, ".segment.credit.new") == 0) {
1741 p = (cdinfo_credit_t *)(void *) MEM_ALLOC("cdinfo_credit_t",
1742 sizeof(cdinfo_credit_t)
1743 );
1744 if (p == NULL) {
1745 CDINFO_FATAL(app_data.str_nomemory);
1746 return FALSE;
1747 }
1748 (void) memset(p, 0, sizeof(cdinfo_credit_t));
1749
1750 if (sp->credit_list == NULL) {
1751 sp->credit_list = p;
1752 p->prev = NULL;
1753 }
1754 else {
1755 cp->next = p;
1756 p->prev = cp;
1757 }
1758 cp = p;
1759 p->next = NULL;
1760 }
1761 else if (strcmp(key, ".segment.credit.role") == 0) {
1762 str = NULL;
1763 if (!cdinfo_getline(pp, "disc.segment.credit.role", &str))
1764 return FALSE;
1765 if (str != NULL) {
1766 cp->crinfo.role = cdinfo_role(str);
1767 MEM_FREE(str);
1768 }
1769 }
1770 else if (strcmp(key, ".segment.credit.name") == 0) {
1771 if (!cdinfo_getline(pp, "disc.segment.credit.name",
1772 &cp->crinfo.name))
1773 return FALSE;
1774 }
1775 else if (strcmp(key, ".segment.credit.fullname.dispname") == 0) {
1776 if (!cdinfo_getline(pp,
1777 "disc.segment.credit.fullname.dispname",
1778 &cp->crinfo.fullname.dispname))
1779 return FALSE;
1780 }
1781 else if (strcmp(key, ".segment.credit.fullname.lastname") == 0) {
1782 if (!cdinfo_getline(pp,
1783 "disc.segment.credit.fullname.lastname",
1784 &cp->crinfo.fullname.lastname))
1785 return FALSE;
1786 }
1787 else if (strcmp(key, ".segment.credit.fullname.firstname") == 0) {
1788 if (!cdinfo_getline(pp,
1789 "disc.segment.credit.fullname.firstname",
1790 &cp->crinfo.fullname.firstname))
1791 return FALSE;
1792 }
1793 else if (strcmp(key, ".segment.credit.fullname.the") == 0) {
1794 if (!cdinfo_getline(pp, "disc.segment.credit.fullname.the",
1795 &cp->crinfo.fullname.the))
1796 return FALSE;
1797 }
1798 else if (strcmp(key, ".segment.credit.notes") == 0) {
1799 if (!cdinfo_getmultiline(pp, "disc.segment.credit.notes",
1800 &cp->notes))
1801 return FALSE;
1802 }
1803
1804 return TRUE;
1805 }
1806
1807
1808 /*
1809 * cdinfo_gettrack_ents
1810 * Read track related elements from pipe, used by the parent.
1811 *
1812 * Args:
1813 * pp - Pointer to cdinfo_pipe_t
1814 * key - track element key string
1815 *
1816 * Return:
1817 * TRUE - success
1818 * FALSE - failure
1819 */
1820 STATIC bool_t
cdinfo_gettrack_ents(cdinfo_pipe_t * pp,char * key)1821 cdinfo_gettrack_ents(cdinfo_pipe_t *pp, char *key)
1822 {
1823 int i;
1824 char *str,
1825 *name;
1826 cdinfo_credit_t *p;
1827 static cdinfo_credit_t *cp = NULL;
1828
1829 if (sscanf(key, "%d.", &i) != 1)
1830 return FALSE; /* Unexpected data */
1831
1832 name = strchr(key, '.') + 1;
1833
1834 if (strcmp(name, "artistfname.dispname") == 0) {
1835 if (!cdinfo_getline(pp, name,
1836 &cdinfo_dbp->track[i].artistfname.dispname))
1837 return FALSE;
1838 }
1839 else if (strcmp(name, "artistfname.lastname") == 0) {
1840 if (!cdinfo_getline(pp, name,
1841 &cdinfo_dbp->track[i].artistfname.lastname))
1842 return FALSE;
1843 }
1844 else if (strcmp(name, "artistfname.firstname") == 0) {
1845 if (!cdinfo_getline(pp, name,
1846 &cdinfo_dbp->track[i].artistfname.firstname))
1847 return FALSE;
1848 }
1849 else if (strcmp(name, "artistfname.the") == 0) {
1850 if (!cdinfo_getline(pp, name,
1851 &cdinfo_dbp->track[i].artistfname.the))
1852 return FALSE;
1853 }
1854 else if (strcmp(name, "artist") == 0) {
1855 if (!cdinfo_getline(pp, name, &cdinfo_dbp->track[i].artist))
1856 return FALSE;
1857 }
1858 else if (strcmp(name, "title") == 0) {
1859 if (!cdinfo_getline(pp, name, &cdinfo_dbp->track[i].title))
1860 return FALSE;
1861 }
1862 else if (strcmp(name, "sorttitle") == 0) {
1863 if (!cdinfo_getline(pp, name, &cdinfo_dbp->track[i].sorttitle))
1864 return FALSE;
1865 }
1866 else if (strcmp(name, "title_the") == 0) {
1867 if (!cdinfo_getline(pp, name, &cdinfo_dbp->track[i].title_the))
1868 return FALSE;
1869 }
1870 else if (strcmp(name, "year") == 0) {
1871 if (!cdinfo_getline(pp, name, &cdinfo_dbp->track[i].year))
1872 return FALSE;
1873 }
1874 else if (strcmp(name, "label") == 0) {
1875 if (!cdinfo_getline(pp, name, &cdinfo_dbp->track[i].label))
1876 return FALSE;
1877 }
1878 else if (strcmp(name, "genre") == 0) {
1879 if (!cdinfo_getline(pp, name, &cdinfo_dbp->track[i].genre))
1880 return FALSE;
1881 }
1882 else if (strcmp(name, "genre2") == 0) {
1883 if (!cdinfo_getline(pp, name, &cdinfo_dbp->track[i].genre2))
1884 return FALSE;
1885 }
1886 else if (strcmp(name, "bpm") == 0) {
1887 if (!cdinfo_getline(pp, name, &cdinfo_dbp->track[i].bpm))
1888 return FALSE;
1889 }
1890 else if (strcmp(name, "notes") == 0) {
1891 if (!cdinfo_getmultiline(pp, name,
1892 &cdinfo_dbp->track[i].notes))
1893 return FALSE;
1894 }
1895 else if (strcmp(name, "isrc") == 0) {
1896 if (!cdinfo_getline(pp, name, &cdinfo_dbp->track[i].isrc))
1897 return FALSE;
1898 }
1899 else if (strcmp(name, "credit.new") == 0) {
1900 p = (cdinfo_credit_t *)(void *) MEM_ALLOC("cdinfo_credit_t",
1901 sizeof(cdinfo_credit_t)
1902 );
1903 if (p == NULL) {
1904 CDINFO_FATAL(app_data.str_nomemory);
1905 return FALSE;
1906 }
1907 (void) memset(p, 0, sizeof(cdinfo_credit_t));
1908
1909 if (cdinfo_dbp->track[i].credit_list == NULL) {
1910 cdinfo_dbp->track[i].credit_list = p;
1911 p->prev = NULL;
1912 }
1913 else {
1914 cp->next = p;
1915 p->prev = cp;
1916 }
1917 cp = p;
1918 p->next = NULL;
1919 }
1920 else if (strcmp(name, "credit.role") == 0) {
1921 str = NULL;
1922 if (!cdinfo_getline(pp, name, &str))
1923 return FALSE;
1924 if (str != NULL) {
1925 cp->crinfo.role = cdinfo_role(str);
1926 MEM_FREE(str);
1927 }
1928 }
1929 else if (strcmp(name, "credit.name") == 0) {
1930 if (!cdinfo_getline(pp, name, &cp->crinfo.name))
1931 return FALSE;
1932 }
1933 else if (strcmp(name, "credit.fullname.dispname") == 0) {
1934 if (!cdinfo_getline(pp, name, &cp->crinfo.fullname.dispname))
1935 return FALSE;
1936 }
1937 else if (strcmp(name, "credit.fullname.lastname") == 0) {
1938 if (!cdinfo_getline(pp, name, &cp->crinfo.fullname.lastname))
1939 return FALSE;
1940 }
1941 else if (strcmp(name, "credit.fullname.firstname") == 0) {
1942 if (!cdinfo_getline(pp, name, &cp->crinfo.fullname.firstname))
1943 return FALSE;
1944 }
1945 else if (strcmp(name, "credit.fullname.the") == 0) {
1946 if (!cdinfo_getline(pp, name, &cp->crinfo.fullname.the))
1947 return FALSE;
1948 }
1949 else if (strcmp(name, "credit.notes") == 0) {
1950 if (!cdinfo_getmultiline(pp, name, &cp->notes))
1951 return FALSE;
1952 }
1953
1954 return TRUE;
1955 }
1956
1957
1958 /*
1959 * cdinfo_puturl_ents
1960 * Write URL match elements into pipe, used by the child.
1961 *
1962 * Args:
1963 * pp - Pointer to cdinfo_pipe_t
1964 *
1965 * Return:
1966 * TRUE - success
1967 * FALSE - failure
1968 */
1969 STATIC bool_t
cdinfo_puturl_ents(cdinfo_pipe_t * pp)1970 cdinfo_puturl_ents(cdinfo_pipe_t *pp)
1971 {
1972 cdinfo_url_t *p;
1973
1974 if (!cdinfo_genurl_initted) {
1975 for (p = cdinfo_dbp->gen_url_list; p != NULL; p = p->next) {
1976 if (!cdinfo_puts(pp, XMCD_PIPESIG "url.gen.new"))
1977 return FALSE;
1978
1979 if (p->type != NULL) {
1980 if (!cdinfo_puts(pp, XMCD_PIPESIG "url.gen.type"))
1981 return FALSE;
1982 if (!cdinfo_puts(pp, p->type))
1983 return FALSE;
1984 }
1985 if (p->href != NULL) {
1986 if (!cdinfo_puts(pp, XMCD_PIPESIG "url.gen.href"))
1987 return FALSE;
1988 if (!cdinfo_puts(pp, p->href))
1989 return FALSE;
1990 }
1991 if (p->displink != NULL) {
1992 if (!cdinfo_puts(pp, XMCD_PIPESIG "url.gen.displink"))
1993 return FALSE;
1994 if (!cdinfo_puts(pp, p->displink))
1995 return FALSE;
1996 }
1997 if (p->disptext != NULL) {
1998 if (!cdinfo_puts(pp, XMCD_PIPESIG "url.gen.disptext"))
1999 return FALSE;
2000 if (!cdinfo_puts(pp, p->disptext))
2001 return FALSE;
2002 }
2003 if (p->categ != NULL) {
2004 if (!cdinfo_puts(pp, XMCD_PIPESIG "url.gen.categ"))
2005 return FALSE;
2006 if (!cdinfo_puts(pp, p->categ))
2007 return FALSE;
2008 }
2009 if (p->size != NULL) {
2010 if (!cdinfo_puts(pp, XMCD_PIPESIG "url.gen.size"))
2011 return FALSE;
2012 if (!cdinfo_puts(pp, p->size))
2013 return FALSE;
2014 }
2015 if (p->weight != NULL) {
2016 if (!cdinfo_puts(pp, XMCD_PIPESIG "url.gen.weight"))
2017 return FALSE;
2018 if (!cdinfo_puts(pp, p->weight))
2019 return FALSE;
2020 }
2021
2022 cdinfo_genurl_initted = TRUE;
2023 }
2024 }
2025
2026 for (p = cdinfo_dbp->disc_url_list; p != NULL; p = p->next) {
2027 if (!cdinfo_puts(pp, XMCD_PIPESIG "url.disc.new"))
2028 return FALSE;
2029
2030 if (p->type != NULL) {
2031 if (!cdinfo_puts(pp, XMCD_PIPESIG "url.disc.type"))
2032 return FALSE;
2033 if (!cdinfo_puts(pp, p->type))
2034 return FALSE;
2035 }
2036 if (p->href != NULL) {
2037 if (!cdinfo_puts(pp, XMCD_PIPESIG "url.disc.href"))
2038 return FALSE;
2039 if (!cdinfo_puts(pp, p->href))
2040 return FALSE;
2041 }
2042 if (p->displink != NULL) {
2043 if (!cdinfo_puts(pp, XMCD_PIPESIG "url.disc.displink"))
2044 return FALSE;
2045 if (!cdinfo_puts(pp, p->displink))
2046 return FALSE;
2047 }
2048 if (p->disptext != NULL) {
2049 if (!cdinfo_puts(pp, XMCD_PIPESIG "url.disc.disptext"))
2050 return FALSE;
2051 if (!cdinfo_puts(pp, p->disptext))
2052 return FALSE;
2053 }
2054 if (p->categ != NULL) {
2055 if (!cdinfo_puts(pp, XMCD_PIPESIG "url.disc.categ"))
2056 return FALSE;
2057 if (!cdinfo_puts(pp, p->categ))
2058 return FALSE;
2059 }
2060 if (p->size != NULL) {
2061 if (!cdinfo_puts(pp, XMCD_PIPESIG "url.disc.size"))
2062 return FALSE;
2063 if (!cdinfo_puts(pp, p->size))
2064 return FALSE;
2065 }
2066 if (p->weight != NULL) {
2067 if (!cdinfo_puts(pp, XMCD_PIPESIG "url.disc.weight"))
2068 return FALSE;
2069 if (!cdinfo_puts(pp, p->weight))
2070 return FALSE;
2071 }
2072 }
2073
2074 return TRUE;
2075 }
2076
2077
2078 /*
2079 * cdinfo_putctrl_ents
2080 * Write CDDB control information into pipe, used by the child.
2081 *
2082 * Args:
2083 * pp - Pointer to cdinfo_pipe_t
2084 *
2085 * Return:
2086 * TRUE - success
2087 * FALSE - failure
2088 */
2089 STATIC bool_t
cdinfo_putctrl_ents(cdinfo_pipe_t * pp)2090 cdinfo_putctrl_ents(cdinfo_pipe_t *pp)
2091 {
2092 if (cdinfo_ctrl_initted)
2093 return TRUE;
2094
2095 if (cdinfo_dbp->ctrl_ver != NULL) {
2096 if (!cdinfo_puts(pp, XMCD_PIPESIG "control.ver"))
2097 return FALSE;
2098 if (!cdinfo_puts(pp, cdinfo_dbp->ctrl_ver))
2099 return FALSE;
2100 }
2101
2102 cdinfo_ctrl_initted = TRUE;
2103 return TRUE;
2104 }
2105
2106
2107 /*
2108 * cdinfo_putglist_ents
2109 * Write genre list elements into pipe, used by the child.
2110 *
2111 * Args:
2112 * pp - Pointer to cdinfo_pipe_t
2113 *
2114 * Return:
2115 * TRUE - success
2116 * FALSE - failure
2117 */
2118 STATIC bool_t
cdinfo_putglist_ents(cdinfo_pipe_t * pp)2119 cdinfo_putglist_ents(cdinfo_pipe_t *pp)
2120 {
2121 cdinfo_genre_t *p,
2122 *q;
2123
2124 if (cdinfo_glist_initted)
2125 return TRUE;
2126
2127 for (p = cdinfo_dbp->genrelist; p != NULL; p = p->next) {
2128 if (!cdinfo_puts(pp, XMCD_PIPESIG "genre.new"))
2129 return FALSE;
2130
2131 if (!cdinfo_puts(pp, XMCD_PIPESIG "genre.id"))
2132 return FALSE;
2133 if (!cdinfo_puts(pp, p->id))
2134 return FALSE;
2135
2136 if (!cdinfo_puts(pp, XMCD_PIPESIG "genre.name"))
2137 return FALSE;
2138 if (!cdinfo_puts(pp, p->name))
2139 return FALSE;
2140
2141 for (q = p->child; q != NULL; q = q->next) {
2142 if (!cdinfo_puts(pp,
2143 XMCD_PIPESIG "genre.subgenre.new"))
2144 return FALSE;
2145
2146 if (!cdinfo_puts(pp,
2147 XMCD_PIPESIG "genre.subgenre.id"))
2148 return FALSE;
2149 if (!cdinfo_puts(pp, q->id))
2150 return FALSE;
2151
2152 if (!cdinfo_puts(pp,
2153 XMCD_PIPESIG "genre.subgenre.name"))
2154 return FALSE;
2155 if (!cdinfo_puts(pp, q->name))
2156 return FALSE;
2157 }
2158 }
2159
2160 cdinfo_glist_initted = TRUE;
2161 return TRUE;
2162 }
2163
2164
2165 /*
2166 * cdinfo_putrelist_ents
2167 * Write region list elements into pipe, used by the child.
2168 *
2169 * Args:
2170 * pp - Pointer to cdinfo_pipe_t
2171 *
2172 * Return:
2173 * TRUE - success
2174 * FALSE - failure
2175 */
2176 STATIC bool_t
cdinfo_putrelist_ents(cdinfo_pipe_t * pp)2177 cdinfo_putrelist_ents(cdinfo_pipe_t *pp)
2178 {
2179 cdinfo_region_t *p;
2180
2181 if (cdinfo_relist_initted)
2182 return TRUE;
2183
2184 for (p = cdinfo_dbp->regionlist; p != NULL; p = p->next) {
2185 if (!cdinfo_puts(pp, XMCD_PIPESIG "region.new"))
2186 return FALSE;
2187
2188 if (!cdinfo_puts(pp, XMCD_PIPESIG "region.id"))
2189 return FALSE;
2190 if (!cdinfo_puts(pp, p->id))
2191 return FALSE;
2192
2193 if (!cdinfo_puts(pp, XMCD_PIPESIG "region.name"))
2194 return FALSE;
2195 if (!cdinfo_puts(pp, p->name))
2196 return FALSE;
2197 }
2198
2199 cdinfo_relist_initted = TRUE;
2200 return TRUE;
2201 }
2202
2203
2204 /*
2205 * cdinfo_putlanglist_ents
2206 * Write language list elements into pipe, used by the child.
2207 *
2208 * Args:
2209 * pp - Pointer to cdinfo_pipe_t
2210 *
2211 * Return:
2212 * TRUE - success
2213 * FALSE - failure
2214 */
2215 STATIC bool_t
cdinfo_putlanglist_ents(cdinfo_pipe_t * pp)2216 cdinfo_putlanglist_ents(cdinfo_pipe_t *pp)
2217 {
2218 cdinfo_lang_t *p;
2219
2220 if (cdinfo_langlist_initted)
2221 return TRUE;
2222
2223 for (p = cdinfo_dbp->langlist; p != NULL; p = p->next) {
2224 if (!cdinfo_puts(pp, XMCD_PIPESIG "lang.new"))
2225 return FALSE;
2226
2227 if (!cdinfo_puts(pp, XMCD_PIPESIG "lang.id"))
2228 return FALSE;
2229 if (!cdinfo_puts(pp, p->id))
2230 return FALSE;
2231
2232 if (!cdinfo_puts(pp, XMCD_PIPESIG "lang.name"))
2233 return FALSE;
2234 if (!cdinfo_puts(pp, p->name))
2235 return FALSE;
2236 }
2237
2238 cdinfo_langlist_initted = TRUE;
2239 return TRUE;
2240 }
2241
2242
2243 /*
2244 * cdinfo_putrolist_ents
2245 * Write role list elements into pipe, used by the child.
2246 *
2247 * Args:
2248 * pp - Pointer to cdinfo_pipe_t
2249 *
2250 * Return:
2251 * TRUE - success
2252 * FALSE - failure
2253 */
2254 STATIC bool_t
cdinfo_putrolist_ents(cdinfo_pipe_t * pp)2255 cdinfo_putrolist_ents(cdinfo_pipe_t *pp)
2256 {
2257 cdinfo_role_t *p,
2258 *q;
2259
2260 if (cdinfo_rolist_initted)
2261 return TRUE;
2262
2263 for (p = cdinfo_dbp->rolelist; p != NULL; p = p->next) {
2264 if (!cdinfo_puts(pp, XMCD_PIPESIG "role.new"))
2265 return FALSE;
2266
2267 if (!cdinfo_puts(pp, XMCD_PIPESIG "role.id"))
2268 return FALSE;
2269 if (!cdinfo_puts(pp, p->id))
2270 return FALSE;
2271
2272 if (!cdinfo_puts(pp, XMCD_PIPESIG "role.name"))
2273 return FALSE;
2274 if (!cdinfo_puts(pp, p->name))
2275 return FALSE;
2276
2277 for (q = p->child; q != NULL; q = q->next) {
2278 if (!cdinfo_puts(pp,
2279 XMCD_PIPESIG "role.subrole.new"))
2280 return FALSE;
2281
2282 if (!cdinfo_puts(pp,
2283 XMCD_PIPESIG "role.subrole.id"))
2284 return FALSE;
2285 if (!cdinfo_puts(pp, q->id))
2286 return FALSE;
2287
2288 if (!cdinfo_puts(pp,
2289 XMCD_PIPESIG "role.subrole.name"))
2290 return FALSE;
2291 if (!cdinfo_puts(pp, q->name))
2292 return FALSE;
2293 }
2294 }
2295
2296 cdinfo_rolist_initted = TRUE;
2297 return TRUE;
2298 }
2299
2300
2301 /*
2302 * cdinfo_putmatch_ents
2303 * Write multiple match elements into pipe, used by the child.
2304 *
2305 * Args:
2306 * pp - Pointer to cdinfo_pipe_t
2307 *
2308 * Return:
2309 * TRUE - success
2310 * FALSE - failure
2311 */
2312 STATIC bool_t
cdinfo_putmatch_ents(cdinfo_pipe_t * pp)2313 cdinfo_putmatch_ents(cdinfo_pipe_t *pp)
2314 {
2315 cdinfo_match_t *p;
2316
2317 for (p = cdinfo_dbp->matchlist; p != NULL; p = p->next) {
2318 if (!cdinfo_puts(pp, XMCD_PIPESIG "match.new"))
2319 return FALSE;
2320 if (!cdinfo_puts(pp, XMCD_PIPESIG "match.artist"))
2321 return FALSE;
2322 if (!cdinfo_puts(pp, p->artist))
2323 return FALSE;
2324 if (!cdinfo_puts(pp, XMCD_PIPESIG "match.title"))
2325 return FALSE;
2326 if (!cdinfo_puts(pp, p->title))
2327 return FALSE;
2328 if (!cdinfo_puts(pp, XMCD_PIPESIG "match.genre"))
2329 return FALSE;
2330 if (!cdinfo_puts(pp, p->genre))
2331 return FALSE;
2332 }
2333
2334 return TRUE;
2335 }
2336
2337
2338 /*
2339 * cdinfo_putuserreg_ents
2340 * Write user registration related elements into pipe, used by the child.
2341 *
2342 * Args:
2343 * pp - Pointer to cdinfo_pipe_t
2344 *
2345 * Return:
2346 * TRUE - success
2347 * FALSE - failure
2348 */
2349 STATIC bool_t
cdinfo_putuserreg_ents(cdinfo_pipe_t * pp)2350 cdinfo_putuserreg_ents(cdinfo_pipe_t *pp)
2351 {
2352 if (cdinfo_user_regd)
2353 return TRUE;
2354
2355 if (cdinfo_dbp->userreg.handle != NULL) {
2356 if (!cdinfo_puts(pp, XMCD_PIPESIG "userreg.handle"))
2357 return FALSE;
2358 if (!cdinfo_puts(pp, cdinfo_dbp->userreg.handle))
2359 return FALSE;
2360 }
2361 if (cdinfo_dbp->userreg.hint != NULL) {
2362 if (!cdinfo_puts(pp, XMCD_PIPESIG "userreg.hint"))
2363 return FALSE;
2364 if (!cdinfo_puts(pp, cdinfo_dbp->userreg.hint))
2365 return FALSE;
2366 }
2367 if (cdinfo_dbp->userreg.email != NULL) {
2368 if (!cdinfo_puts(pp, XMCD_PIPESIG "userreg.email"))
2369 return FALSE;
2370 if (!cdinfo_puts(pp, cdinfo_dbp->userreg.email))
2371 return FALSE;
2372 }
2373 if (cdinfo_dbp->userreg.region != NULL) {
2374 if (!cdinfo_puts(pp, XMCD_PIPESIG "userreg.region"))
2375 return FALSE;
2376 if (!cdinfo_puts(pp, cdinfo_dbp->userreg.region))
2377 return FALSE;
2378 }
2379 if (cdinfo_dbp->userreg.postal != NULL) {
2380 if (!cdinfo_puts(pp, XMCD_PIPESIG "userreg.postal"))
2381 return FALSE;
2382 if (!cdinfo_puts(pp, cdinfo_dbp->userreg.postal))
2383 return FALSE;
2384 }
2385 if (cdinfo_dbp->userreg.age != NULL) {
2386 if (!cdinfo_puts(pp, XMCD_PIPESIG "userreg.age"))
2387 return FALSE;
2388 if (!cdinfo_puts(pp, cdinfo_dbp->userreg.age))
2389 return FALSE;
2390 }
2391 if (cdinfo_dbp->userreg.gender != NULL) {
2392 if (!cdinfo_puts(pp, XMCD_PIPESIG "userreg.gender"))
2393 return FALSE;
2394 if (!cdinfo_puts(pp, cdinfo_dbp->userreg.gender))
2395 return FALSE;
2396 }
2397 if (cdinfo_dbp->userreg.allowemail) {
2398 if (!cdinfo_puts(pp, XMCD_PIPESIG "userreg.allowemail"))
2399 return FALSE;
2400 if (!cdinfo_puts(pp, "1\n"))
2401 return FALSE;
2402 }
2403 if (cdinfo_dbp->userreg.allowstats) {
2404 if (!cdinfo_puts(pp, XMCD_PIPESIG "userreg.allowstats"))
2405 return FALSE;
2406 if (!cdinfo_puts(pp, "1\n"))
2407 return FALSE;
2408 }
2409
2410 cdinfo_user_regd = TRUE;
2411 return TRUE;
2412 }
2413
2414
2415 /*
2416 * cdinfo_putdisc_ents
2417 * Write disc related elements into pipe, used by the child.
2418 *
2419 * Args:
2420 * pp - Pointer to cdinfo_pipe_t
2421 *
2422 * Return:
2423 * TRUE - success
2424 * FALSE - failure
2425 */
2426 STATIC bool_t
cdinfo_putdisc_ents(cdinfo_pipe_t * pp)2427 cdinfo_putdisc_ents(cdinfo_pipe_t *pp)
2428 {
2429 char buf[32];
2430 cdinfo_credit_t *p;
2431 cdinfo_segment_t *q;
2432
2433 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.flags"))
2434 return FALSE;
2435 (void) sprintf(buf, "%x", cdinfo_dbp->flags);
2436 if (!cdinfo_puts(pp, buf))
2437 return FALSE;
2438
2439 if (cdinfo_dbp->disc.compilation) {
2440 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.compilation"))
2441 return FALSE;
2442 if (!cdinfo_puts(pp, "1\n"))
2443 return FALSE;
2444 }
2445 if (cdinfo_dbp->disc.artistfname.dispname != NULL) {
2446 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.artistfname.dispname"))
2447 return FALSE;
2448 if (!cdinfo_puts(pp, cdinfo_dbp->disc.artistfname.dispname))
2449 return FALSE;
2450 }
2451 if (cdinfo_dbp->disc.artistfname.lastname != NULL) {
2452 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.artistfname.lastname"))
2453 return FALSE;
2454 if (!cdinfo_puts(pp, cdinfo_dbp->disc.artistfname.lastname))
2455 return FALSE;
2456 }
2457 if (cdinfo_dbp->disc.artistfname.firstname != NULL) {
2458 if (!cdinfo_puts(pp,
2459 XMCD_PIPESIG "disc.artistfname.firstname"))
2460 return FALSE;
2461 if (!cdinfo_puts(pp, cdinfo_dbp->disc.artistfname.firstname))
2462 return FALSE;
2463 }
2464 if (cdinfo_dbp->disc.artistfname.the != NULL) {
2465 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.artistfname.the"))
2466 return FALSE;
2467 if (!cdinfo_puts(pp, cdinfo_dbp->disc.artistfname.the))
2468 return FALSE;
2469 }
2470 if (cdinfo_dbp->disc.artist != NULL) {
2471 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.artist"))
2472 return FALSE;
2473 if (!cdinfo_puts(pp, cdinfo_dbp->disc.artist))
2474 return FALSE;
2475 }
2476 if (cdinfo_dbp->disc.title != NULL) {
2477 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.title"))
2478 return FALSE;
2479 if (!cdinfo_puts(pp, cdinfo_dbp->disc.title))
2480 return FALSE;
2481 }
2482 if (cdinfo_dbp->disc.sorttitle != NULL) {
2483 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.sorttitle"))
2484 return FALSE;
2485 if (!cdinfo_puts(pp, cdinfo_dbp->disc.sorttitle))
2486 return FALSE;
2487 }
2488 if (cdinfo_dbp->disc.title_the != NULL) {
2489 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.title_the"))
2490 return FALSE;
2491 if (!cdinfo_puts(pp, cdinfo_dbp->disc.title_the))
2492 return FALSE;
2493 }
2494 if (cdinfo_dbp->disc.year != NULL) {
2495 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.year"))
2496 return FALSE;
2497 if (!cdinfo_puts(pp, cdinfo_dbp->disc.year))
2498 return FALSE;
2499 }
2500 if (cdinfo_dbp->disc.label != NULL) {
2501 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.label"))
2502 return FALSE;
2503 if (!cdinfo_puts(pp, cdinfo_dbp->disc.label))
2504 return FALSE;
2505 }
2506 if (cdinfo_dbp->disc.genre != NULL) {
2507 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.genre"))
2508 return FALSE;
2509 if (!cdinfo_puts(pp, cdinfo_dbp->disc.genre))
2510 return FALSE;
2511 }
2512 if (cdinfo_dbp->disc.genre2 != NULL) {
2513 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.genre2"))
2514 return FALSE;
2515 if (!cdinfo_puts(pp, cdinfo_dbp->disc.genre2))
2516 return FALSE;
2517 }
2518 if (cdinfo_dbp->disc.dnum != NULL) {
2519 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.dnum"))
2520 return FALSE;
2521 if (!cdinfo_puts(pp, cdinfo_dbp->disc.dnum))
2522 return FALSE;
2523 }
2524 if (cdinfo_dbp->disc.tnum != NULL) {
2525 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.tnum"))
2526 return FALSE;
2527 if (!cdinfo_puts(pp, cdinfo_dbp->disc.tnum))
2528 return FALSE;
2529 }
2530 if (cdinfo_dbp->disc.region != NULL) {
2531 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.region"))
2532 return FALSE;
2533 if (!cdinfo_puts(pp, cdinfo_dbp->disc.region))
2534 return FALSE;
2535 }
2536 if (cdinfo_dbp->disc.lang != NULL) {
2537 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.lang"))
2538 return FALSE;
2539 if (!cdinfo_puts(pp, cdinfo_dbp->disc.lang))
2540 return FALSE;
2541 }
2542 if (cdinfo_dbp->disc.notes != NULL) {
2543 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.notes"))
2544 return FALSE;
2545 if (!cdinfo_puts(pp, cdinfo_dbp->disc.notes))
2546 return FALSE;
2547 if (!cdinfo_puts(pp, XMCD_PIPESIG "multi.end"))
2548 return FALSE;
2549 }
2550 if (cdinfo_dbp->disc.mediaid != NULL) {
2551 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.mediaid"))
2552 return FALSE;
2553 if (!cdinfo_puts(pp, cdinfo_dbp->disc.mediaid))
2554 return FALSE;
2555 }
2556 if (cdinfo_dbp->disc.muiid != NULL) {
2557 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.muiid"))
2558 return FALSE;
2559 if (!cdinfo_puts(pp, cdinfo_dbp->disc.muiid))
2560 return FALSE;
2561 }
2562 if (cdinfo_dbp->disc.titleuid != NULL) {
2563 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.titleuid"))
2564 return FALSE;
2565 if (!cdinfo_puts(pp, cdinfo_dbp->disc.titleuid))
2566 return FALSE;
2567 }
2568 if (cdinfo_dbp->disc.revision != NULL) {
2569 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.revision"))
2570 return FALSE;
2571 if (!cdinfo_puts(pp, cdinfo_dbp->disc.revision))
2572 return FALSE;
2573 }
2574 if (cdinfo_dbp->disc.revtag != NULL) {
2575 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.revtag"))
2576 return FALSE;
2577 if (!cdinfo_puts(pp, cdinfo_dbp->disc.revtag))
2578 return FALSE;
2579 }
2580 if (cdinfo_dbp->disc.certifier != NULL) {
2581 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.certifier"))
2582 return FALSE;
2583 if (!cdinfo_puts(pp, cdinfo_dbp->disc.certifier))
2584 return FALSE;
2585 }
2586 for (p = cdinfo_dbp->disc.credit_list; p != NULL; p = p->next) {
2587 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.credit.new"))
2588 return FALSE;
2589 if (p->crinfo.role != NULL) {
2590 if (!cdinfo_puts(pp, XMCD_PIPESIG
2591 "disc.credit.role"))
2592 return FALSE;
2593 if (!cdinfo_puts(pp, p->crinfo.role->id))
2594 return FALSE;
2595 }
2596 if (p->crinfo.name != NULL) {
2597 if (!cdinfo_puts(pp, XMCD_PIPESIG
2598 "disc.credit.name"))
2599 return FALSE;
2600 if (!cdinfo_puts(pp, p->crinfo.name))
2601 return FALSE;
2602 }
2603 if (p->crinfo.fullname.dispname != NULL) {
2604 if (!cdinfo_puts(pp, XMCD_PIPESIG
2605 "disc.credit.fullname.dispname"))
2606 return FALSE;
2607 if (!cdinfo_puts(pp, p->crinfo.fullname.dispname))
2608 return FALSE;
2609 }
2610 if (p->crinfo.fullname.lastname != NULL) {
2611 if (!cdinfo_puts(pp, XMCD_PIPESIG
2612 "disc.credit.fullname.lastname"))
2613 return FALSE;
2614 if (!cdinfo_puts(pp, p->crinfo.fullname.lastname))
2615 return FALSE;
2616 }
2617 if (p->crinfo.fullname.firstname != NULL) {
2618 if (!cdinfo_puts(pp, XMCD_PIPESIG
2619 "disc.credit.fullname.firstname"))
2620 return FALSE;
2621 if (!cdinfo_puts(pp, p->crinfo.fullname.firstname))
2622 return FALSE;
2623 }
2624 if (p->crinfo.fullname.the != NULL) {
2625 if (!cdinfo_puts(pp, XMCD_PIPESIG
2626 "disc.credit.fullname.the"))
2627 return FALSE;
2628 if (!cdinfo_puts(pp, p->crinfo.fullname.the))
2629 return FALSE;
2630 }
2631 if (p->notes != NULL) {
2632 if (!cdinfo_puts(pp, XMCD_PIPESIG
2633 "disc.credit.notes"))
2634 return FALSE;
2635 if (!cdinfo_puts(pp, p->notes))
2636 return FALSE;
2637 if (!cdinfo_puts(pp, XMCD_PIPESIG "multi.end"))
2638 return FALSE;
2639 }
2640 }
2641 for (q = cdinfo_dbp->disc.segment_list; q != NULL; q = q->next) {
2642 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.segment.new"))
2643 return FALSE;
2644 if (q->name != NULL) {
2645 if (!cdinfo_puts(pp, XMCD_PIPESIG "disc.segment.name"))
2646 return FALSE;
2647 if (!cdinfo_puts(pp, q->name))
2648 return FALSE;
2649 }
2650 if (q->notes != NULL) {
2651 if (!cdinfo_puts(pp, XMCD_PIPESIG
2652 "disc.segment.notes"))
2653 return FALSE;
2654 if (!cdinfo_puts(pp, q->notes))
2655 return FALSE;
2656 if (!cdinfo_puts(pp, XMCD_PIPESIG "multi.end"))
2657 return FALSE;
2658 }
2659 if (q->start_track != NULL) {
2660 if (!cdinfo_puts(pp, XMCD_PIPESIG
2661 "disc.segment.start_track"))
2662 return FALSE;
2663 if (!cdinfo_puts(pp, q->start_track))
2664 return FALSE;
2665 }
2666 if (q->start_frame != NULL) {
2667 if (!cdinfo_puts(pp, XMCD_PIPESIG
2668 "disc.segment.start_frame"))
2669 return FALSE;
2670 if (!cdinfo_puts(pp, q->start_frame))
2671 return FALSE;
2672 }
2673 if (q->end_track != NULL) {
2674 if (!cdinfo_puts(pp, XMCD_PIPESIG
2675 "disc.segment.end_track"))
2676 return FALSE;
2677 if (!cdinfo_puts(pp, q->end_track))
2678 return FALSE;
2679 }
2680 if (q->end_frame != NULL) {
2681 if (!cdinfo_puts(pp, XMCD_PIPESIG
2682 "disc.segment.end_frame"))
2683 return FALSE;
2684 if (!cdinfo_puts(pp, q->end_frame))
2685 return FALSE;
2686 }
2687 for (p = q->credit_list; p != NULL; p = p->next) {
2688 if (!cdinfo_puts(pp, XMCD_PIPESIG
2689 "disc.segment.credit.new"))
2690 return FALSE;
2691 if (p->crinfo.role != NULL) {
2692 if (!cdinfo_puts(pp, XMCD_PIPESIG
2693 "disc.segment.credit.role"))
2694 return FALSE;
2695 if (!cdinfo_puts(pp, p->crinfo.role->id))
2696 return FALSE;
2697 }
2698 if (p->crinfo.name != NULL) {
2699 if (!cdinfo_puts(pp, XMCD_PIPESIG
2700 "disc.segment.credit.name"))
2701 return FALSE;
2702 if (!cdinfo_puts(pp, p->crinfo.name))
2703 return FALSE;
2704 }
2705 if (p->crinfo.fullname.dispname != NULL) {
2706 if (!cdinfo_puts(pp, XMCD_PIPESIG
2707 "disc.segment.credit.fullname.dispname"))
2708 return FALSE;
2709 if (!cdinfo_puts(pp,
2710 p->crinfo.fullname.dispname))
2711 return FALSE;
2712 }
2713 if (p->crinfo.fullname.lastname != NULL) {
2714 if (!cdinfo_puts(pp, XMCD_PIPESIG
2715 "disc.segment.credit.fullname.lastname"))
2716 return FALSE;
2717 if (!cdinfo_puts(pp,
2718 p->crinfo.fullname.lastname))
2719 return FALSE;
2720 }
2721 if (p->crinfo.fullname.firstname != NULL) {
2722 if (!cdinfo_puts(pp, XMCD_PIPESIG
2723 "disc.segment.credit.fullname.firstname"))
2724 return FALSE;
2725 if (!cdinfo_puts(pp,
2726 p->crinfo.fullname.firstname))
2727 return FALSE;
2728 }
2729 if (p->crinfo.fullname.the != NULL) {
2730 if (!cdinfo_puts(pp, XMCD_PIPESIG
2731 "disc.segment.credit.fullname.the"))
2732 return FALSE;
2733 if (!cdinfo_puts(pp, p->crinfo.fullname.the))
2734 return FALSE;
2735 }
2736 if (p->notes != NULL) {
2737 if (!cdinfo_puts(pp, XMCD_PIPESIG
2738 "disc.segment.credit.notes"))
2739 return FALSE;
2740 if (!cdinfo_puts(pp, p->notes))
2741 return FALSE;
2742 if (!cdinfo_puts(pp, XMCD_PIPESIG "multi.end"))
2743 return FALSE;
2744 }
2745 }
2746 }
2747
2748 return TRUE;
2749 }
2750
2751
2752 /*
2753 * cdinfo_puttrack_ents
2754 * Write track related elements into pipe, used by the child.
2755 *
2756 * Args:
2757 * pp - Pointer to cdinfo_pipe_t
2758 * s - Pointer to the curstat_t structure
2759 *
2760 * Return:
2761 * TRUE - success
2762 * FALSE - failure
2763 */
2764 STATIC bool_t
cdinfo_puttrack_ents(cdinfo_pipe_t * pp,curstat_t * s)2765 cdinfo_puttrack_ents(cdinfo_pipe_t *pp, curstat_t *s)
2766 {
2767 int i;
2768 char buf[80];
2769 cdinfo_credit_t *p;
2770
2771 for (i = 0; i < (int) s->tot_trks; i++) {
2772 if (cdinfo_dbp->track[i].artistfname.dispname != NULL) {
2773 (void) sprintf(buf, "%strack%d.artistfname.dispname",
2774 XMCD_PIPESIG, i);
2775 if (!cdinfo_puts(pp, buf))
2776 return FALSE;
2777 if (!cdinfo_puts(pp,
2778 cdinfo_dbp->track[i].artistfname.dispname))
2779 return FALSE;
2780 }
2781 if (cdinfo_dbp->track[i].artistfname.lastname != NULL) {
2782 (void) sprintf(buf, "%strack%d.artistfname.lastname",
2783 XMCD_PIPESIG, i);
2784 if (!cdinfo_puts(pp, buf))
2785 return FALSE;
2786 if (!cdinfo_puts(pp,
2787 cdinfo_dbp->track[i].artistfname.lastname))
2788 return FALSE;
2789 }
2790 if (cdinfo_dbp->track[i].artistfname.firstname != NULL) {
2791 (void) sprintf(buf, "%strack%d.artistfname.firstname",
2792 XMCD_PIPESIG, i);
2793 if (!cdinfo_puts(pp, buf))
2794 return FALSE;
2795 if (!cdinfo_puts(pp,
2796 cdinfo_dbp->track[i].artistfname.firstname))
2797 return FALSE;
2798 }
2799 if (cdinfo_dbp->track[i].artistfname.the != NULL) {
2800 (void) sprintf(buf, "%strack%d.artistfname.the",
2801 XMCD_PIPESIG, i);
2802 if (!cdinfo_puts(pp, buf))
2803 return FALSE;
2804 if (!cdinfo_puts(pp, cdinfo_dbp->track[i].artistfname.the))
2805 return FALSE;
2806 }
2807 if (cdinfo_dbp->track[i].artist != NULL) {
2808 (void) sprintf(buf, "%strack%d.artist", XMCD_PIPESIG, i);
2809 if (!cdinfo_puts(pp, buf))
2810 return FALSE;
2811 if (!cdinfo_puts(pp, cdinfo_dbp->track[i].artist))
2812 return FALSE;
2813 }
2814 if (cdinfo_dbp->track[i].title != NULL) {
2815 (void) sprintf(buf, "%strack%d.title", XMCD_PIPESIG, i);
2816 if (!cdinfo_puts(pp, buf))
2817 return FALSE;
2818 if (!cdinfo_puts(pp, cdinfo_dbp->track[i].title))
2819 return FALSE;
2820 }
2821 if (cdinfo_dbp->track[i].sorttitle != NULL) {
2822 (void) sprintf(buf, "%strack%d.sorttitle", XMCD_PIPESIG, i);
2823 if (!cdinfo_puts(pp, buf))
2824 return FALSE;
2825 if (!cdinfo_puts(pp, cdinfo_dbp->track[i].sorttitle))
2826 return FALSE;
2827 }
2828 if (cdinfo_dbp->track[i].title_the != NULL) {
2829 (void) sprintf(buf, "%strack%d.title_the", XMCD_PIPESIG, i);
2830 if (!cdinfo_puts(pp, buf))
2831 return FALSE;
2832 if (!cdinfo_puts(pp, cdinfo_dbp->track[i].title_the))
2833 return FALSE;
2834 }
2835 if (cdinfo_dbp->track[i].year != NULL) {
2836 (void) sprintf(buf, "%strack%d.year", XMCD_PIPESIG, i);
2837 if (!cdinfo_puts(pp, buf))
2838 return FALSE;
2839 if (!cdinfo_puts(pp, cdinfo_dbp->track[i].year))
2840 return FALSE;
2841 }
2842 if (cdinfo_dbp->track[i].label != NULL) {
2843 (void) sprintf(buf, "%strack%d.label", XMCD_PIPESIG, i);
2844 if (!cdinfo_puts(pp, buf))
2845 return FALSE;
2846 if (!cdinfo_puts(pp, cdinfo_dbp->track[i].label))
2847 return FALSE;
2848 }
2849 if (cdinfo_dbp->track[i].genre != NULL) {
2850 (void) sprintf(buf, "%strack%d.genre", XMCD_PIPESIG, i);
2851 if (!cdinfo_puts(pp, buf))
2852 return FALSE;
2853 if (!cdinfo_puts(pp, cdinfo_dbp->track[i].genre))
2854 return FALSE;
2855 }
2856 if (cdinfo_dbp->track[i].genre2 != NULL) {
2857 (void) sprintf(buf, "%strack%d.genre2", XMCD_PIPESIG, i);
2858 if (!cdinfo_puts(pp, buf))
2859 return FALSE;
2860 if (!cdinfo_puts(pp, cdinfo_dbp->track[i].genre2))
2861 return FALSE;
2862 }
2863 if (cdinfo_dbp->track[i].bpm != NULL) {
2864 (void) sprintf(buf, "%strack%d.bpm", XMCD_PIPESIG, i);
2865 if (!cdinfo_puts(pp, buf))
2866 return FALSE;
2867 if (!cdinfo_puts(pp, cdinfo_dbp->track[i].bpm))
2868 return FALSE;
2869 }
2870 if (cdinfo_dbp->track[i].notes != NULL) {
2871 (void) sprintf(buf, "%strack%d.notes", XMCD_PIPESIG, i);
2872 if (!cdinfo_puts(pp, buf))
2873 return FALSE;
2874 if (!cdinfo_puts(pp, cdinfo_dbp->track[i].notes))
2875 return FALSE;
2876 (void) sprintf(buf, "%smulti.end", XMCD_PIPESIG);
2877 if (!cdinfo_puts(pp, buf))
2878 return FALSE;
2879 }
2880 if (cdinfo_dbp->track[i].isrc != NULL) {
2881 (void) sprintf(buf, "%strack%d.isrc", XMCD_PIPESIG, i);
2882 if (!cdinfo_puts(pp, buf))
2883 return FALSE;
2884 if (!cdinfo_puts(pp, cdinfo_dbp->track[i].isrc))
2885 return FALSE;
2886 }
2887
2888 for (p = cdinfo_dbp->track[i].credit_list; p != NULL; p = p->next){
2889 (void) sprintf(buf, "%strack%d.credit.new", XMCD_PIPESIG, i);
2890 if (!cdinfo_puts(pp, buf))
2891 return FALSE;
2892 if (p->crinfo.role != NULL) {
2893 (void) sprintf(buf, "%strack%d.credit.role",
2894 XMCD_PIPESIG, i);
2895 if (!cdinfo_puts(pp, buf))
2896 return FALSE;
2897 if (!cdinfo_puts(pp, p->crinfo.role->id))
2898 return FALSE;
2899 }
2900 if (p->crinfo.name != NULL) {
2901 (void) sprintf(buf, "%strack%d.credit.name",
2902 XMCD_PIPESIG, i);
2903 if (!cdinfo_puts(pp, buf))
2904 return FALSE;
2905 if (!cdinfo_puts(pp, p->crinfo.name))
2906 return FALSE;
2907 }
2908 if (p->crinfo.fullname.dispname != NULL) {
2909 (void) sprintf(buf,
2910 "%strack%d.credit.fullname.dispname",
2911 XMCD_PIPESIG, i);
2912 if (!cdinfo_puts(pp, buf))
2913 return FALSE;
2914 if (!cdinfo_puts(pp, p->crinfo.fullname.dispname))
2915 return FALSE;
2916 }
2917 if (p->crinfo.fullname.lastname != NULL) {
2918 (void) sprintf(buf,
2919 "%strack%d.credit.fullname.lastname",
2920 XMCD_PIPESIG, i);
2921 if (!cdinfo_puts(pp, buf))
2922 return FALSE;
2923 if (!cdinfo_puts(pp, p->crinfo.fullname.lastname))
2924 return FALSE;
2925 }
2926 if (p->crinfo.fullname.firstname != NULL) {
2927 (void) sprintf(buf,
2928 "%strack%d.credit.fullname.firstname",
2929 XMCD_PIPESIG, i);
2930 if (!cdinfo_puts(pp, buf))
2931 return FALSE;
2932 if (!cdinfo_puts(pp, p->crinfo.fullname.firstname))
2933 return FALSE;
2934 }
2935 if (p->crinfo.fullname.the != NULL) {
2936 (void) sprintf(buf,
2937 "%strack%d.credit.fullname.the",
2938 XMCD_PIPESIG, i);
2939 if (!cdinfo_puts(pp, buf))
2940 return FALSE;
2941 if (!cdinfo_puts(pp, p->crinfo.fullname.the))
2942 return FALSE;
2943 }
2944 if (p->notes != NULL) {
2945 (void) sprintf(buf, "%strack%d.credit.notes",
2946 XMCD_PIPESIG, i);
2947 if (!cdinfo_puts(pp, buf))
2948 return FALSE;
2949 if (!cdinfo_puts(pp, p->notes))
2950 return FALSE;
2951 if (!cdinfo_puts(pp, XMCD_PIPESIG "multi.end"))
2952 return FALSE;
2953 }
2954 }
2955 }
2956
2957 return TRUE;
2958 }
2959
2960
2961 /*
2962 * cdinfo_flushpipe
2963 * Flush the pipe write cache.
2964 *
2965 * Args:
2966 * pp - Pointer to the cdinfo_pipe_t structure.
2967 *
2968 * Return:
2969 * TRUE - success
2970 * FALSE - failure
2971 */
2972 bool_t
cdinfo_flushpipe(cdinfo_pipe_t * pp)2973 cdinfo_flushpipe(cdinfo_pipe_t *pp)
2974 {
2975 if (pp == NULL)
2976 return FALSE;
2977
2978 if (pp->w.cache != NULL && pp->w.pos > 0) {
2979 unsigned char *p;
2980 int resid,
2981 n = 0;
2982
2983 /* Flush write cache */
2984 p = pp->w.cache;
2985 for (resid = pp->w.pos; resid > 0; resid -= n) {
2986 if ((n = write(pp->w.fd, p, resid)) < 0) {
2987 pp->w.pos = 0;
2988 return FALSE;
2989 }
2990 p += n;
2991 }
2992 pp->w.pos = 0;
2993 }
2994
2995 return TRUE;
2996 }
2997
2998
2999 /*
3000 * cdinfo_openpipe
3001 * Create a one-way pipe and set up for buffered I/O
3002 *
3003 * Args:
3004 * dir - pipe data direction: CDINFO_DATAIN or CDINFO_DATAOUT
3005 * (from the perspective of parent process)
3006 *
3007 * Return:
3008 * A pointer to the cdinfo_pipe_t structure which contains pipe
3009 * file descriptors and FILE stream pointers.
3010 */
3011 cdinfo_pipe_t *
cdinfo_openpipe(int dir)3012 cdinfo_openpipe(int dir)
3013 {
3014 int pfd[2];
3015 cdinfo_pipe_t *pp;
3016
3017 /* Allocate cdinfo_pipe_t */
3018 pp = (cdinfo_pipe_t *)(void *) MEM_ALLOC(
3019 "cdinfo_pipe_t",
3020 sizeof(cdinfo_pipe_t)
3021 );
3022 if (pp == NULL) {
3023 CDINFO_FATAL(app_data.str_nomemory);
3024 return NULL;
3025 }
3026
3027 /* Create pipe */
3028 if (PIPE(pfd) < 0) {
3029 MEM_FREE(pp);
3030 return NULL;
3031 }
3032
3033 pp->dir = dir;
3034 pp->r.fd = pfd[0];
3035 pp->w.fd = pfd[1];
3036 pp->r.rw = O_RDONLY;
3037 pp->w.rw = O_WRONLY;
3038 pp->r.pos = pp->w.pos = 0;
3039 pp->r.cnt = pp->w.cnt = 0;
3040
3041 /* The caches are allocated on first I/O */
3042 pp->r.cache = pp->w.cache = NULL;
3043
3044 return (pp);
3045 }
3046
3047
3048 /*
3049 * cdinfo_closepipe
3050 * Close the pipe created with cdinfo_openpipe.
3051 *
3052 * Args:
3053 * pp - Pointer to the cdinfo_pipe_t structure.
3054 *
3055 * Return:
3056 * TRUE - success
3057 * FALSE - failure
3058 */
3059 bool_t
cdinfo_closepipe(cdinfo_pipe_t * pp)3060 cdinfo_closepipe(cdinfo_pipe_t *pp)
3061 {
3062 int fd;
3063
3064 if (pp == NULL)
3065 return FALSE;
3066
3067 if (pp->w.cache != NULL && pp->w.pos > 0) {
3068 unsigned char *p;
3069 int resid,
3070 n = 0;
3071
3072 /* Flush write cache */
3073 p = pp->w.cache;
3074 for (resid = pp->w.pos; resid > 0; resid -= n) {
3075 if ((n = write(pp->w.fd, p, resid)) < 0) {
3076 pp->w.pos = 0;
3077 return FALSE;
3078 }
3079 p += n;
3080 }
3081 pp->w.pos = 0;
3082 }
3083
3084 /* Close file descriptor */
3085 if (pp->dir == CDINFO_DATAIN) {
3086 if (cdinfo_ischild)
3087 fd = pp->w.fd;
3088 else
3089 fd = pp->r.fd;
3090 }
3091 else {
3092 if (cdinfo_ischild)
3093 fd = pp->r.fd;
3094 else
3095 fd = pp->w.fd;
3096 }
3097 if (fd != -1)
3098 (void) close(fd);
3099
3100 /* Free cache storage */
3101 if (pp->r.cache != NULL)
3102 MEM_FREE(pp->r.cache);
3103 if (pp->w.cache != NULL)
3104 MEM_FREE(pp->w.cache);
3105
3106 /* Free cdinfo_pipe_t structure */
3107 MEM_FREE(pp);
3108
3109 return TRUE;
3110 }
3111
3112
3113 /*
3114 * cdinfo_write_datapipe
3115 * Write incore CD information into pipe. Used by child process.
3116 *
3117 * Args:
3118 * pp - Pointer to the cdinfo_pipe_t structure.
3119 * s - Pointer to the curstat_t structure.
3120 *
3121 * Return:
3122 * TRUE - Success
3123 * FALSE - Failure
3124 */
3125 bool_t
cdinfo_write_datapipe(cdinfo_pipe_t * pp,curstat_t * s)3126 cdinfo_write_datapipe(cdinfo_pipe_t *pp, curstat_t *s)
3127 {
3128 if (!cdinfo_putctrl_ents(pp))
3129 return FALSE;
3130
3131 if (!cdinfo_putglist_ents(pp))
3132 return FALSE;
3133
3134 if (!cdinfo_putrelist_ents(pp))
3135 return FALSE;
3136
3137 if (!cdinfo_putlanglist_ents(pp))
3138 return FALSE;
3139
3140 if (!cdinfo_putrolist_ents(pp))
3141 return FALSE;
3142
3143 if (!cdinfo_putuserreg_ents(pp))
3144 return FALSE;
3145
3146 if (cdinfo_dbp->matchlist != NULL) {
3147 /* Fuzzy matches */
3148 if (!cdinfo_putmatch_ents(pp))
3149 return FALSE;
3150 }
3151 else {
3152 /* Exact match */
3153 if (!cdinfo_putdisc_ents(pp))
3154 return FALSE;
3155
3156 if (!cdinfo_puttrack_ents(pp, s))
3157 return FALSE;
3158 }
3159
3160 /* URLs */
3161 if (!cdinfo_puturl_ents(pp))
3162 return FALSE;
3163
3164 if (!cdinfo_puts(pp, XMCD_PIPESIG "end"))
3165 return FALSE;
3166
3167 /* Flush write cache in pipe */
3168 if (!cdinfo_flushpipe(pp))
3169 return FALSE;
3170
3171 return TRUE;
3172 }
3173
3174
3175 /*
3176 * cdinfo_read_datapipe
3177 * Read CDDB data from pipe and update in-core structures.
3178 * Used by parent process.
3179 *
3180 * Args:
3181 * pp - Pointer to the cdinfo_pipe_t structure.
3182 *
3183 * Return:
3184 * TRUE - Success
3185 * FALSE - Failure
3186 */
3187 bool_t
cdinfo_read_datapipe(cdinfo_pipe_t * pp)3188 cdinfo_read_datapipe(cdinfo_pipe_t *pp)
3189 {
3190 int n;
3191 char *key;
3192 static char buf[2048];
3193
3194 n = strlen(XMCD_PIPESIG);
3195 key = &buf[n];
3196 while (cdinfo_gets(pp, buf, sizeof(buf))) {
3197 if (strncmp(buf, XMCD_PIPESIG, n) == 0) {
3198 buf[strlen(buf) - 1] = '\0'; /* Zap newline */
3199
3200 if (strncmp(key, "disc", 4) == 0 &&
3201 !cdinfo_getdisc_ents(pp, key + 4)) {
3202 return FALSE;
3203 }
3204 else if (strncmp(key, "track", 5) == 0 &&
3205 !cdinfo_gettrack_ents(pp, key + 5)) {
3206 return FALSE;
3207 }
3208 else if (strncmp(key, "url", 3) == 0 &&
3209 !cdinfo_geturl_ents(pp, key + 3)) {
3210 return FALSE;
3211 }
3212 else if (strncmp(key, "genre", 5) == 0 &&
3213 !cdinfo_getglist_ents(pp, key + 5)) {
3214 return FALSE;
3215 }
3216 else if (strncmp(key, "region", 6) == 0 &&
3217 !cdinfo_getrelist_ents(pp, key + 6)) {
3218 return FALSE;
3219 }
3220 else if (strncmp(key, "lang", 4) == 0 &&
3221 !cdinfo_getlanglist_ents(pp, key + 4)) {
3222 return FALSE;
3223 }
3224 else if (strncmp(key, "role", 4) == 0 &&
3225 !cdinfo_getrolist_ents(pp, key + 4)) {
3226 return FALSE;
3227 }
3228 else if (strncmp(key, "match", 5) == 0 &&
3229 !cdinfo_getmatch_ents(pp, key + 5)) {
3230 return FALSE;
3231 }
3232 else if (strncmp(key, "userreg", 7) == 0 &&
3233 !cdinfo_getuserreg_ents(pp, key + 7)) {
3234 return FALSE;
3235 }
3236 else if (strncmp(key, "control", 7) == 0 &&
3237 !cdinfo_getctrl_ents(pp, key + 7)) {
3238 return FALSE;
3239 }
3240 else if (strcmp(key, "end") == 0) {
3241 break;
3242 }
3243 }
3244 else {
3245 /* Unexpected data */
3246 return FALSE;
3247 }
3248 }
3249
3250 return TRUE;
3251 }
3252
3253
3254 /*
3255 * cdinfo_write_selpipe
3256 * Write multiple match selection to pipe. Used by parent process.
3257 *
3258 * Args:
3259 * pp - Pointer to the cdinfo_pipe_t structure.
3260 *
3261 * Return:
3262 * TRUE - Success
3263 * FALSE - Failure
3264 */
3265 bool_t
cdinfo_write_selpipe(cdinfo_pipe_t * pp)3266 cdinfo_write_selpipe(cdinfo_pipe_t *pp)
3267 {
3268 char buf[16];
3269
3270 if (!cdinfo_puts(pp, XMCD_PIPESIG "match.tag"))
3271 return FALSE;
3272
3273 (void) sprintf(buf, "%ld", cdinfo_dbp->match_tag);
3274 if (!cdinfo_puts(pp, buf))
3275 return FALSE;
3276
3277 if (!cdinfo_puts(pp, XMCD_PIPESIG "end"))
3278 return FALSE;
3279
3280 /* Flush write cache in pipe */
3281 if (!cdinfo_flushpipe(pp))
3282 return FALSE;
3283
3284 return TRUE;
3285 }
3286
3287
3288 /*
3289 * cdinfo_read_selpipe
3290 * Read multiple match selection from pipe. Used by child process.
3291 *
3292 * Args:
3293 * pp - Pointer to the cdinfo_pipe_t structure.
3294 *
3295 * Return:
3296 * TRUE - Success
3297 * FALSE - Failure
3298 */
3299 bool_t
cdinfo_read_selpipe(cdinfo_pipe_t * pp)3300 cdinfo_read_selpipe(cdinfo_pipe_t *pp)
3301 {
3302 int n;
3303 char *key,
3304 *str;
3305 static char buf[80];
3306
3307 n = strlen(XMCD_PIPESIG);
3308 key = &buf[n];
3309 while (cdinfo_gets(pp, buf, sizeof(buf))) {
3310 if (strncmp(buf, XMCD_PIPESIG, n) == 0) {
3311 buf[strlen(buf) - 1] = '\0'; /* Zap newline */
3312
3313 if (strncmp(key, "match.tag", 9) == 0) {
3314 str = NULL;
3315 if (!cdinfo_getline(pp, "match.tag", &str))
3316 return FALSE;
3317
3318 if (str != NULL) {
3319 cdinfo_dbp->match_tag = atol(str);
3320 MEM_FREE(str);
3321 }
3322 }
3323 else if (strcmp(key, "end") == 0) {
3324 break;
3325 }
3326 }
3327 else {
3328 /* Unexpected data */
3329 return FALSE;
3330 }
3331 }
3332
3333 return TRUE;
3334 }
3335
3336 #endif /* SYNCHRONOUS */
3337
3338
3339 /*
3340 * cdinfo_tocstr
3341 * Return a text string containing the CD's TOC frame offset
3342 * information suitable for use with the CDDB service.
3343 *
3344 * Args:
3345 * s - Pointer to the curstat_t structure.
3346 *
3347 * Return:
3348 * The TOC text string.
3349 */
3350 char *
cdinfo_tocstr(curstat_t * s)3351 cdinfo_tocstr(curstat_t *s)
3352 {
3353 int i;
3354 static char toc[512];
3355
3356 toc[0] = '\0';
3357
3358 for (i = 0; i <= (int) s->tot_trks; i++) {
3359 (void) sprintf(toc, "%s%s%d", toc, (i == 0) ? "" : " ",
3360 (((s->trkinfo[i].min * 60) +
3361 s->trkinfo[i].sec) * FRAME_PER_SEC) +
3362 s->trkinfo[i].frame);
3363 }
3364
3365 return (toc);
3366 }
3367
3368
3369 /*
3370 * cdinfo_get_str
3371 * CDDB object string property retrieval handler.
3372 *
3373 * Args:
3374 * funcname - The name of the CDDB service function
3375 * func - CDDB service function to call
3376 * objp - CDDB object
3377 * datap - Return string property
3378 *
3379 * Return:
3380 * TRUE - Success
3381 * FALSE - Failure
3382 */
3383 STATIC bool_t
cdinfo_get_str(char * funcname,CddbResult (* func)(),void * objp,char ** datap)3384 cdinfo_get_str(
3385 char *funcname,
3386 CddbResult (*func)(),
3387 void *objp,
3388 char **datap
3389 )
3390 {
3391 CddbResult ret;
3392 char *str;
3393
3394 DBGPRN(DBG_CDI)(errfp, "%s: ", funcname);
3395 ret = (*func)(objp, &str);
3396 DBGPRN(DBG_CDI)(errfp, "0x%lx %s\n", ret, str == NULL ? "-" : str);
3397
3398 cdinfo_set_errstr(ret);
3399
3400 return (util_newstr(datap, str));
3401 }
3402
3403
3404 /*
3405 * cdinfo_get_bool
3406 * CDDB object boolean property retrieval handler.
3407 *
3408 * Args:
3409 * funcname - The name of the CDDB service function
3410 * func - CDDB service function to call
3411 * objp - CDDB object
3412 * datap - Return boolean property
3413 *
3414 * Return:
3415 * TRUE - Success
3416 * FALSE - Failure
3417 */
3418 STATIC bool_t
cdinfo_get_bool(char * funcname,CddbResult (* func)(),void * objp,bool_t * datap)3419 cdinfo_get_bool(
3420 char *funcname,
3421 CddbResult (*func)(),
3422 void *objp,
3423 bool_t *datap
3424 )
3425 {
3426 CddbResult ret;
3427 CddbBoolean b;
3428
3429 DBGPRN(DBG_CDI)(errfp, "%s: ", funcname);
3430 ret = (*func)(objp, &b);
3431 DBGPRN(DBG_CDI)(errfp, "0x%lx %s\n", ret, b ? "Yes" : "No");
3432
3433 cdinfo_set_errstr(ret);
3434
3435 *datap = (bool_t) b;
3436 return TRUE;
3437 }
3438
3439
3440 /*
3441 * cdinfo_get_fullname
3442 * CDDB object fullname property retrieval handler.
3443 *
3444 * Args:
3445 * funcname - The name of the CDDB service function
3446 * func - CDDB service function to call
3447 * objp - CDDB object
3448 * dispname - Return name string
3449 * lastname - Return last name string
3450 * firstname - Return first name string
3451 * the - Return "the"
3452 *
3453 * Return:
3454 * TRUE - Success
3455 * FALSE - Failure
3456 */
3457 STATIC bool_t
cdinfo_get_fullname(char * funcname,CddbResult (* func)(),void * objp,char ** dispname,char ** lastname,char ** firstname,char ** the)3458 cdinfo_get_fullname(
3459 char *funcname,
3460 CddbResult (*func)(),
3461 void *objp,
3462 char **dispname,
3463 char **lastname,
3464 char **firstname,
3465 char **the
3466 )
3467 {
3468 CddbResult ret;
3469 CddbFullNamePtr f;
3470
3471 DBGPRN(DBG_CDI)(errfp, "%s: ", funcname);
3472 ret = (*func)(objp, &f);
3473 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
3474
3475 cdinfo_set_errstr(ret);
3476
3477 if (ret != Cddb_OK || f == NULL) {
3478 *dispname = *lastname = *firstname = *the = NULL;
3479 }
3480 else {
3481 if (!cdinfo_get_str(" CddbFullName_GetName",
3482 CddbFullName_GetName, f,
3483 dispname)) {
3484 CddbReleaseObject(f);
3485 return FALSE;
3486 }
3487
3488 if (!cdinfo_get_str(" CddbFullName_GetLastName",
3489 CddbFullName_GetLastName, f,
3490 lastname)) {
3491 CddbReleaseObject(f);
3492 return FALSE;
3493 }
3494 if (!cdinfo_get_str(" CddbFullName_GetFirstName",
3495 CddbFullName_GetFirstName, f,
3496 firstname)) {
3497 CddbReleaseObject(f);
3498 return FALSE;
3499 }
3500 if (!cdinfo_get_str(" CddbFullName_GetThe",
3501 CddbFullName_GetThe, f, the)) {
3502 CddbReleaseObject(f);
3503 return FALSE;
3504 }
3505 CddbReleaseObject(f);
3506 }
3507 return TRUE;
3508 }
3509
3510
3511 /*
3512 * cdinfo_put_str
3513 * CDDB object string property put handler.
3514 *
3515 * Args:
3516 * funcname - The name of the CDDB service function
3517 * func - CDDB service function to call
3518 * objp - CDDB object
3519 * datap - String property to put
3520 *
3521 * Return:
3522 * TRUE - Success
3523 * FALSE - Failure
3524 */
3525 STATIC bool_t
cdinfo_put_str(char * funcname,CddbResult (* func)(),void * objp,char * datap)3526 cdinfo_put_str(
3527 char *funcname,
3528 CddbResult (*func)(),
3529 void *objp,
3530 char *datap
3531 )
3532 {
3533 CddbResult ret;
3534
3535 DBGPRN(DBG_CDI)(errfp, "%s: ", funcname);
3536 ret = (*func)(objp, (CddbStr) datap);
3537 DBGPRN(DBG_CDI)(errfp, "0x%lx", ret);
3538
3539 cdinfo_set_errstr(ret);
3540
3541 if (util_strstr(funcname, "Password") == NULL) {
3542 DBGPRN(DBG_CDI)(errfp, " %s\n", datap == NULL ? "-" : datap);
3543 }
3544 else {
3545 /* Don't show any password related strings in debug output */
3546 DBGPRN(DBG_CDI)(errfp, "\n");
3547 }
3548
3549 return (ret == Cddb_OK);
3550 }
3551
3552
3553 /*
3554 * cdinfo_put_fullname
3555 * CDDB object fullname property put handler.
3556 *
3557 * Args:
3558 * funcname - The name of the CDDB service function
3559 * func - CDDB service function to call
3560 * objp - CDDB object
3561 * dispname - Return name string
3562 * lastname - Return last name string
3563 * firstname - Return first name string
3564 * the - Return "the"
3565 *
3566 * Return:
3567 * TRUE - Success
3568 * FALSE - Failure
3569 */
3570 STATIC bool_t
cdinfo_put_fullname(char * funcname,CddbResult (* func)(),void * objp,char * dispname,char * lastname,char * firstname,char * the)3571 cdinfo_put_fullname(
3572 char *funcname,
3573 CddbResult (*func)(),
3574 void *objp,
3575 char *dispname,
3576 char *lastname,
3577 char *firstname,
3578 char *the
3579 )
3580 {
3581 CddbResult ret;
3582 CddbFullNamePtr f;
3583
3584 if ((f = (CddbFullNamePtr) CddbCreateObject(CddbFullNameType)) == NULL)
3585 return FALSE;
3586
3587 if (!cdinfo_put_str(" CddbFullName_PutName",
3588 CddbFullName_PutName, f, dispname)) {
3589 CddbReleaseObject(f);
3590 return FALSE;
3591 }
3592
3593 if (!cdinfo_put_str(" CddbFullName_PutLastName",
3594 CddbFullName_PutLastName, f, lastname)) {
3595 CddbReleaseObject(f);
3596 return FALSE;
3597 }
3598 if (!cdinfo_put_str(" CddbFullName_PutFirstName",
3599 CddbFullName_PutFirstName, f, firstname)) {
3600 CddbReleaseObject(f);
3601 return FALSE;
3602 }
3603 if (!cdinfo_put_str(" CddbFullName_PutThe",
3604 CddbFullName_PutThe, f, the)) {
3605 CddbReleaseObject(f);
3606 return FALSE;
3607 }
3608
3609 DBGPRN(DBG_CDI)(errfp, "%s: ", funcname);
3610 ret = (*func)(objp, f);
3611 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
3612
3613 cdinfo_set_errstr(ret);
3614
3615 CddbReleaseObject(f);
3616 return (ret == Cddb_OK);
3617 }
3618
3619
3620 /*
3621 * cdinfo_check_userreg
3622 * Check CDDB user registration and update structures
3623 *
3624 * Args:
3625 * cp - cdinfo_cddb_t pointer for the CDDB connection
3626 *
3627 * Return:
3628 * TRUE - success
3629 * FALSE - failure
3630 */
3631 STATIC bool_t
cdinfo_check_userreg(cdinfo_cddb_t * cp)3632 cdinfo_check_userreg(cdinfo_cddb_t *cp)
3633 {
3634 CddbUserInfoPtr uip = NULL;
3635 CddbResult ret;
3636 CddbBoolean registered = 0;
3637 bool_t yn;
3638
3639 /* Check if user is registered */
3640 DBGPRN(DBG_CDI)(errfp, "CddbControl_IsRegistered: ");
3641 ret = CddbControl_IsRegistered(cp->ctrlp, 0, ®istered);
3642 DBGPRN(DBG_CDI)(errfp, "0x%lx %s\n", ret, registered ? "Yes" : "No");
3643
3644 cdinfo_set_errstr(ret);
3645
3646 if (!registered) {
3647 DBGPRN(DBG_CDI)(errfp, "User is not registered with CDDB.\n");
3648 return FALSE;
3649 }
3650
3651 DBGPRN(DBG_CDI)(errfp, "CddbControl_GetUserInfo: ");
3652 ret = CddbControl_GetUserInfo(cp->ctrlp, &uip);
3653 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
3654
3655 cdinfo_set_errstr(ret);
3656
3657 if (ret != Cddb_OK || uip == NULL)
3658 return FALSE;
3659
3660 if (!cdinfo_get_str("CddbUserInfo_GetUserHandle",
3661 CddbUserInfo_GetUserHandle, uip,
3662 &cdinfo_dbp->userreg.handle)) {
3663 CddbReleaseObject(uip);
3664 return FALSE;
3665 }
3666
3667 DBGPRN(DBG_CDI)(errfp, "User \"%s\" is registered.\n",
3668 cdinfo_dbp->userreg.handle == NULL ?
3669 "(null)" : cdinfo_dbp->userreg.handle);
3670
3671 if (!cdinfo_get_str("CddbUserInfo_GetPasswordHint",
3672 CddbUserInfo_GetPasswordHint, uip,
3673 &cdinfo_dbp->userreg.hint)) {
3674 CddbReleaseObject(uip);
3675 return FALSE;
3676 }
3677 if (!cdinfo_get_str("CddbUserInfo_GetEmailAddress",
3678 CddbUserInfo_GetEmailAddress, uip,
3679 &cdinfo_dbp->userreg.email)) {
3680 CddbReleaseObject(uip);
3681 return FALSE;
3682 }
3683 if (!cdinfo_get_str("CddbUserInfo_GetRegionId",
3684 CddbUserInfo_GetRegionId, uip,
3685 &cdinfo_dbp->userreg.region)) {
3686 CddbReleaseObject(uip);
3687 return FALSE;
3688 }
3689 if (!cdinfo_get_str("CddbUserInfo_GetPostalCode",
3690 CddbUserInfo_GetPostalCode, uip,
3691 &cdinfo_dbp->userreg.postal)) {
3692 CddbReleaseObject(uip);
3693 return FALSE;
3694 }
3695 if (!cdinfo_get_str("CddbUserInfo_GetAge",
3696 CddbUserInfo_GetAge, uip,
3697 &cdinfo_dbp->userreg.age)) {
3698 CddbReleaseObject(uip);
3699 return FALSE;
3700 }
3701 if (!cdinfo_get_str("CddbUserInfo_GetSex",
3702 CddbUserInfo_GetSex, uip,
3703 &cdinfo_dbp->userreg.gender)) {
3704 CddbReleaseObject(uip);
3705 return FALSE;
3706 }
3707 if (!cdinfo_get_bool("CddbUserInfo_GetAllowEmail",
3708 CddbUserInfo_GetAllowEmail, uip, &yn)) {
3709 CddbReleaseObject(uip);
3710 return FALSE;
3711 }
3712 cdinfo_dbp->userreg.allowemail = (bool_t) yn;
3713 if (!cdinfo_get_bool("CddbUserInfo_GetAllowStats",
3714 CddbUserInfo_GetAllowStats, uip, &yn)) {
3715 CddbReleaseObject(uip);
3716 return FALSE;
3717 }
3718 cdinfo_dbp->userreg.allowstats = (bool_t) yn;
3719
3720 CddbReleaseObject(uip);
3721 return TRUE;
3722 }
3723
3724
3725 /*
3726 * cdinfo_allocinit_genre
3727 * CDDB genre information initialization routine
3728 *
3729 * Args:
3730 * genrep - CddbGenre object
3731 * ret - cddb_genre_t return structure
3732 * sub - Whether a sub-genre is being processed
3733 *
3734 * Return:
3735 * TRUE - Success
3736 * FALSE - Failure
3737 */
3738 STATIC bool_t
cdinfo_allocinit_genre(CddbGenrePtr genrep,cdinfo_genre_t ** ret,bool_t sub)3739 cdinfo_allocinit_genre(CddbGenrePtr genrep, cdinfo_genre_t **ret, bool_t sub)
3740 {
3741 cdinfo_genre_t *p;
3742
3743 *ret = NULL;
3744
3745 p = (cdinfo_genre_t *)(void *) MEM_ALLOC("genre",
3746 sizeof(cdinfo_genre_t)
3747 );
3748 if (p == NULL) {
3749 CDINFO_FATAL(app_data.str_nomemory);
3750 return FALSE;
3751 }
3752 (void) memset(p, 0, sizeof(cdinfo_genre_t));
3753
3754 /* Genre ID */
3755 if (!cdinfo_get_str(sub ? " CddbGenre_GetId" :
3756 " CddbGenre_GetId",
3757 CddbGenre_GetId,
3758 genrep, &p->id)) {
3759 return FALSE;
3760 }
3761
3762 /* Genre name */
3763 if (!cdinfo_get_str(sub ? " CddbGenre_GetName" :
3764 " CddbGenre_GetName",
3765 CddbGenre_GetName,
3766 genrep, &p->name)) {
3767 return FALSE;
3768 }
3769
3770 *ret = p;
3771 return TRUE;
3772 }
3773
3774
3775 /*
3776 * cdinfo_allocinit_region
3777 * CDDB region information initialization routine
3778 *
3779 * Args:
3780 * regionp - CddbRegion object
3781 * ret - cddb_region_t return structure
3782 *
3783 * Return:
3784 * TRUE - Success
3785 * FALSE - Failure
3786 */
3787 STATIC bool_t
cdinfo_allocinit_region(CddbRegionPtr regionp,cdinfo_region_t ** ret)3788 cdinfo_allocinit_region(CddbRegionPtr regionp, cdinfo_region_t **ret)
3789 {
3790 cdinfo_region_t *p;
3791
3792 *ret = NULL;
3793
3794 p = (cdinfo_region_t *)(void *) MEM_ALLOC("region",
3795 sizeof(cdinfo_region_t)
3796 );
3797 if (p == NULL) {
3798 CDINFO_FATAL(app_data.str_nomemory);
3799 return FALSE;
3800 }
3801 (void) memset(p, 0, sizeof(cdinfo_region_t));
3802
3803 /* Region ID */
3804 if (!cdinfo_get_str(" CddbRegion_GetId",
3805 CddbRegion_GetId,
3806 regionp, &p->id)) {
3807 return FALSE;
3808 }
3809
3810 /* Region name */
3811 if (!cdinfo_get_str(" CddbRegion_GetName",
3812 CddbRegion_GetName,
3813 regionp, &p->name)) {
3814 return FALSE;
3815 }
3816
3817 *ret = p;
3818 return TRUE;
3819 }
3820
3821
3822 /*
3823 * cdinfo_allocinit_lang
3824 * CDDB language information initialization routine
3825 *
3826 * Args:
3827 * langp - CddbLanguage object
3828 * ret - cddb_lang_t return structure
3829 *
3830 * Return:
3831 * TRUE - Success
3832 * FALSE - Failure
3833 */
3834 STATIC bool_t
cdinfo_allocinit_lang(CddbLanguagePtr langp,cdinfo_lang_t ** ret)3835 cdinfo_allocinit_lang(CddbLanguagePtr langp, cdinfo_lang_t **ret)
3836 {
3837 cdinfo_lang_t *p;
3838
3839 *ret = NULL;
3840
3841 p = (cdinfo_lang_t *)(void *) MEM_ALLOC("lang",
3842 sizeof(cdinfo_lang_t)
3843 );
3844 if (p == NULL) {
3845 CDINFO_FATAL(app_data.str_nomemory);
3846 return FALSE;
3847 }
3848 (void) memset(p, 0, sizeof(cdinfo_lang_t));
3849
3850 /* Language ID */
3851 if (!cdinfo_get_str(" CddbLanguage_GetId",
3852 CddbLanguage_GetId,
3853 langp, &p->id)) {
3854 return FALSE;
3855 }
3856
3857 /* Language name */
3858 if (!cdinfo_get_str(" CddbLanguage_GetName",
3859 CddbLanguage_GetName,
3860 langp, &p->name)) {
3861 return FALSE;
3862 }
3863
3864 *ret = p;
3865 return TRUE;
3866 }
3867
3868
3869 /*
3870 * cdinfo_allocinit_role
3871 * CDDB role information initialization routine
3872 *
3873 * Args:
3874 * rolep - CddbRole object
3875 * ret - cddb_role_t return structure
3876 *
3877 * Return:
3878 * TRUE - Success
3879 * FALSE - Failure
3880 */
3881 STATIC bool_t
cdinfo_allocinit_role(CddbRolePtr rolep,cdinfo_role_t ** ret)3882 cdinfo_allocinit_role(CddbRolePtr rolep, cdinfo_role_t **ret)
3883 {
3884 cdinfo_role_t *p;
3885
3886 *ret = NULL;
3887
3888 p = (cdinfo_role_t *)(void *) MEM_ALLOC("role",
3889 sizeof(cdinfo_role_t)
3890 );
3891 if (p == NULL) {
3892 CDINFO_FATAL(app_data.str_nomemory);
3893 return FALSE;
3894 }
3895 (void) memset(p, 0, sizeof(cdinfo_role_t));
3896
3897 /* Role ID */
3898 if (!cdinfo_get_str(" CddbRole_GetId",
3899 CddbRole_GetId, rolep, &p->id)) {
3900 return FALSE;
3901 }
3902
3903 /* Role name */
3904 if (!cdinfo_get_str(" CddbRole_GetName",
3905 CddbRole_GetName, rolep, &p->name)) {
3906 return FALSE;
3907 }
3908
3909 *ret = p;
3910 return TRUE;
3911 }
3912
3913
3914 /*
3915 * cdinfo_discinfo_query
3916 * Query CDDB for album information
3917 *
3918 * Args:
3919 * discp - CddbDisc object
3920 *
3921 * Return:
3922 * TRUE - Success
3923 * FALSE - Failure
3924 */
3925 STATIC bool_t
cdinfo_discinfo_query(CddbDiscPtr discp)3926 cdinfo_discinfo_query(CddbDiscPtr discp)
3927 {
3928 CddbResult ret;
3929 CddbCreditPtr credp = NULL;
3930 CddbSegmentPtr segp = NULL;
3931 char *str;
3932 long ncreds,
3933 nsegs;
3934 int i,
3935 j;
3936 cdinfo_genre_t *gp,
3937 *sgp;
3938 cdinfo_credit_t *p,
3939 *q;
3940 cdinfo_segment_t *r,
3941 *s;
3942 cdinfo_role_t *rp;
3943
3944 /* Disc artist */
3945 if (!cdinfo_get_str("CddbDisc_GetArtist",
3946 CddbDisc_GetArtist,
3947 discp, &cdinfo_dbp->disc.artist)) {
3948 return FALSE;
3949 }
3950
3951 /* Disc title */
3952 if (!cdinfo_get_str("CddbDisc_GetTitle",
3953 CddbDisc_GetTitle,
3954 discp, &cdinfo_dbp->disc.title)) {
3955 return FALSE;
3956 }
3957
3958 /* Artist full name */
3959 if (!cdinfo_get_fullname("CddbDisc_GetArtistFullName",
3960 CddbDisc_GetArtistFullName,
3961 discp,
3962 &cdinfo_dbp->disc.artistfname.dispname,
3963 &cdinfo_dbp->disc.artistfname.lastname,
3964 &cdinfo_dbp->disc.artistfname.firstname,
3965 &cdinfo_dbp->disc.artistfname.the)) {
3966 return FALSE;
3967 }
3968
3969 /* Disc sort title */
3970 if (!cdinfo_get_str("CddbDisc_GetTitleSort",
3971 CddbDisc_GetTitleSort,
3972 discp, &cdinfo_dbp->disc.sorttitle)) {
3973 return FALSE;
3974 }
3975
3976 /* Disc sort title */
3977 if (!cdinfo_get_str("CddbDisc_GetTitleThe",
3978 CddbDisc_GetTitleThe,
3979 discp, &cdinfo_dbp->disc.title_the)) {
3980 return FALSE;
3981 }
3982
3983 /* Year */
3984 if (!cdinfo_get_str("CddbDisc_GetYear",
3985 CddbDisc_GetYear,
3986 discp, &cdinfo_dbp->disc.year)) {
3987 return FALSE;
3988 }
3989
3990 /* Label */
3991 if (!cdinfo_get_str("CddbDisc_GetLabel",
3992 CddbDisc_GetLabel,
3993 discp, &cdinfo_dbp->disc.label)) {
3994 return FALSE;
3995 }
3996
3997 /* Compilation */
3998 if (!cdinfo_get_bool("CddbDisc_GetCompilation",
3999 CddbDisc_GetCompilation,
4000 discp, &cdinfo_dbp->disc.compilation)) {
4001 return FALSE;
4002 }
4003
4004 /* Genre */
4005 if (!cdinfo_get_str("CddbDisc_GetGenreId",
4006 CddbDisc_GetGenreId,
4007 discp, &cdinfo_dbp->disc.genre)) {
4008 return FALSE;
4009 }
4010 gp = cdinfo_genre(cdinfo_dbp->disc.genre);
4011 if (gp != NULL && gp->parent == NULL) {
4012 /* Illegal: the primary genre is set to a genre category.
4013 * "Fix" it by setting it to the category's "General"
4014 * subgenre. If not found, then set it to the first
4015 * subgenre.
4016 */
4017 for (sgp = gp->child; sgp != NULL; sgp = sgp->next) {
4018 if (sgp->name != NULL &&
4019 strncmp(sgp->name, "General ", 8) == 0) {
4020 if (!util_newstr(&cdinfo_dbp->disc.genre,
4021 sgp->id)) {
4022 CDINFO_FATAL(app_data.str_nomemory);
4023 return FALSE;
4024 }
4025 break;
4026 }
4027 }
4028 if (sgp == NULL) {
4029 if (gp->child != NULL) {
4030 if (!util_newstr(&cdinfo_dbp->disc.genre,
4031 gp->child->id)) {
4032 CDINFO_FATAL(app_data.str_nomemory);
4033 return FALSE;
4034 }
4035 }
4036 else {
4037 MEM_FREE(cdinfo_dbp->disc.genre);
4038 cdinfo_dbp->disc.genre = NULL;
4039 }
4040 }
4041 }
4042
4043 /* Secondary Genre */
4044 if (!cdinfo_get_str("CddbDisc_GetSecondaryGenreId",
4045 CddbDisc_GetSecondaryGenreId,
4046 discp, &cdinfo_dbp->disc.genre2)) {
4047 return FALSE;
4048 }
4049 gp = cdinfo_genre(cdinfo_dbp->disc.genre2);
4050 if (gp != NULL && gp->parent == NULL) {
4051 /* Illegal: the secondary genre is set to a genre category.
4052 * "Fix" it by setting it to the category's "General"
4053 * subgenre. If not found, then set it to the first
4054 * subgenre.
4055 */
4056 for (sgp = gp->child; sgp != NULL; sgp = sgp->next) {
4057 if (sgp->name != NULL &&
4058 strncmp(sgp->name, "General ", 8) == 0) {
4059 if (!util_newstr(&cdinfo_dbp->disc.genre2,
4060 sgp->id)) {
4061 CDINFO_FATAL(app_data.str_nomemory);
4062 return FALSE;
4063 }
4064 break;
4065 }
4066 }
4067 if (sgp == NULL) {
4068 if (gp->child != NULL) {
4069 if (!util_newstr(&cdinfo_dbp->disc.genre2,
4070 gp->child->id)) {
4071 CDINFO_FATAL(app_data.str_nomemory);
4072 return FALSE;
4073 }
4074 }
4075 else {
4076 MEM_FREE(cdinfo_dbp->disc.genre2);
4077 cdinfo_dbp->disc.genre2 = NULL;
4078 }
4079 }
4080 }
4081
4082 /* Disc number in set */
4083 if (!cdinfo_get_str("CddbDisc_GetNumberInSet",
4084 CddbDisc_GetNumberInSet,
4085 discp, &cdinfo_dbp->disc.dnum)) {
4086 return FALSE;
4087 }
4088
4089 /* Total number in set */
4090 if (!cdinfo_get_str("CddbDisc_GetTotalInSet",
4091 CddbDisc_GetTotalInSet,
4092 discp, &cdinfo_dbp->disc.tnum)) {
4093 return FALSE;
4094 }
4095
4096 /* Region */
4097 if (!cdinfo_get_str("CddbDisc_GetRegionId",
4098 CddbDisc_GetRegionId,
4099 discp, &cdinfo_dbp->disc.region)) {
4100 return FALSE;
4101 }
4102
4103 /* Language ID */
4104 if (!cdinfo_get_str("CddbDisc_GetLanguageId",
4105 CddbDisc_GetLanguageId,
4106 discp, &cdinfo_dbp->disc.lang)) {
4107 return FALSE;
4108 }
4109
4110 /* Notes */
4111 if (!cdinfo_get_str("CddbDisc_GetNotes",
4112 CddbDisc_GetNotes,
4113 discp, &cdinfo_dbp->disc.notes)) {
4114 return FALSE;
4115 }
4116
4117 /* Media ID */
4118 if (!cdinfo_get_str("CddbDisc_GetMediaId",
4119 CddbDisc_GetMediaId,
4120 discp, &cdinfo_dbp->disc.mediaid)) {
4121 return FALSE;
4122 }
4123
4124 /* Media unique ID */
4125 if (!cdinfo_get_str("CddbDisc_GetMuiId",
4126 CddbDisc_GetMuiId,
4127 discp, &cdinfo_dbp->disc.muiid)) {
4128 return FALSE;
4129 }
4130
4131 /* Title unique ID */
4132 if (!cdinfo_get_str("CddbDisc_GetTitleUId",
4133 CddbDisc_GetTitleUId,
4134 discp, &cdinfo_dbp->disc.titleuid)) {
4135 return FALSE;
4136 }
4137
4138 /* Revision */
4139 if (!cdinfo_get_str("CddbDisc_GetRevision",
4140 CddbDisc_GetRevision,
4141 discp, &cdinfo_dbp->disc.revision)) {
4142 return FALSE;
4143 }
4144
4145 /* Revision Tag */
4146 if (!cdinfo_get_str("CddbDisc_GetRevisionTag",
4147 CddbDisc_GetRevisionTag,
4148 discp, &cdinfo_dbp->disc.revtag)) {
4149 return FALSE;
4150 }
4151
4152 /* Certifier */
4153 if (!cdinfo_get_str("CddbDisc_GetCertifier",
4154 CddbDisc_GetCertifier,
4155 discp, &cdinfo_dbp->disc.certifier)) {
4156 return FALSE;
4157 }
4158
4159 /* Disc Credits */
4160 DBGPRN(DBG_CDI)(errfp, "CddbDisc_GetNumCredits: ");
4161 ret = CddbDisc_GetNumCredits(discp, &ncreds);
4162 DBGPRN(DBG_CDI)(errfp, "0x%lx %ld credits\n", ret, ncreds);
4163
4164 cdinfo_set_errstr(ret);
4165
4166 q = NULL;
4167 for (i = 0; i < (int) ncreds; i++) {
4168 DBGPRN(DBG_CDI)(errfp, "CddbDisc_GetCredit[%02d]: ", i+1);
4169 ret = CddbDisc_GetCredit(discp, (long) (i+1), &credp);
4170 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
4171
4172 if (ret != Cddb_OK)
4173 continue;
4174
4175 /* Allocate a credit structure */
4176 p = (cdinfo_credit_t *) MEM_ALLOC(
4177 "cdinfo_credit_t",
4178 sizeof(cdinfo_credit_t)
4179 );
4180 if (p == NULL) {
4181 CDINFO_FATAL(app_data.str_nomemory);
4182 return FALSE;
4183 }
4184 (void) memset(p, 0, sizeof(cdinfo_credit_t));
4185
4186 /* Credit role */
4187 str = NULL;
4188 if (!cdinfo_get_str(" CddbCredit_GetId",
4189 CddbCredit_GetId, credp, &str)) {
4190 MEM_FREE(p);
4191 return FALSE;
4192 }
4193 rp = cdinfo_role(str);
4194 if (rp->parent == NULL) {
4195 /* Illegal: role set to the category role
4196 * "Fix" it by setting the role to the
4197 * first subrole of that category instead.
4198 * If for some reason there are no subroles
4199 * then the child would be NULL and thus the
4200 * role would be "None -> None".
4201 */
4202 rp = rp->child;
4203 }
4204 p->crinfo.role = rp;
4205 MEM_FREE(str);
4206 str = NULL;
4207
4208 /* Credit name */
4209 if (!cdinfo_get_str(" CddbCredit_GetName",
4210 CddbCredit_GetName,
4211 credp, &p->crinfo.name)) {
4212 MEM_FREE(p);
4213 return FALSE;
4214 }
4215
4216 /* Credit full name */
4217 if (!cdinfo_get_fullname(" CddbCredit_GetFullName",
4218 CddbCredit_GetFullName,
4219 credp,
4220 &p->crinfo.fullname.dispname,
4221 &p->crinfo.fullname.lastname,
4222 &p->crinfo.fullname.firstname,
4223 &p->crinfo.fullname.the)) {
4224 MEM_FREE(p);
4225 return FALSE;
4226 }
4227
4228 /* Credit notes */
4229 if (!cdinfo_get_str(" CddbCredit_GetNotes",
4230 CddbCredit_GetNotes,
4231 credp, &p->notes)) {
4232 MEM_FREE(p);
4233 return FALSE;
4234 }
4235
4236 CddbReleaseObject(credp);
4237
4238 if (cdinfo_dbp->disc.credit_list == NULL) {
4239 cdinfo_dbp->disc.credit_list = p;
4240 p->prev = NULL;
4241 }
4242 else {
4243 q->next = p;
4244 p->prev = q;
4245 }
4246 q = p;
4247 p->next = NULL;
4248 }
4249
4250 /* Segments */
4251 DBGPRN(DBG_CDI)(errfp, "CddbDisc_GetNumSegments: ");
4252 ret = CddbDisc_GetNumSegments(discp, &nsegs);
4253 DBGPRN(DBG_CDI)(errfp, "0x%lx %ld segments\n", ret, nsegs);
4254
4255 cdinfo_set_errstr(ret);
4256
4257 s = NULL;
4258 for (i = 0; i < (int) nsegs; i++) {
4259 DBGPRN(DBG_CDI)(errfp, "CddbDisc_GetSegment[%02d]: ", i+1);
4260 ret = CddbDisc_GetSegment(discp, (long) (i+1), &segp);
4261 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
4262
4263 if (ret != Cddb_OK)
4264 continue;
4265
4266 /* Allocate a segment structure */
4267 r = (cdinfo_segment_t *) MEM_ALLOC(
4268 "cdinfo_segment_t",
4269 sizeof(cdinfo_segment_t)
4270 );
4271 if (r == NULL) {
4272 CDINFO_FATAL(app_data.str_nomemory);
4273 return FALSE;
4274 }
4275 (void) memset(r, 0, sizeof(cdinfo_segment_t));
4276
4277 /* Segment name */
4278 if (!cdinfo_get_str(" CddbSegment_GetName",
4279 CddbSegment_GetName,
4280 segp, &r->name)) {
4281 MEM_FREE(r);
4282 return FALSE;
4283 }
4284
4285 /* Segment notes */
4286 if (!cdinfo_get_str(" CddbSegment_GetNotes",
4287 CddbSegment_GetNotes,
4288 segp, &r->notes)) {
4289 MEM_FREE(r);
4290 return FALSE;
4291 }
4292
4293 /* Segment start track */
4294 if (!cdinfo_get_str(" CddbSegment_GetStartTrack",
4295 CddbSegment_GetStartTrack,
4296 segp, &r->start_track)) {
4297 MEM_FREE(r);
4298 return FALSE;
4299 }
4300
4301 /* Segment start frame */
4302 if (!cdinfo_get_str(" CddbSegment_GetStartFrame",
4303 CddbSegment_GetStartFrame,
4304 segp, &r->start_frame)) {
4305 MEM_FREE(r);
4306 return FALSE;
4307 }
4308
4309 /* Segment end track */
4310 if (!cdinfo_get_str(" CddbSegment_GetEndTrack",
4311 CddbSegment_GetEndTrack,
4312 segp, &r->end_track)) {
4313 MEM_FREE(r);
4314 return FALSE;
4315 }
4316
4317 /* Segment end frame */
4318 if (!cdinfo_get_str(" CddbSegment_GetEndFrame",
4319 CddbSegment_GetEndFrame,
4320 segp, &r->end_frame)) {
4321 MEM_FREE(r);
4322 return FALSE;
4323 }
4324
4325 /* Segment Credits */
4326 DBGPRN(DBG_CDI)(errfp, " CddbSegment_GetNumCredits: ");
4327 ret = CddbSegment_GetNumCredits(segp, &ncreds);
4328 DBGPRN(DBG_CDI)(errfp, "0x%lx %ld credits\n", ret, ncreds);
4329
4330 cdinfo_set_errstr(ret);
4331
4332 q = NULL;
4333 for (j = 0; j < (int) ncreds; j++) {
4334 DBGPRN(DBG_CDI)(errfp,
4335 "CddbSegment_GetCredit[%02d]: ", j+1);
4336 ret = CddbSegment_GetCredit(segp, (long) (j+1),
4337 &credp);
4338 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
4339
4340 if (ret != Cddb_OK)
4341 continue;
4342
4343 /* Allocate a credit structure */
4344 p = (cdinfo_credit_t *) MEM_ALLOC(
4345 "cdinfo_credit_t",
4346 sizeof(cdinfo_credit_t)
4347 );
4348 if (p == NULL) {
4349 CDINFO_FATAL(app_data.str_nomemory);
4350 return FALSE;
4351 }
4352 (void) memset(p, 0, sizeof(cdinfo_credit_t));
4353
4354 /* Credit role */
4355 str = NULL;
4356 if (!cdinfo_get_str(" CddbCredit_GetId",
4357 CddbCredit_GetId, credp,
4358 &str)) {
4359 MEM_FREE(p);
4360 return FALSE;
4361 }
4362 rp = cdinfo_role(str);
4363 if (rp->parent == NULL) {
4364 /* Illegal: role set to the category role
4365 * "Fix" it by setting the role to the
4366 * first subrole of that category instead.
4367 * If for some reason there are no subroles
4368 * then the child would be NULL and thus the
4369 * role would be "None -> None".
4370 */
4371 rp = rp->child;
4372 }
4373 p->crinfo.role = rp;
4374 MEM_FREE(str);
4375 str = NULL;
4376
4377 /* Credit name */
4378 if (!cdinfo_get_str(" CddbCredit_GetName",
4379 CddbCredit_GetName,
4380 credp, &p->crinfo.name)) {
4381 MEM_FREE(p);
4382 return FALSE;
4383 }
4384
4385 /* Credit full name */
4386 if (!cdinfo_get_fullname(" CddbCredit_GetFullName",
4387 CddbCredit_GetFullName,
4388 credp,
4389 &p->crinfo.fullname.dispname,
4390 &p->crinfo.fullname.lastname,
4391 &p->crinfo.fullname.firstname,
4392 &p->crinfo.fullname.the)) {
4393 MEM_FREE(p);
4394 return FALSE;
4395 }
4396
4397 /* Credit notes */
4398 if (!cdinfo_get_str(" CddbCredit_GetNotes",
4399 CddbCredit_GetNotes,
4400 credp, &p->notes)) {
4401 MEM_FREE(p);
4402 return FALSE;
4403 }
4404
4405 CddbReleaseObject(credp);
4406
4407 if (r->credit_list == NULL) {
4408 r->credit_list = p;
4409 p->prev = NULL;
4410 }
4411 else {
4412 q->next = p;
4413 p->prev = q;
4414 }
4415 q = p;
4416 p->next = NULL;
4417 }
4418
4419 CddbReleaseObject(segp);
4420
4421 if (cdinfo_dbp->disc.segment_list == NULL) {
4422 cdinfo_dbp->disc.segment_list = r;
4423 r->prev = NULL;
4424 }
4425 else {
4426 s->next = r;
4427 r->prev = s;
4428 }
4429 s = r;
4430 r->next = NULL;
4431 }
4432
4433 return TRUE;
4434 }
4435
4436
4437 /*
4438 * cdinfo_trackinfo_query
4439 * Query CDDB for track information
4440 *
4441 * Args:
4442 * discp - CddbDisc object
4443 *
4444 * Return:
4445 * TRUE - Success
4446 * FALSE - Failure
4447 */
4448 STATIC bool_t
cdinfo_trackinfo_query(CddbDiscPtr discp)4449 cdinfo_trackinfo_query(CddbDiscPtr discp)
4450 {
4451 CddbResult ret;
4452 CddbTrackPtr trkp = NULL;
4453 CddbCreditPtr credp = NULL;
4454 long ntrks,
4455 ncreds;
4456 int i,
4457 j;
4458 char *str;
4459 cdinfo_genre_t *gp,
4460 *sgp;
4461 cdinfo_credit_t *p,
4462 *q;
4463 cdinfo_role_t *rp;
4464
4465 /* Track information */
4466 DBGPRN(DBG_CDI)(errfp, "CddbDisc_GetNumTracks: ");
4467 ret = CddbDisc_GetNumTracks(discp, &ntrks);
4468 DBGPRN(DBG_CDI)(errfp, "0x%lx %ld tracks\n", ret, ntrks);
4469
4470 cdinfo_set_errstr(ret);
4471
4472 for (i = 0; i < (int) ntrks; i++) {
4473 DBGPRN(DBG_CDI)(errfp, "CddbDisc_GetTrack[%02d]: ", i+1);
4474 ret = CddbDisc_GetTrack(discp, (long) (i+1), &trkp);
4475 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
4476
4477 if (ret != Cddb_OK)
4478 continue;
4479
4480 /* Track artist */
4481 if (!cdinfo_get_str(" CddbTrack_GetArtist",
4482 CddbTrack_GetArtist,
4483 trkp, &cdinfo_dbp->track[i].artist)) {
4484 return FALSE;
4485 }
4486
4487 /* Track title */
4488 if (!cdinfo_get_str(" CddbTrack_GetTitle",
4489 CddbTrack_GetTitle,
4490 trkp, &cdinfo_dbp->track[i].title)) {
4491 return FALSE;
4492 }
4493
4494 /* Artist full name */
4495 if (!cdinfo_get_fullname(" CddbTrack_GetArtistFullName",
4496 CddbTrack_GetArtistFullName,
4497 trkp,
4498 &cdinfo_dbp->track[i].artistfname.dispname,
4499 &cdinfo_dbp->track[i].artistfname.lastname,
4500 &cdinfo_dbp->track[i].artistfname.firstname,
4501 &cdinfo_dbp->track[i].artistfname.the)) {
4502 return FALSE;
4503 }
4504
4505 /* Track sort title */
4506 if (!cdinfo_get_str(" CddbTrack_GetTitleSort",
4507 CddbTrack_GetTitleSort,
4508 trkp, &cdinfo_dbp->track[i].sorttitle)) {
4509 return FALSE;
4510 }
4511
4512 /* Track sort title */
4513 if (!cdinfo_get_str(" CddbTrack_GetTitleThe",
4514 CddbTrack_GetTitleThe,
4515 trkp, &cdinfo_dbp->track[i].title_the)) {
4516 return FALSE;
4517 }
4518
4519 /* Year */
4520 if (!cdinfo_get_str(" CddbTrack_GetYear",
4521 CddbTrack_GetYear,
4522 trkp, &cdinfo_dbp->track[i].year)) {
4523 return FALSE;
4524 }
4525
4526 /* Label */
4527 if (!cdinfo_get_str(" CddbTrack_GetLabel",
4528 CddbTrack_GetLabel,
4529 trkp, &cdinfo_dbp->track[i].label)) {
4530 return FALSE;
4531 }
4532
4533 /* Genre */
4534 if (!cdinfo_get_str(" CddbTrack_GetGenreId",
4535 CddbTrack_GetGenreId,
4536 trkp, &cdinfo_dbp->track[i].genre)) {
4537 return FALSE;
4538 }
4539 gp = cdinfo_genre(cdinfo_dbp->track[i].genre);
4540 if (gp != NULL && gp->parent == NULL) {
4541 /* Illegal: the primary genre is set to a genre
4542 * category. "Fix" it by setting it to the category's
4543 * "General" subgenre. If not found, then set it to
4544 * the first subgenre.
4545 */
4546 for (sgp = gp->child; sgp != NULL; sgp = sgp->next) {
4547 if (sgp->name != NULL &&
4548 strncmp(sgp->name, "General ", 8) == 0) {
4549 if (!util_newstr(&cdinfo_dbp->track[i].genre,
4550 sgp->id)) {
4551 CDINFO_FATAL(app_data.str_nomemory);
4552 return FALSE;
4553 }
4554 break;
4555 }
4556 }
4557 if (sgp == NULL) {
4558 if (gp->child != NULL) {
4559 if (!util_newstr(&cdinfo_dbp->track[i].genre,
4560 gp->child->id)) {
4561 CDINFO_FATAL(app_data.str_nomemory);
4562 return FALSE;
4563 }
4564 }
4565 else {
4566 MEM_FREE(cdinfo_dbp->track[i].genre);
4567 cdinfo_dbp->track[i].genre = NULL;
4568 }
4569 }
4570 }
4571
4572 /* Secondary Genre */
4573 if (!cdinfo_get_str(" CddbTrack_GetSecondaryGenreId",
4574 CddbTrack_GetSecondaryGenreId,
4575 trkp, &cdinfo_dbp->track[i].genre2)) {
4576 return FALSE;
4577 }
4578 gp = cdinfo_genre(cdinfo_dbp->track[i].genre2);
4579 if (gp != NULL && gp->parent == NULL) {
4580 /* Illegal: the secondary genre is set to a genre
4581 * category. "Fix" it by setting it to the category's
4582 * "General" subgenre. If not found, then set it to
4583 * the first subgenre.
4584 */
4585 for (sgp = gp->child; sgp != NULL; sgp = sgp->next) {
4586 if (sgp->name != NULL &&
4587 strncmp(sgp->name, "General ", 8) == 0) {
4588 if (!util_newstr(&cdinfo_dbp->track[i].genre2,
4589 sgp->id)) {
4590 CDINFO_FATAL(app_data.str_nomemory);
4591 return FALSE;
4592 }
4593 break;
4594 }
4595 }
4596 if (sgp == NULL) {
4597 if (gp->child != NULL) {
4598 if (!util_newstr(&cdinfo_dbp->track[i].genre2,
4599 gp->child->id)) {
4600 CDINFO_FATAL(app_data.str_nomemory);
4601 return FALSE;
4602 }
4603 }
4604 else {
4605 MEM_FREE(cdinfo_dbp->track[i].genre2);
4606 cdinfo_dbp->track[i].genre2 = NULL;
4607 }
4608 }
4609 }
4610
4611 /* BPM */
4612 if (!cdinfo_get_str(" CddbTrack_GetBeatsPerMinute",
4613 CddbTrack_GetBeatsPerMinute,
4614 trkp, &cdinfo_dbp->track[i].bpm)) {
4615 return FALSE;
4616 }
4617
4618 /* Notes */
4619 if (!cdinfo_get_str(" CddbTrack_GetNotes",
4620 CddbTrack_GetNotes,
4621 trkp, &cdinfo_dbp->track[i].notes)) {
4622 return FALSE;
4623 }
4624
4625 /* ISRC */
4626 if (!cdinfo_get_str(" CddbTrack_GetISRC",
4627 CddbTrack_GetISRC,
4628 trkp, &cdinfo_dbp->track[i].isrc)) {
4629 return FALSE;
4630 }
4631
4632 /* Track Credits */
4633 DBGPRN(DBG_CDI)(errfp, " CddbTrack_GetNumCredits: ");
4634 ret = CddbTrack_GetNumCredits(trkp, &ncreds);
4635 DBGPRN(DBG_CDI)(errfp, "0x%lx %ld credits\n", ret, ncreds);
4636
4637 cdinfo_set_errstr(ret);
4638
4639 q = NULL;
4640 for (j = 0; j < (int) ncreds; j++) {
4641 DBGPRN(DBG_CDI)(errfp,
4642 " CddbTrack_GetCredit[%02d]: ", j+1);
4643 ret = CddbTrack_GetCredit(trkp, (long) (j+1), &credp);
4644 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
4645
4646 if (ret != Cddb_OK)
4647 continue;
4648
4649 /* Allocate a credit structure */
4650 p = (cdinfo_credit_t *) MEM_ALLOC(
4651 "cdinfo_credit_t",
4652 sizeof(cdinfo_credit_t)
4653 );
4654 if (p == NULL) {
4655 CDINFO_FATAL(app_data.str_nomemory);
4656 return FALSE;
4657 }
4658 (void) memset(p, 0, sizeof(cdinfo_credit_t));
4659
4660 /* Credit role */
4661 str = NULL;
4662 if (!cdinfo_get_str(" CddbCredit_GetId",
4663 CddbCredit_GetId, credp, &str)) {
4664 MEM_FREE(p);
4665 return FALSE;
4666 }
4667 rp = cdinfo_role(str);
4668 if (rp->parent == NULL) {
4669 /* Illegal: role set to the category role
4670 * "Fix" it by setting the role to the
4671 * first subrole of that category instead.
4672 * If for some reason there are no subroles
4673 * then the child would be NULL and thus the
4674 * role would be "None -> None".
4675 */
4676 rp = rp->child;
4677 }
4678 p->crinfo.role = rp;
4679 MEM_FREE(str);
4680 str = NULL;
4681
4682 /* Credit name */
4683 if (!cdinfo_get_str(" CddbCredit_GetName",
4684 CddbCredit_GetName,
4685 credp, &p->crinfo.name)) {
4686 MEM_FREE(p);
4687 return FALSE;
4688 }
4689
4690 /* Credit full name */
4691 if (!cdinfo_get_fullname(" CddbCredit_GetFullName",
4692 CddbCredit_GetFullName,
4693 credp,
4694 &p->crinfo.fullname.dispname,
4695 &p->crinfo.fullname.lastname,
4696 &p->crinfo.fullname.firstname,
4697 &p->crinfo.fullname.the)) {
4698 MEM_FREE(p);
4699 return FALSE;
4700 }
4701
4702 /* Credit notes */
4703 if (!cdinfo_get_str(" CddbCredit_GetNotes",
4704 CddbCredit_GetNotes,
4705 credp, &p->notes)) {
4706 MEM_FREE(p);
4707 return FALSE;
4708 }
4709
4710 CddbReleaseObject(credp);
4711
4712 if (cdinfo_dbp->track[i].credit_list == NULL) {
4713 cdinfo_dbp->track[i].credit_list = p;
4714 p->prev = NULL;
4715 }
4716 else {
4717 q->next = p;
4718 p->prev = q;
4719 }
4720 q = p;
4721 p->next = NULL;
4722 }
4723
4724 CddbReleaseObject(trkp);
4725 }
4726
4727 return TRUE;
4728 }
4729
4730
4731 /*
4732 * cdinfo_add_urllist
4733 * Given a CddbURLList, add the items in that list to the URL list
4734 * specified by *listhead.
4735 *
4736 * Args:
4737 * listhead - Address of the listhead
4738 * urllistp - The CddbURLList
4739 * type - WTYPE_ALBUM or WTYPE_GEN
4740 *
4741 * Return:
4742 * TRUE - Success
4743 * FALSE - Failure (cannot allocate memory)
4744 */
4745 STATIC bool_t
cdinfo_add_urllist(cdinfo_url_t ** listhead,CddbURLListPtr urllistp,int wtype)4746 cdinfo_add_urllist(cdinfo_url_t **listhead, CddbURLListPtr urllistp, int wtype)
4747 {
4748 CddbURLPtr urlp;
4749 CddbResult ret;
4750 long cnt,
4751 i;
4752 cdinfo_url_t *p;
4753 static cdinfo_url_t *q = NULL;
4754
4755 cnt = 0;
4756 DBGPRN(DBG_CDI)(errfp, "CddbURLList_GetCount: ");
4757 ret = CddbURLList_GetCount(urllistp, &cnt);
4758 DBGPRN(DBG_CDI)(errfp, "0x%lx %ld entries\n", ret, cnt);
4759
4760 if (ret != Cddb_OK || cnt == 0)
4761 return TRUE;
4762
4763 for (i = 1; i <= cnt; i++) {
4764 urlp = NULL;
4765 DBGPRN(DBG_CDI)(errfp, "CddbURLList_GetURL: ");
4766 ret = CddbURLList_GetURL(urllistp, i, &urlp);
4767 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
4768
4769 if (ret != Cddb_OK || urlp == NULL)
4770 return TRUE;
4771
4772 p = (cdinfo_url_t *)(void *) MEM_ALLOC(
4773 "cdinfo_url_t", sizeof(cdinfo_url_t)
4774 );
4775 if (p == NULL) {
4776 CDINFO_FATAL(app_data.str_nomemory);
4777 return FALSE;
4778 }
4779 (void) memset(p, 0, sizeof(cdinfo_url_t));
4780
4781 if (!cdinfo_get_str("CddbURL_GetType",
4782 CddbURL_GetType,
4783 urlp, &p->type)) {
4784 MEM_FREE(p);
4785 return FALSE;
4786 }
4787 if (!cdinfo_get_str("CddbURL_GetHref",
4788 CddbURL_GetHref,
4789 urlp, &p->href)) {
4790 MEM_FREE(p);
4791 return FALSE;
4792 }
4793 if (!cdinfo_get_str("CddbURL_GetDisplayLink",
4794 CddbURL_GetDisplayLink,
4795 urlp, &p->displink)) {
4796 MEM_FREE(p);
4797 return FALSE;
4798 }
4799 if (!cdinfo_get_str("CddbURL_GetDisplayText",
4800 CddbURL_GetDisplayText,
4801 urlp, &p->disptext)) {
4802 MEM_FREE(p);
4803 return FALSE;
4804 }
4805 if (!cdinfo_get_str("CddbURL_GetCategory",
4806 CddbURL_GetCategory,
4807 urlp, &p->categ)) {
4808 MEM_FREE(p);
4809 return FALSE;
4810 }
4811 if (!cdinfo_get_str("CddbURL_GetSize",
4812 CddbURL_GetSize,
4813 urlp, &p->size)) {
4814 MEM_FREE(p);
4815 return FALSE;
4816 }
4817 if (!cdinfo_get_str("CddbURL_GetWeight",
4818 CddbURL_GetWeight,
4819 urlp, &p->weight)) {
4820 MEM_FREE(p);
4821 return FALSE;
4822 }
4823
4824 p->wtype = wtype;
4825
4826 if (*listhead == NULL)
4827 *listhead = q = p;
4828 else {
4829 q->next = p;
4830 q = p;
4831 }
4832
4833 CddbReleaseObject(urlp);
4834 }
4835
4836 return TRUE;
4837 }
4838
4839
4840 /*
4841 * cdinfo_urls_query
4842 * Query CDDB for URLs information
4843 *
4844 * Args:
4845 * cp - cdinfo_cddb_t pointer for the CDDB connection
4846 * discp - CddbDisc object. If NULL, then general-interest URLs
4847 * are queried.
4848 *
4849 * Return:
4850 * TRUE - Success
4851 * FALSE - Failure
4852 */
4853 STATIC bool_t
cdinfo_urls_query(cdinfo_cddb_t * cp,CddbDiscPtr discp)4854 cdinfo_urls_query(cdinfo_cddb_t *cp, CddbDiscPtr discp)
4855 {
4856 CddbURLManagerPtr urlmgrp = NULL;
4857 CddbURLListPtr urllistp = NULL;
4858 CddbResult ret;
4859 int wtype;
4860 cdinfo_url_t **listhead;
4861
4862 /* Get URLS from the service */
4863 DBGPRN(DBG_CDI)(errfp, "CddbControl_GetURLList: ");
4864 ret = CddbControl_GetURLList(cp->ctrlp, discp, 0, &urllistp);
4865 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
4866
4867 if (urllistp != NULL)
4868 CddbReleaseObject(urllistp);
4869
4870 if (discp == NULL) {
4871 listhead = &cdinfo_dbp->gen_url_list;
4872 wtype = WTYPE_GEN;
4873 }
4874 else {
4875 listhead = &cdinfo_dbp->disc_url_list;
4876 wtype = WTYPE_ALBUM;
4877 }
4878
4879 DBGPRN(DBG_CDI)(errfp, "CddbControl_GetURLManager: ");
4880 ret = CddbControl_GetURLManager(cp->ctrlp, &urlmgrp);
4881 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
4882
4883 if (ret != Cddb_OK || urlmgrp == NULL)
4884 return FALSE;
4885
4886 #if 0 /* Not currently used */
4887 /* Cover URLs */
4888 DBGPRN(DBG_CDI)(errfp, "CddbURLManager_GetCoverURLs: ");
4889 ret = CddbURLManager_GetCoverURLs(urlmgrp, discp, &urllistp);
4890 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
4891 if (ret == Cddb_OK && urllistp != NULL) {
4892 if (!cdinfo_add_urllist(listhead, urllistp, wtype)) {
4893 CddbReleaseObject(urllistp);
4894 CddbReleaseObject(urlmgrp);
4895 return FALSE;
4896 }
4897 CddbReleaseObject(urllistp);
4898 }
4899 #endif
4900
4901 /* Menu URLs */
4902 DBGPRN(DBG_CDI)(errfp, "CddbURLManager_GetMenuURLs: ");
4903 ret = CddbURLManager_GetMenuURLs(urlmgrp, discp, &urllistp);
4904 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
4905 if (ret == Cddb_OK && urllistp != NULL) {
4906 if (!cdinfo_add_urllist(listhead, urllistp, wtype)) {
4907 CddbReleaseObject(urllistp);
4908 CddbReleaseObject(urlmgrp);
4909 return FALSE;
4910 }
4911 CddbReleaseObject(urllistp);
4912 }
4913
4914 CddbReleaseObject(urlmgrp);
4915
4916 return TRUE;
4917 }
4918
4919
4920 /*
4921 * cdinfo_build_matchlist
4922 * Build multiple fuzzy match disc elements list. This is used
4923 * to query the user for a selection.
4924 *
4925 * Args:
4926 * discs - CddbDiscs object pointer
4927 *
4928 * Return:
4929 * TRUE - success
4930 * FALSE - failure
4931 */
4932 STATIC bool_t
cdinfo_build_matchlist(CddbDiscsPtr discsp)4933 cdinfo_build_matchlist(CddbDiscsPtr discsp)
4934 {
4935 CddbResult ret;
4936 CddbDiscPtr discp;
4937 long cnt,
4938 i;
4939 cdinfo_genre_t *gp,
4940 *sgp;
4941 cdinfo_match_t *mp,
4942 *mp2;
4943
4944 DBGPRN(DBG_CDI)(errfp, "CddbDiscs_GetCount: ");
4945 ret = CddbDiscs_GetCount(discsp, &cnt);
4946 DBGPRN(DBG_CDI)(errfp, "0x%lx %ld matches\n", ret, cnt);
4947
4948 if (ret != Cddb_OK || cnt <= 0)
4949 return FALSE;
4950
4951 mp = NULL;
4952 for (i = 1; i <= cnt; i++) {
4953 DBGPRN(DBG_CDI)(errfp, "CddbDiscs_GetDisc[%ld]: ", i);
4954 ret = CddbDiscs_GetDisc(discsp, i, &discp);
4955 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
4956
4957 if (ret == Cddb_OK && discp != NULL) {
4958 mp2 = (cdinfo_match_t *)(void *) MEM_ALLOC(
4959 "cdinfo_match_t",
4960 sizeof(cdinfo_match_t)
4961 );
4962 if (mp2 == NULL) {
4963 CDINFO_FATAL(app_data.str_nomemory);
4964 return FALSE;
4965 }
4966 (void) memset(mp2, 0, sizeof(cdinfo_match_t));
4967
4968 mp2->tag = i;
4969
4970 if (!cdinfo_get_str(" CddbDisc_GetArtist",
4971 CddbDisc_GetArtist,
4972 discp, &mp2->artist)) {
4973 return FALSE;
4974 }
4975 if (!cdinfo_get_str(" CddbDisc_GetTitle",
4976 CddbDisc_GetTitle,
4977 discp, &mp2->title)) {
4978 return FALSE;
4979 }
4980 if (!cdinfo_get_str(" CddbDisc_GetGenreId",
4981 CddbDisc_GetGenreId,
4982 discp, &mp2->genre)) {
4983 return FALSE;
4984 }
4985 gp = cdinfo_genre(cdinfo_dbp->disc.genre);
4986 if (gp != NULL && gp->parent == NULL) {
4987 /* Illegal: the genre is set to a genre category.
4988 * "Fix" it by setting it to the category's
4989 * "General" subgenre. If not found, then set
4990 * it to the first subgenre.
4991 */
4992 for (sgp = gp->child; sgp != NULL;
4993 sgp = sgp->next) {
4994 if (sgp->name != NULL &&
4995 strncmp(sgp->name, "General ", 8) == 0) {
4996 if (!util_newstr(&cdinfo_dbp->disc.genre,
4997 sgp->id)) {
4998 CDINFO_FATAL(app_data.str_nomemory);
4999 return FALSE;
5000 }
5001 break;
5002 }
5003 }
5004 if (sgp == NULL) {
5005 if (gp->child != NULL) {
5006 if (!util_newstr(&cdinfo_dbp->disc.genre,
5007 gp->child->id)) {
5008 CDINFO_FATAL(app_data.str_nomemory);
5009 return FALSE;
5010 }
5011 }
5012 else {
5013 MEM_FREE(cdinfo_dbp->disc.genre);
5014 cdinfo_dbp->disc.genre = NULL;
5015 }
5016 }
5017 }
5018
5019 if (cdinfo_dbp->matchlist == NULL)
5020 cdinfo_dbp->matchlist = mp = mp2;
5021 else {
5022 mp->next = mp2;
5023 mp = mp2;
5024 }
5025
5026 CddbReleaseObject(discp);
5027 }
5028 }
5029 return TRUE;
5030 }
5031
5032
5033 /*
5034 * cdinfo_ctrlver_init
5035 * Query CDDB control version information initialize the incore struct.
5036 *
5037 * Args:
5038 * cp - cdinfo_cddb_t pointer for the CDDB connection
5039 *
5040 * Return:
5041 * TRUE - success
5042 * FALSE - failure
5043 */
5044 STATIC bool_t
cdinfo_ctrlver_init(cdinfo_cddb_t * cp)5045 cdinfo_ctrlver_init(cdinfo_cddb_t *cp)
5046 {
5047 return cdinfo_get_str("CddbControl_GetVersion",
5048 CddbControl_GetVersion, cp->ctrlp,
5049 &cdinfo_dbp->ctrl_ver);
5050 }
5051
5052
5053 /*
5054 * cdinfo_chk_service
5055 * Check CDDB service for good network connectivity, and that the
5056 * server is up and functional.
5057 *
5058 * Args:
5059 * cp - cdinfo_cddb_t pointer for the CDDB connection
5060 *
5061 * Return:
5062 * TRUE - success
5063 * FALSE - failure
5064 */
5065 STATIC bool_t
cdinfo_chk_service(cdinfo_cddb_t * cp)5066 cdinfo_chk_service(cdinfo_cddb_t *cp)
5067 {
5068 CddbResult ret;
5069 CddbStr str;
5070
5071 DBGPRN(DBG_CDI)(errfp, "CddbControl_GetServiceStatus: ");
5072 ret = CddbControl_GetServiceStatus(cp->ctrlp, &str);
5073 if ((app_data.debug & DBG_CDI) && str != NULL) {
5074 /* Strip out extra newlines */
5075 while (str[strlen(str)-1] == '\n')
5076 str[strlen(str)-1] = '\0';
5077 }
5078 DBGPRN(DBG_CDI)(errfp, "0x%lx %s\n", ret, str == NULL ? "" : str);
5079
5080 cdinfo_set_errstr(ret);
5081
5082 if (ret != Cddb_OK)
5083 return FALSE;
5084
5085 DBGPRN(DBG_CDI)(errfp, "CddbControl_ServerNoop: ");
5086 ret = CddbControl_ServerNoop(cp->ctrlp, 0);
5087 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
5088
5089 cdinfo_set_errstr(ret);
5090
5091 return (ret == Cddb_OK);
5092 }
5093
5094
5095 /*
5096 * cdinfo_genrelist_init
5097 * Query genre tree information from CDDB and initialize the genre list.
5098 *
5099 * Args:
5100 * cp - cdinfo_cddb_t pointer for the CDDB connection
5101 *
5102 * Return:
5103 * TRUE - Success
5104 * FALSE - Failure
5105 */
5106 STATIC bool_t
cdinfo_genrelist_init(cdinfo_cddb_t * cp)5107 cdinfo_genrelist_init(cdinfo_cddb_t *cp)
5108 {
5109 CddbResult ret;
5110 CddbGenreTreePtr gtreep;
5111 CddbGenreListPtr glistp;
5112 CddbGenrePtr genrep;
5113 long cnt,
5114 subcnt;
5115 int i,
5116 j;
5117 cdinfo_genre_t *p,
5118 *q,
5119 *r,
5120 *s;
5121
5122 DBGPRN(DBG_CDI)(errfp, "CddbControl_GetGenreTree: ");
5123 ret = CddbControl_GetGenreTree(cp->ctrlp, 0, >reep);
5124 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
5125
5126 cdinfo_set_errstr(ret);
5127
5128 if (ret != Cddb_OK || gtreep == NULL)
5129 return FALSE;
5130
5131 DBGPRN(DBG_CDI)(errfp, "CddbGenreTree_GetCount: ");
5132 ret = CddbGenreTree_GetCount(gtreep, &cnt);
5133 DBGPRN(DBG_CDI)(errfp, "0x%lx %ld\n", ret, cnt);
5134
5135 q = NULL;
5136 for (i = 1; i <= (int) cnt; i++) {
5137 DBGPRN(DBG_CDI)(errfp, "CddbGenreTree_GetMetaGenre[%d]: ", i);
5138 ret = CddbGenreTree_GetMetaGenre(gtreep, (long) i, &genrep);
5139 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
5140
5141 if (ret != Cddb_OK) {
5142 CddbReleaseObject(gtreep);
5143 return FALSE;
5144 }
5145
5146 /* Allocate genre entry and fill it with genre info */
5147 if (!cdinfo_allocinit_genre(genrep, &p, FALSE)) {
5148 CddbReleaseObject(genrep);
5149 CddbReleaseObject(gtreep);
5150 return FALSE;
5151 }
5152
5153 CddbReleaseObject(genrep);
5154
5155 /* Sub-Genre list */
5156 DBGPRN(DBG_CDI)(errfp, " CddbGenreTree_GetSubGenreList: ");
5157 ret = CddbGenreTree_GetSubGenreList(gtreep, p->id, &glistp);
5158 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
5159
5160 if (ret != Cddb_OK) {
5161 CddbReleaseObject(gtreep);
5162 return FALSE;
5163 }
5164
5165 DBGPRN(DBG_CDI)(errfp, " CddbGenreList_GetCount: ");
5166 ret = CddbGenreList_GetCount(glistp, &subcnt);
5167 DBGPRN(DBG_CDI)(errfp, "0x%lx %ld\n", ret, subcnt);
5168
5169 r = NULL;
5170 for (j = 1; j <= (int) subcnt; j++) {
5171 DBGPRN(DBG_CDI)(errfp,
5172 " CddbGenreList_GetGenre[%d]: ", j);
5173 ret = CddbGenreList_GetGenre(glistp,
5174 (long) j, &genrep);
5175 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
5176
5177 /* Allocate genre entry and fill it with genre info */
5178 if (!cdinfo_allocinit_genre(genrep, &s, TRUE)) {
5179 CddbReleaseObject(genrep);
5180 CddbReleaseObject(glistp);
5181 CddbReleaseObject(gtreep);
5182 return FALSE;
5183 }
5184
5185 CddbReleaseObject(genrep);
5186
5187 s->parent = p;
5188 if (p->child == NULL)
5189 p->child = r = s;
5190 else {
5191 r->next = s;
5192 r = s;
5193 }
5194 }
5195
5196 CddbReleaseObject(glistp);
5197
5198 if (cdinfo_dbp->genrelist == NULL)
5199 cdinfo_dbp->genrelist = q = p;
5200 else {
5201 q->next = p;
5202 q = p;
5203 }
5204 p->parent = NULL;
5205 }
5206
5207 CddbReleaseObject(gtreep);
5208 return TRUE;
5209 }
5210
5211
5212 /*
5213 * cdinfo_regionlist_init
5214 * Query region list information from CDDB and initialize the region list.
5215 *
5216 * Args:
5217 * cp - cdinfo_cddb_t pointer for the CDDB connection
5218 *
5219 * Return:
5220 * TRUE - Success
5221 * FALSE - Failure
5222 */
5223 STATIC bool_t
cdinfo_regionlist_init(cdinfo_cddb_t * cp)5224 cdinfo_regionlist_init(cdinfo_cddb_t *cp)
5225 {
5226 CddbResult ret;
5227 CddbRegionListPtr relistp;
5228 CddbRegionPtr regionp;
5229 cdinfo_region_t *p,
5230 *q;
5231 long cnt;
5232 int i;
5233
5234 DBGPRN(DBG_CDI)(errfp, "CddbControl_GetRegionList: ");
5235 ret = CddbControl_GetRegionList(cp->ctrlp, 0, &relistp);
5236 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
5237
5238 cdinfo_set_errstr(ret);
5239
5240 if (ret != Cddb_OK)
5241 return FALSE;
5242
5243 DBGPRN(DBG_CDI)(errfp, "CddbRegionList_GetCount: ");
5244 ret = CddbRegionList_GetCount(relistp, &cnt);
5245 DBGPRN(DBG_CDI)(errfp, "0x%lx %ld\n", ret, cnt);
5246
5247 q = NULL;
5248 for (i = 1; i <= (int) cnt; i++) {
5249 DBGPRN(DBG_CDI)(errfp, "CddbRegionList_GetRegion[%d]: ", i);
5250 ret = CddbRegionList_GetRegion(relistp, (long) i, ®ionp);
5251 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
5252
5253 if (ret != Cddb_OK) {
5254 CddbReleaseObject(relistp);
5255 return FALSE;
5256 }
5257
5258 /* Allocate region entry and fill it with region info */
5259 if (!cdinfo_allocinit_region(regionp, &p)) {
5260 CddbReleaseObject(regionp);
5261 CddbReleaseObject(relistp);
5262 return FALSE;
5263 }
5264
5265 CddbReleaseObject(regionp);
5266
5267 if (cdinfo_dbp->regionlist == NULL)
5268 cdinfo_dbp->regionlist = q = p;
5269 else {
5270 q->next = p;
5271 q = p;
5272 }
5273 }
5274
5275 CddbReleaseObject(relistp);
5276 return TRUE;
5277 }
5278
5279
5280 /*
5281 * cdinfo_langlist_init
5282 * Query language list information from CDDB and initialize the
5283 * language list.
5284 *
5285 * Args:
5286 * cp - cdinfo_cddb_t pointer for the CDDB connection
5287 *
5288 * Return:
5289 * TRUE - Success
5290 * FALSE - Failure
5291 */
5292 STATIC bool_t
cdinfo_langlist_init(cdinfo_cddb_t * cp)5293 cdinfo_langlist_init(cdinfo_cddb_t *cp)
5294 {
5295 CddbResult ret;
5296 CddbLanguageListPtr langlistp;
5297 CddbLanguagePtr langp;
5298 cdinfo_lang_t *p,
5299 *q;
5300 long cnt;
5301 int i;
5302
5303 DBGPRN(DBG_CDI)(errfp, "CddbControl_GetLanguageList: ");
5304 ret = CddbControl_GetLanguageList(cp->ctrlp, 0, &langlistp);
5305 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
5306
5307 cdinfo_set_errstr(ret);
5308
5309 if (ret != Cddb_OK)
5310 return FALSE;
5311
5312 DBGPRN(DBG_CDI)(errfp, "CddbLanguageList_GetCount: ");
5313 ret = CddbLanguageList_GetCount(langlistp, &cnt);
5314 DBGPRN(DBG_CDI)(errfp, "0x%lx %ld\n", ret, cnt);
5315
5316 q = NULL;
5317 for (i = 1; i <= (int) cnt; i++) {
5318 DBGPRN(DBG_CDI)(errfp,
5319 "CddbLanguageList_GetLanguage[%d]: ", i);
5320 ret = CddbLanguageList_GetLanguage(
5321 langlistp, (long) i, &langp
5322 );
5323 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
5324
5325 if (ret != Cddb_OK) {
5326 CddbReleaseObject(langlistp);
5327 return FALSE;
5328 }
5329
5330 /* Allocate language entry and fill it with language info */
5331 if (!cdinfo_allocinit_lang(langp, &p)) {
5332 CddbReleaseObject(langp);
5333 CddbReleaseObject(langlistp);
5334 return FALSE;
5335 }
5336
5337 CddbReleaseObject(langp);
5338
5339 if (cdinfo_dbp->langlist == NULL)
5340 cdinfo_dbp->langlist = q = p;
5341 else {
5342 q->next = p;
5343 q = p;
5344 }
5345 }
5346
5347 CddbReleaseObject(langlistp);
5348 return TRUE;
5349 }
5350
5351
5352 /*
5353 * cdinfo_rolelist_init
5354 * Query role list information from CDDB and initialize the role list.
5355 *
5356 * Args:
5357 * cp - cdinfo_cddb_t pointer for the CDDB connection
5358 *
5359 * Return:
5360 * TRUE - Success
5361 * FALSE - Failure
5362 */
5363 STATIC bool_t
cdinfo_rolelist_init(cdinfo_cddb_t * cp)5364 cdinfo_rolelist_init(cdinfo_cddb_t *cp)
5365 {
5366 CddbResult ret;
5367 CddbRoleTreePtr rotreep;
5368 CddbRoleListPtr rolistp;
5369 CddbRolePtr rolep;
5370 long tcnt,
5371 lcnt;
5372 int i,
5373 j;
5374 cdinfo_role_t *p,
5375 *q,
5376 *r,
5377 *s;
5378
5379 DBGPRN(DBG_CDI)(errfp, "CddbControl_GetRoleTree: ");
5380 ret = CddbControl_GetRoleTree(cp->ctrlp, 0, &rotreep);
5381 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
5382
5383 cdinfo_set_errstr(ret);
5384
5385 if (ret != Cddb_OK)
5386 return FALSE;
5387
5388 DBGPRN(DBG_CDI)(errfp, "CddbRoleTree_GetCount: ");
5389 ret = CddbRoleTree_GetCount(rotreep, &tcnt);
5390 DBGPRN(DBG_CDI)(errfp, "0x%lx %ld\n", ret, tcnt);
5391
5392 q = NULL;
5393 for (i = 1; i <= (int) tcnt; i++) {
5394 DBGPRN(DBG_CDI)(errfp, "CddbRoleTree_GetRoleList[%d]: ", i);
5395 ret = CddbRoleTree_GetRoleList(rotreep, (long) i, &rolistp);
5396 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
5397
5398 if (ret != Cddb_OK) {
5399 CddbReleaseObject(rotreep);
5400 return FALSE;
5401 }
5402
5403 DBGPRN(DBG_CDI)(errfp, " CddbRoleList_GetCategoryRole: ");
5404 ret = CddbRoleList_GetCategoryRole(rolistp, &rolep);
5405 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
5406
5407 if (ret != Cddb_OK) {
5408 CddbReleaseObject(rolistp);
5409 CddbReleaseObject(rotreep);
5410 return FALSE;
5411 }
5412
5413 /* Allocate role entry and fill it with role info */
5414 if (!cdinfo_allocinit_role(rolep, &p)) {
5415 CddbReleaseObject(rolep);
5416 CddbReleaseObject(rolistp);
5417 CddbReleaseObject(rotreep);
5418 return FALSE;
5419 }
5420
5421 CddbReleaseObject(rolep);
5422
5423 DBGPRN(DBG_CDI)(errfp, " CddbRoleList_GetCount: ");
5424 ret = CddbRoleList_GetCount(rolistp, &lcnt);
5425 DBGPRN(DBG_CDI)(errfp, "0x%lx %ld\n", ret, lcnt);
5426
5427 r = NULL;
5428 for (j = 1; j <= (int) lcnt; j++) {
5429 DBGPRN(DBG_CDI)(errfp,
5430 " CddbRoleList_GetRole[%d]: ", j);
5431 ret = CddbRoleList_GetRole(rolistp, (long) j, &rolep);
5432 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
5433
5434 if (ret != Cddb_OK) {
5435 CddbReleaseObject(rolistp);
5436 CddbReleaseObject(rotreep);
5437 return FALSE;
5438 }
5439
5440 /* Allocate role entry and fill it with role info */
5441 if (!cdinfo_allocinit_role(rolep, &s)) {
5442 CddbReleaseObject(rolep);
5443 CddbReleaseObject(rolistp);
5444 CddbReleaseObject(rotreep);
5445 return FALSE;
5446 }
5447
5448 CddbReleaseObject(rolep);
5449
5450 s->parent = p;
5451 if (p->child == NULL)
5452 p->child = r = s;
5453 else {
5454 r->next = s;
5455 r = s;
5456 }
5457 }
5458
5459 CddbReleaseObject(rolistp);
5460
5461 if (cdinfo_dbp->rolelist == NULL)
5462 cdinfo_dbp->rolelist = q = p;
5463 else {
5464 q->next = p;
5465 q = p;
5466 }
5467 p->parent = NULL;
5468 }
5469
5470 CddbReleaseObject(rotreep);
5471 return TRUE;
5472 }
5473
5474
5475 /*
5476 * cdinfo_opencddb
5477 * Open a remote CDDB connection
5478 *
5479 * Args:
5480 * s - Pointer to the curstat_t structure
5481 * query - Whether we're opening CDDB connection for a query operation
5482 * retcode - return status code
5483 *
5484 * Return:
5485 * Open descriptor cdbinfo_file_t
5486 */
5487 /*ARGSUSED*/
5488 cdinfo_cddb_t *
cdinfo_opencddb(curstat_t * s,bool_t query,int * retcode)5489 cdinfo_opencddb(curstat_t *s, bool_t query, int *retcode)
5490 {
5491 CddbOptionsPtr optp = NULL;
5492 cdinfo_cddb_t *cp;
5493 CddbResult ret;
5494 int i;
5495 long cacheflags;
5496 char cache_path[FILE_PATH_SZ];
5497
5498 /* Default is success */
5499 *retcode = 0;
5500
5501 if (cdinfo_cddbp != NULL) {
5502 /* Already opened - only one open allowed at a time */
5503 *retcode = OPEN_ERR;
5504 return NULL;
5505 }
5506
5507 /* Allocate cdinfo_cddb_t */
5508 cp = (cdinfo_cddb_t *)(void *) MEM_ALLOC(
5509 "cdinfo_cddb_t",
5510 sizeof(cdinfo_cddb_t)
5511 );
5512 if (cp == NULL) {
5513 *retcode = MEM_ERR;
5514 CDINFO_FATAL(app_data.str_nomemory);
5515 return NULL;
5516 }
5517
5518 /* Save pointer for signal handler */
5519 cdinfo_cddbp = cp;
5520
5521 DBGPRN(DBG_CDI)(errfp, "\nOpening CDDB service...\n");
5522
5523 DBGPRN(DBG_CDI)(errfp, "CddbInitialize: ");
5524 ret = CddbInitialize((CddbControlPtr *) &cp->ctrlp);
5525 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
5526
5527 switch (ret) {
5528 case Cddb_OK:
5529 if (cddb_ifver() != 2) {
5530 *retcode = LIBCDDB_ERR;
5531 (void) fprintf(errfp,
5532 "ERROR: libcddb and libcddbkey mismatch (2:1).\n");
5533 return NULL;
5534 }
5535 break;
5536
5537 case Cddb_ISCDDB1:
5538 if (cddb_ifver() != 1) {
5539 *retcode = LIBCDDB_ERR;
5540 (void) fprintf(errfp,
5541 "ERROR: libcddb and libcddbkey mismatch (1:2).\n");
5542 return NULL;
5543 }
5544 break;
5545
5546 default:
5547 cdinfo_set_errstr(ret);
5548 *retcode = INIT_ERR;
5549 return NULL;
5550 }
5551
5552 if (cp->ctrlp == NULL ||
5553 !cddb_setkey(cp, cdinfo_clinfo, &app_data, s, errfp)) {
5554 *retcode = INIT_ERR;
5555 return NULL;
5556 }
5557
5558 i = 0;
5559 for (;;) {
5560 DBGPRN(DBG_CDI)(errfp, "CddbControl_Initialize: ");
5561 ret = CddbControl_Initialize(
5562 cp->ctrlp, 0,
5563 app_data.cdinfo_inetoffln ?
5564 CACHE_DONT_CONNECT : CACHE_DEFAULT
5565 );
5566 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
5567
5568 if (ret == Cddb_OK || ret == Cddb_FALSE)
5569 break;
5570
5571 if (++i > 1) {
5572 cdinfo_set_errstr(ret);
5573 (void) cdinfo_closecddb(cp);
5574 *retcode = INIT_ERR;
5575 return NULL;
5576 }
5577
5578 /* Try removing the cache file */
5579 (void) sprintf(cache_path, "%s/.cddb2/%s/cddb.ds",
5580 util_homedir(util_get_ouid()),
5581 XMCD_CLIENT_ID);
5582 (void) UNLINK(cache_path);
5583 }
5584
5585 DBGPRN(DBG_CDI)(errfp, "CddbControl_GetOptions: ");
5586 ret = CddbControl_GetOptions(cp->ctrlp, &optp);
5587 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
5588
5589 if (ret == Cddb_OK && optp != NULL) {
5590 if (app_data.use_proxy) {
5591 char *p;
5592 long port = HTTP_PORT;
5593
5594 if ((p = strchr(app_data.proxy_server, ':')) != NULL){
5595 *p = '\0';
5596 port = atol(p+1);
5597 }
5598
5599 /* Proxy server */
5600 (void) cdinfo_put_str("CddbOptions_PutProxyServer",
5601 CddbOptions_PutProxyServer, optp,
5602 app_data.proxy_server
5603 );
5604
5605 /* Proxy server port */
5606 DBGPRN(DBG_CDI)(errfp,
5607 "CddbOptions_PutProxyServerPort: ");
5608 ret = CddbOptions_PutProxyServerPort(optp, port);
5609 DBGPRN(DBG_CDI)(errfp, "0x%lx port %ld\n", ret, port);
5610
5611 if (p != NULL)
5612 *p = ':';
5613
5614 if (app_data.proxy_auth) {
5615 if (cdinfo_dbp->proxy_user == NULL ||
5616 cdinfo_dbp->proxy_passwd == NULL) {
5617 CddbReleaseObject(optp);
5618
5619 *retcode = AUTH_ERR;
5620 (void) cdinfo_closecddb(cp);
5621 return NULL;
5622 }
5623
5624 #ifdef __VMS
5625 /* Hack to work around a memory
5626 * corruption problem on VMS.
5627 */
5628 {
5629 static char *sav_user = NULL,
5630 *sav_pass = NULL;
5631
5632 if (cdinfo_dbp->proxy_user[0] == '\0' ||
5633 cdinfo_dbp->proxy_passwd[0] == '\0') {
5634 if (sav_user != NULL &&
5635 sav_pass != NULL) {
5636 (void) strcpy(
5637 cdinfo_dbp->proxy_user,
5638 sav_user
5639 );
5640 (void) strcpy(
5641 cdinfo_dbp->proxy_passwd,
5642 sav_pass
5643 );
5644 }
5645 }
5646 else {
5647 if (!util_newstr(&sav_user,
5648 cdinfo_dbp->proxy_user) ||
5649 !util_newstr(&sav_pass,
5650 cdinfo_dbp->proxy_passwd)){
5651 *retcode = MEM_ERR;
5652 return NULL;
5653 }
5654 }
5655 }
5656 #endif /* __VMS */
5657
5658 /* Proxy user name */
5659 (void) cdinfo_put_str(
5660 "CddbOptions_PutProxyUserName",
5661 CddbOptions_PutProxyUserName, optp,
5662 cdinfo_dbp->proxy_user
5663 );
5664
5665 /* Proxy password */
5666 (void) cdinfo_put_str(
5667 "CddbOptions_PutProxyPassword",
5668 CddbOptions_PutProxyPassword, optp,
5669 cdinfo_dbp->proxy_passwd
5670 );
5671 }
5672 }
5673 else {
5674 /* Clear proxy server settings if any */
5675 (void) cdinfo_put_str(
5676 "CddbOptions_PutProxyServer",
5677 CddbOptions_PutProxyServer, optp,
5678 NULL
5679 );
5680
5681 /* Clear proxy server user name if any */
5682 (void) cdinfo_put_str(
5683 "CddbOptions_PutProxyUserName",
5684 CddbOptions_PutProxyUserName, optp,
5685 NULL
5686 );
5687
5688 /* Clear proxy server password if any */
5689 (void) cdinfo_put_str(
5690 "CddbOptions_PutProxyPassword",
5691 CddbOptions_PutProxyPassword, optp,
5692 NULL
5693 );
5694 }
5695
5696 /* Set local cache flags */
5697 cacheflags = app_data.cdinfo_inetoffln ?
5698 CACHE_DONT_CONNECT : CACHE_DEFAULT;
5699 DBGPRN(DBG_CDI)(errfp, "CddbOptions_PutLocalCacheFlags: ");
5700 ret = CddbOptions_PutLocalCacheFlags(optp, cacheflags);
5701 DBGPRN(DBG_CDI)(errfp, "0x%lx flags=0x%lx\n", ret, cacheflags);
5702
5703 /* Set local cache timeout value */
5704 DBGPRN(DBG_CDI)(errfp, "CddbOptions_PutLocalCacheTimeout: ");
5705 ret = CddbOptions_PutLocalCacheTimeout(
5706 optp, (long) app_data.cache_timeout
5707 );
5708 DBGPRN(DBG_CDI)(errfp,
5709 "0x%lx %d\n", ret, app_data.cache_timeout);
5710
5711 /* Set server timeout value */
5712 DBGPRN(DBG_CDI)(errfp, "CddbOptions_PutServerTimeout: ");
5713 ret = CddbOptions_PutServerTimeout(
5714 optp, (long) (app_data.srv_timeout * 1000)
5715 );
5716 DBGPRN(DBG_CDI)(errfp,
5717 "0x%lx %d\n", ret, app_data.srv_timeout * 1000);
5718
5719 DBGPRN(DBG_CDI)(errfp, "CddbOptions_PutTestSubmitMode: ");
5720 #ifdef CDINFO_PRODUCTION
5721 ret = CddbOptions_PutTestSubmitMode(optp, 0);
5722 DBGPRN(DBG_CDI)(errfp, "0x%lx False\n", ret);
5723 #else
5724 ret = CddbOptions_PutTestSubmitMode(optp, 1);
5725 DBGPRN(DBG_CDI)(errfp, "0x%lx True\n", ret);
5726 #endif
5727
5728 /* Write out options */
5729 DBGPRN(DBG_CDI)(errfp, "CddbControl_SetOptions: ");
5730 ret = CddbControl_SetOptions(cp->ctrlp, optp);
5731 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
5732
5733 CddbReleaseObject(optp);
5734 }
5735
5736 return (cp);
5737 }
5738
5739
5740 /*
5741 * cdinfo_closecddb
5742 * Close a remote CDDB connection
5743 *
5744 * Args:
5745 * cp - Pointer to the cdinfo_cddb_t structure returned from
5746 * cdinfo_opencddb.
5747 *
5748 * Return:
5749 * TRUE - Success
5750 * FALSE - Failure
5751 */
5752 bool_t
cdinfo_closecddb(cdinfo_cddb_t * cp)5753 cdinfo_closecddb(cdinfo_cddb_t *cp)
5754 {
5755 CddbResult ret;
5756
5757 if (cp == NULL)
5758 return FALSE;
5759
5760 if (cp->ctrlp != NULL) {
5761 DBGPRN(DBG_CDI)(errfp, "CddbControl_Shutdown: ");
5762 ret = CddbControl_Shutdown(cp->ctrlp);
5763 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
5764
5765 DBGPRN(DBG_CDI)(errfp, "CddbTerminate: ");
5766 ret = CddbTerminate(cp->ctrlp);
5767 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
5768 }
5769
5770 MEM_FREE(cp);
5771 cdinfo_cddbp = NULL;
5772
5773 return TRUE;
5774 }
5775
5776
5777 /*
5778 * cdinfo_initcddb
5779 * Perform CDDB initializations
5780 *
5781 * Args:
5782 * cp - Pointer to the cdinfo_cddb_t structure returned from
5783 * cdinfo_opencddb.
5784 * retcode - Pointer to location where a cdinfo_ret_t code is returned.
5785 *
5786 * Return:
5787 * TRUE - Success
5788 * FALSE - Failure
5789 */
5790 bool_t
cdinfo_initcddb(cdinfo_cddb_t * cp,cdinfo_ret_t * retcode)5791 cdinfo_initcddb(cdinfo_cddb_t *cp, cdinfo_ret_t *retcode)
5792 {
5793 *retcode = 0;
5794
5795 /* Get CDDB control version */
5796 if (cdinfo_dbp->ctrl_ver == NULL && !cdinfo_ctrlver_init(cp)) {
5797 *retcode = READ_ERR;
5798 return FALSE;
5799 }
5800
5801 /* Set up region list if not done */
5802 if (cdinfo_dbp->regionlist == NULL && !cdinfo_regionlist_init(cp)) {
5803 *retcode = READ_ERR;
5804 return FALSE;
5805 }
5806
5807 /* Set up language list if not done */
5808 if (cdinfo_dbp->langlist == NULL && !cdinfo_langlist_init(cp)) {
5809 *retcode = READ_ERR;
5810 return FALSE;
5811 }
5812
5813 if ((app_data.debug & DBG_CDI) != 0 && !app_data.cdinfo_inetoffln &&
5814 !cdinfo_chk_service(cp)) {
5815 *retcode = READ_ERR;
5816 return FALSE;
5817 }
5818
5819 /* Check user registration */
5820 if (!cdinfo_check_userreg(cp)) {
5821 cdinfo_dbp->flags |= CDINFO_NEEDREG;
5822 return TRUE;
5823 }
5824
5825 /* Set up role list if not done */
5826 if (cdinfo_dbp->rolelist == NULL && !cdinfo_rolelist_init(cp)) {
5827 *retcode = READ_ERR;
5828 return FALSE;
5829 }
5830
5831 /* Set up genre list if not done */
5832 if (cdinfo_dbp->genrelist == NULL && !cdinfo_genrelist_init(cp)) {
5833 *retcode = READ_ERR;
5834 return FALSE;
5835 }
5836
5837 /* Query CDDB about general URLs if not done */
5838 if (cdinfo_dbp->gen_url_list == NULL && !cdinfo_urls_query(cp, NULL)) {
5839 *retcode = READ_ERR;
5840 return FALSE;
5841 }
5842
5843 return TRUE;
5844 }
5845
5846
5847 /*
5848 * cdinfo_querycddb
5849 * Read CDDB data for the current CD and update incore structures.
5850 *
5851 * Args:
5852 * cp - Pointer to the cdinfo_cddb_t structure returned from
5853 * cdinfo_opencddb.
5854 * s - Pointer to curstat_t structure.
5855 * retcode - Pointer to location where a cdinfo_ret_t code is returned.
5856 *
5857 * Return:
5858 * TRUE - Success
5859 * FALSE - Failure
5860 */
5861 bool_t
cdinfo_querycddb(cdinfo_cddb_t * cp,curstat_t * s,cdinfo_ret_t * retcode)5862 cdinfo_querycddb(cdinfo_cddb_t *cp, curstat_t *s, cdinfo_ret_t *retcode)
5863 {
5864 CddbDiscPtr discp = NULL,
5865 discp2;
5866 CddbDiscsPtr discsp = NULL;
5867 CddbStr tocstr;
5868 CddbResult ret;
5869 CDDBMatchCode matchcode = MATCH_NONE;
5870
5871 if (!cdinfo_initcddb(cp, retcode))
5872 return FALSE;
5873
5874 if ((cdinfo_dbp->flags & CDINFO_NEEDREG) != 0)
5875 return TRUE;
5876
5877 if (cdinfo_dbp->match_tag == -1) {
5878 /* Query by TOC */
5879
5880 tocstr = (CddbStr) cdinfo_tocstr(s);
5881 DBGPRN(DBG_CDI)(errfp, "TOC string: %s\n", tocstr);
5882
5883 DBGPRN(DBG_CDI)(errfp, "CddbControl_LookupMediaByToc: ");
5884 ret = CddbControl_LookupMediaByToc(
5885 cp->ctrlp, tocstr, 0, &matchcode
5886 );
5887 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
5888
5889 cdinfo_set_errstr(ret);
5890
5891 if (ret != Cddb_OK) {
5892 if (ret == CDDBTRNHTTPProxyError)
5893 *retcode = AUTH_ERR;
5894 else
5895 *retcode = READ_ERR;
5896 return FALSE;
5897 }
5898
5899 switch (matchcode) {
5900 case MATCH_EXACT:
5901 DBGPRN(DBG_CDI)(errfp, "Exact CDDB match\n");
5902
5903 DBGPRN(DBG_CDI)(errfp, "CddbControl_GetMatchedDisc: ");
5904 ret = CddbControl_GetMatchedDisc(cp->ctrlp, &discp);
5905 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
5906
5907 cdinfo_set_errstr(ret);
5908
5909 if (ret != Cddb_OK || discp == NULL) {
5910 *retcode = READ_ERR;
5911 return FALSE;
5912 }
5913 break;
5914
5915 case MATCH_MULTIPLE:
5916 DBGPRN(DBG_CDI)(errfp, "Multiple CDDB matches\n");
5917
5918 /* Get the list of matching discs.
5919 * Each one is a partial disc
5920 */
5921 DBGPRN(DBG_CDI)(errfp,
5922 "CddbControl_GetMatchedDiscs: ");
5923 ret = CddbControl_GetMatchedDiscs(cp->ctrlp, &discsp);
5924 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
5925
5926 cdinfo_set_errstr(ret);
5927
5928 if (ret != Cddb_OK || discsp == NULL) {
5929 *retcode = READ_ERR;
5930 return FALSE;
5931 }
5932
5933 /* Build matchlist */
5934 if (!cdinfo_build_matchlist(discsp)) {
5935 /* Failure */
5936 CddbReleaseObject(discsp);
5937 *retcode = READ_ERR;
5938 return FALSE;
5939 }
5940
5941 /* Save discs pointer - release later */
5942 cdinfo_dbp->match_aux = (void *) discsp;
5943 return TRUE;
5944
5945 case MATCH_NONE:
5946 DBGPRN(DBG_CDI)(errfp, "No CDDB match\n");
5947 return TRUE;
5948
5949 default:
5950 DBGPRN(DBG_CDI)(errfp, "Unknown CDDB matchcode 0x%x\n",
5951 matchcode);
5952 *retcode = READ_ERR;
5953 return FALSE;
5954 }
5955 }
5956 else {
5957 /* Query after fuzzy selection */
5958
5959 discsp = (CddbDiscsPtr) cdinfo_dbp->match_aux;
5960
5961 if (cdinfo_dbp->match_tag == 0) {
5962 /* User chose "none of the above" */
5963 CddbReleaseObject(discsp);
5964 return TRUE;
5965 }
5966
5967 DBGPRN(DBG_CDI)(errfp,
5968 "CddbDiscs_GetDisc[%ld]: ", cdinfo_dbp->match_tag);
5969 ret = CddbDiscs_GetDisc(discsp,
5970 cdinfo_dbp->match_tag,
5971 &discp2
5972 );
5973 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
5974
5975 cdinfo_set_errstr(ret);
5976
5977 if (ret != Cddb_OK || discp2 == NULL) {
5978 CddbReleaseObject(discsp);
5979 *retcode = READ_ERR;
5980 return FALSE;
5981 }
5982
5983 DBGPRN(DBG_CDI)(errfp, "CddbControl_GetFullDiscInfo: ");
5984 ret = CddbControl_GetFullDiscInfo(
5985 cp->ctrlp, discp2, 0, &discp
5986 );
5987 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
5988
5989 cdinfo_set_errstr(ret);
5990
5991 if (ret != Cddb_OK) {
5992 CddbReleaseObject(discp2);
5993 CddbReleaseObject(discsp);
5994 *retcode = READ_ERR;
5995 return FALSE;
5996 }
5997
5998 CddbReleaseObject(discp2);
5999 CddbReleaseObject(discsp);
6000 }
6001
6002 /* Query CDDB about the disc */
6003 if (!cdinfo_discinfo_query(discp)) {
6004 *retcode = READ_ERR;
6005 return FALSE;
6006 }
6007
6008 /* Query CDDB about the tracks */
6009 if (!cdinfo_trackinfo_query(discp)) {
6010 *retcode = READ_ERR;
6011 return FALSE;
6012 }
6013
6014 /* Query CDDB about the disc-related URLs */
6015 if (!cdinfo_urls_query(cp, discp)) {
6016 *retcode = READ_ERR;
6017 return FALSE;
6018 }
6019
6020 CddbReleaseObject(discp);
6021
6022 cdinfo_dbp->flags |= CDINFO_MATCH;
6023 return TRUE;
6024 }
6025
6026
6027 /*
6028 * cdinfo_uregcddb
6029 * Register the user with CDDB
6030 *
6031 * Args:
6032 * cp - Pointer to the cdinfo_cddb_t structure returned from
6033 * cdinfo_opencddb.
6034 * retcode - return status code
6035 *
6036 * Return:
6037 * TRUE - Success
6038 * FALSE - Failure
6039 */
6040 bool_t
cdinfo_uregcddb(cdinfo_cddb_t * cp,cdinfo_ret_t * retcode)6041 cdinfo_uregcddb(cdinfo_cddb_t *cp, cdinfo_ret_t *retcode)
6042 {
6043 CddbUserInfoPtr uip = NULL;
6044 CddbResult ret;
6045 CddbBoolean registered = 0;
6046
6047 if (cdinfo_dbp->userreg.handle == NULL ||
6048 cdinfo_dbp->userreg.passwd == NULL) {
6049 *retcode = REGI_ERR;
6050 return FALSE;
6051 }
6052
6053 DBGPRN(DBG_CDI)(errfp, "CddbControl_GetUserInfo: ");
6054 ret = CddbControl_GetUserInfo(cp->ctrlp, &uip);
6055 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
6056
6057 cdinfo_set_errstr(ret);
6058
6059 if (ret != Cddb_OK && uip == NULL) {
6060 *retcode = REGI_ERR;
6061 return FALSE;
6062 }
6063
6064 (void) cdinfo_put_str("CddbUserInfo_PutUserHandle",
6065 CddbUserInfo_PutUserHandle, uip,
6066 cdinfo_dbp->userreg.handle
6067 );
6068 (void) cdinfo_put_str("CddbUserInfo_PutPassword",
6069 CddbUserInfo_PutPassword, uip,
6070 cdinfo_dbp->userreg.passwd
6071 );
6072 (void) cdinfo_put_str("CddbUserInfo_PutPasswordHint",
6073 CddbUserInfo_PutPasswordHint, uip,
6074 cdinfo_dbp->userreg.hint == NULL ?
6075 "" : cdinfo_dbp->userreg.hint
6076 );
6077 (void) cdinfo_put_str("CddbUserInfo_PutEmailAddress",
6078 CddbUserInfo_PutEmailAddress, uip,
6079 cdinfo_dbp->userreg.email == NULL ?
6080 "" : cdinfo_dbp->userreg.email
6081 );
6082 (void) cdinfo_put_str("CddbUserInfo_PutRegionId",
6083 CddbUserInfo_PutRegionId, uip,
6084 cdinfo_dbp->userreg.region == NULL ?
6085 "" : cdinfo_dbp->userreg.region
6086 );
6087 (void) cdinfo_put_str("CddbUserInfo_PutPostalCode",
6088 CddbUserInfo_PutPostalCode, uip,
6089 cdinfo_dbp->userreg.postal == NULL ?
6090 "" : cdinfo_dbp->userreg.postal
6091 );
6092 (void) cdinfo_put_str("CddbUserInfo_PutAge",
6093 CddbUserInfo_PutAge, uip,
6094 cdinfo_dbp->userreg.age == NULL ?
6095 "" : cdinfo_dbp->userreg.age
6096 );
6097 (void) cdinfo_put_str("CddbUserInfo_PutSex",
6098 CddbUserInfo_PutSex, uip,
6099 cdinfo_dbp->userreg.gender == NULL ?
6100 "" : cdinfo_dbp->userreg.gender
6101 );
6102
6103 DBGPRN(DBG_CDI)(errfp, "CddbUserInfo_PutAllowEmail: ");
6104 ret = CddbUserInfo_PutAllowEmail(uip,
6105 (CddbBoolean) cdinfo_dbp->userreg.allowemail
6106 );
6107 DBGPRN(DBG_CDI)(errfp, "0x%lx %s\n", ret,
6108 cdinfo_dbp->userreg.allowemail ? "Yes" : "No"
6109 );
6110
6111 DBGPRN(DBG_CDI)(errfp, "CddbUserInfo_PutAllowStats: ");
6112 ret = CddbUserInfo_PutAllowStats(uip,
6113 (CddbBoolean) cdinfo_dbp->userreg.allowstats
6114 );
6115 DBGPRN(DBG_CDI)(errfp, "0x%lx %s\n", ret,
6116 cdinfo_dbp->userreg.allowstats ? "Yes" : "No"
6117 );
6118
6119 /* Set the registration info */
6120 DBGPRN(DBG_CDI)(errfp, "CddbControl_SetUserInfo: ");
6121 ret = CddbControl_SetUserInfo(cp->ctrlp, uip);
6122 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
6123
6124 CddbReleaseObject(uip);
6125
6126 switch ((unsigned int) ret) {
6127 case Cddb_OK:
6128 /* Success: check if user is now registered */
6129 DBGPRN(DBG_CDI)(errfp, "CddbControl_IsRegistered: ");
6130 ret = CddbControl_IsRegistered(cp->ctrlp, 0, ®istered);
6131 DBGPRN(DBG_CDI)(errfp,
6132 "0x%lx %s\n", ret, registered ? "Yes" : "No");
6133
6134 if (!registered)
6135 *retcode = REGI_ERR;
6136
6137 DBGPRN(DBG_CDI)(errfp,
6138 "User \"%s\" is %s registered with CDDB.\n",
6139 cdinfo_dbp->userreg.handle,
6140 registered ? "now" : "NOT");
6141
6142 return ((bool_t) registered);
6143
6144 case (unsigned int) CDDBSVCHandleUsed:
6145 /* Incorrect password or handle taken */
6146 *retcode = NAME_ERR;
6147 return FALSE;
6148
6149 default:
6150 /* Other error */
6151 *retcode = REGI_ERR;
6152 return FALSE;
6153 }
6154 /*NOTREACHED*/
6155 }
6156
6157
6158 /*
6159 * cdinfo_passhintcddb
6160 * Request CDDB to e-mail the password hint.
6161 *
6162 * Args:
6163 * cp - Pointer to the cdinfo_cddb_t structure returned from
6164 * cdinfo_opencddb.
6165 * retcode - return status code
6166 *
6167 * Return:
6168 * TRUE - Success
6169 * FALSE - Failure
6170 */
6171 bool_t
cdinfo_passhintcddb(cdinfo_cddb_t * cp,cdinfo_ret_t * retcode)6172 cdinfo_passhintcddb(cdinfo_cddb_t *cp, cdinfo_ret_t *retcode)
6173 {
6174 CddbUserInfoPtr uip = NULL;
6175 CddbResult ret;
6176
6177 if (cdinfo_dbp->userreg.handle == NULL) {
6178 *retcode = REGI_ERR;
6179 return FALSE;
6180 }
6181
6182 DBGPRN(DBG_CDI)(errfp, "CddbControl_GetUserInfo: ");
6183 ret = CddbControl_GetUserInfo(cp->ctrlp, &uip);
6184 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
6185
6186 cdinfo_set_errstr(ret);
6187
6188 if (ret != Cddb_OK && uip == NULL) {
6189 *retcode = REGI_ERR;
6190 return FALSE;
6191 }
6192
6193 (void) cdinfo_put_str("CddbUserInfo_PutUserHandle",
6194 CddbUserInfo_PutUserHandle, uip,
6195 cdinfo_dbp->userreg.handle
6196 );
6197
6198 /* Set the registration info - request CDDB to mail password hint */
6199 DBGPRN(DBG_CDI)(errfp, "CddbControl_SetUserInfo: ");
6200 ret = CddbControl_SetUserInfo(cp->ctrlp, uip);
6201 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
6202
6203 cdinfo_set_errstr(ret);
6204
6205 CddbReleaseObject(uip);
6206
6207 switch ((unsigned int) ret) {
6208 case Cddb_OK:
6209 /* Success */
6210 return TRUE;
6211
6212 case (unsigned int) CDDBSVCUnknownHandle:
6213 /* Unknown handle */
6214 *retcode = NAME_ERR;
6215 return FALSE;
6216
6217 case (unsigned int) CDDBSVCNoHint:
6218 /* No hint registered */
6219 *retcode = HINT_ERR;
6220 return FALSE;
6221
6222 case (unsigned int) CDDBSVCNoEmail:
6223 /* No e-mail address registered */
6224 *retcode = MAIL_ERR;
6225 return FALSE;
6226
6227 default:
6228 /* Other error */
6229 *retcode = REGI_ERR;
6230 return FALSE;
6231 }
6232 /*NOTREACHED*/
6233 }
6234
6235
6236 /*
6237 * cdinfo_submitcddb
6238 * Submit current CD info to CDDB
6239 *
6240 * Args:
6241 * cp - Pointer to the cdinfo_cddb_t structure returned from
6242 * cdinfo_opencddb.
6243 * s - Pointer to the curstat_t structure
6244 * retcode - Return pointer of status code
6245 *
6246 * Return:
6247 * TRUE - Success
6248 * FALSE - Failure
6249 */
6250 bool_t
cdinfo_submitcddb(cdinfo_cddb_t * cp,curstat_t * s,cdinfo_ret_t * retcode)6251 cdinfo_submitcddb(cdinfo_cddb_t *cp, curstat_t *s, cdinfo_ret_t *retcode)
6252 {
6253 CddbDiscPtr discp = NULL;
6254 CddbTrackPtr trkp = NULL;
6255 CddbCreditPtr credp = NULL;
6256 CddbSegmentPtr segp = NULL;
6257 CddbResult ret;
6258 long ntrks,
6259 pval;
6260 int i;
6261 CddbStr tocstr;
6262 cdinfo_credit_t *p;
6263 cdinfo_segment_t *q;
6264
6265 if (!cdinfo_initcddb(cp, retcode))
6266 return FALSE;
6267
6268 if ((cdinfo_dbp->flags & CDINFO_NEEDREG) != 0)
6269 return TRUE;
6270
6271 tocstr = (CddbStr) cdinfo_tocstr(s);
6272
6273 DBGPRN(DBG_CDI)(errfp, "CddbControl_GetSubmitDisc: ");
6274 ret = CddbControl_GetSubmitDisc(
6275 cp->ctrlp,
6276 tocstr,
6277 cdinfo_dbp->disc.mediaid,
6278 cdinfo_dbp->disc.muiid,
6279 &discp
6280 );
6281 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
6282
6283 cdinfo_set_errstr(ret);
6284
6285 if (ret != Cddb_OK || discp == NULL) {
6286 if (discp != NULL)
6287 CddbReleaseObject(discp);
6288 *retcode = SUBMIT_ERR;
6289 return FALSE;
6290 }
6291
6292 /*
6293 * Fill in disc information
6294 */
6295 (void) cdinfo_put_str("CddbDisc_PutToc",
6296 CddbDisc_PutToc, discp, tocstr
6297 );
6298
6299 DBGPRN(DBG_CDI)(errfp, "CddbDisc_PutCompilation: ");
6300 ret = CddbDisc_PutCompilation(discp,
6301 (CddbBoolean) cdinfo_dbp->disc.compilation
6302 );
6303 DBGPRN(DBG_CDI)(errfp, "0x%lx %s\n", ret,
6304 cdinfo_dbp->disc.compilation ? "Yes" : "No"
6305 );
6306
6307 (void) cdinfo_put_str("CddbDisc_PutArtist",
6308 CddbDisc_PutArtist, discp, cdinfo_dbp->disc.artist
6309 );
6310 (void) cdinfo_put_str("CddbDisc_PutTitle",
6311 CddbDisc_PutTitle, discp, cdinfo_dbp->disc.title
6312 );
6313 (void) cdinfo_put_str("CddbDisc_PutTitleSort",
6314 CddbDisc_PutTitleSort, discp, cdinfo_dbp->disc.sorttitle
6315 );
6316 (void) cdinfo_put_str("CddbDisc_PutTitleThe",
6317 CddbDisc_PutTitleThe, discp, cdinfo_dbp->disc.title_the
6318 );
6319 (void) cdinfo_put_str("CddbDisc_PutYear",
6320 CddbDisc_PutYear, discp, cdinfo_dbp->disc.year
6321 );
6322 (void) cdinfo_put_str("CddbDisc_PutLabel",
6323 CddbDisc_PutLabel, discp, cdinfo_dbp->disc.label
6324 );
6325 (void) cdinfo_put_str("CddbDisc_PutGenreId",
6326 CddbDisc_PutGenreId, discp, cdinfo_dbp->disc.genre
6327 );
6328 (void) cdinfo_put_str("CddbDisc_PutSecondaryGenreId",
6329 CddbDisc_PutSecondaryGenreId, discp, cdinfo_dbp->disc.genre2
6330 );
6331 (void) cdinfo_put_str("CddbDisc_PutNumberInSet",
6332 CddbDisc_PutNumberInSet, discp, cdinfo_dbp->disc.dnum
6333 );
6334 (void) cdinfo_put_str("CddbDisc_PutTotalInSet",
6335 CddbDisc_PutTotalInSet, discp, cdinfo_dbp->disc.tnum
6336 );
6337 (void) cdinfo_put_str("CddbDisc_PutRegionId",
6338 CddbDisc_PutRegionId, discp, cdinfo_dbp->disc.region
6339 );
6340 (void) cdinfo_put_str("CddbDisc_PutLanguageId",
6341 CddbDisc_PutLanguageId, discp, cdinfo_dbp->disc.lang
6342 );
6343 (void) cdinfo_put_str("CddbDisc_PutNotes",
6344 CddbDisc_PutNotes, discp, cdinfo_dbp->disc.notes
6345 );
6346 (void) cdinfo_put_str("CddbDisc_PutRevision",
6347 CddbDisc_PutRevision, discp, cdinfo_dbp->disc.revision
6348 );
6349 (void) cdinfo_put_str("CddbDisc_PutRevisionTag",
6350 CddbDisc_PutRevisionTag, discp, cdinfo_dbp->disc.revtag
6351 );
6352
6353 (void) cdinfo_put_fullname("CddbDisc_PutArtistFullName",
6354 CddbDisc_PutArtistFullName, discp,
6355 cdinfo_dbp->disc.artistfname.dispname,
6356 cdinfo_dbp->disc.artistfname.lastname,
6357 cdinfo_dbp->disc.artistfname.firstname,
6358 cdinfo_dbp->disc.artistfname.the
6359 );
6360
6361 /* Disc credits */
6362 for (p = cdinfo_dbp->disc.credit_list; p != NULL; p = p->next) {
6363 DBGPRN(DBG_CDI)(errfp, "CddbDisc_AddCredit: ");
6364 ret = CddbDisc_AddCredit(discp,
6365 p->crinfo.role->id,
6366 p->crinfo.name,
6367 &credp);
6368 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
6369
6370 if (ret != Cddb_OK || credp == NULL)
6371 continue;
6372
6373 (void) cdinfo_put_fullname(" CddbCredit_PutFullName",
6374 CddbCredit_PutFullName, credp,
6375 p->crinfo.fullname.dispname,
6376 p->crinfo.fullname.lastname,
6377 p->crinfo.fullname.firstname,
6378 p->crinfo.fullname.the
6379 );
6380
6381 (void) cdinfo_put_str(" CddbCredit_PutNotes",
6382 CddbCredit_PutNotes, credp,
6383 p->notes
6384 );
6385
6386 CddbReleaseObject(credp);
6387 }
6388
6389 /* Segments */
6390 for (q = cdinfo_dbp->disc.segment_list; q != NULL; q = q->next) {
6391 DBGPRN(DBG_CDI)(errfp, "CddbDisc_AddSegment: ");
6392 ret = CddbDisc_AddSegment(discp, q->name, &segp);
6393 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
6394
6395 if (ret != Cddb_OK || segp == NULL)
6396 continue;
6397
6398 (void) cdinfo_put_str(" CddbSegment_PutNotes",
6399 CddbSegment_PutNotes, segp,
6400 q->notes
6401 );
6402 (void) cdinfo_put_str(" CddbSegment_PutStartTrack",
6403 CddbSegment_PutStartTrack, segp,
6404 q->start_track
6405 );
6406 (void) cdinfo_put_str(" CddbSegment_PutStartFrame",
6407 CddbSegment_PutStartFrame, segp,
6408 q->start_frame
6409 );
6410 (void) cdinfo_put_str(" CddbSegment_PutEndTrack",
6411 CddbSegment_PutEndTrack, segp,
6412 q->end_track
6413 );
6414 (void) cdinfo_put_str(" CddbSegment_PutEndFrame",
6415 CddbSegment_PutEndFrame, segp,
6416 q->end_frame
6417 );
6418
6419 /* Segment Credits */
6420 for (p = q->credit_list; p != NULL; p = p->next) {
6421 DBGPRN(DBG_CDI)(errfp, " CddbSegment_AddCredit: ");
6422 ret = CddbSegment_AddCredit(segp,
6423 p->crinfo.role->id,
6424 p->crinfo.name,
6425 &credp);
6426 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
6427
6428 if (ret != Cddb_OK || credp == NULL)
6429 continue;
6430
6431 (void) cdinfo_put_fullname(
6432 " CddbCredit_PutFullName",
6433 CddbCredit_PutFullName, credp,
6434 p->crinfo.fullname.dispname,
6435 p->crinfo.fullname.lastname,
6436 p->crinfo.fullname.firstname,
6437 p->crinfo.fullname.the
6438 );
6439
6440 (void) cdinfo_put_str(" CddbCredit_PutNotes",
6441 CddbCredit_PutNotes, credp,
6442 p->notes
6443 );
6444
6445 CddbReleaseObject(credp);
6446 }
6447
6448 CddbReleaseObject(segp);
6449 }
6450
6451 /*
6452 * Fill in track information
6453 */
6454 DBGPRN(DBG_CDI)(errfp, "CddbDisc_GetNumTracks: ");
6455 ret = CddbDisc_GetNumTracks(discp, &ntrks);
6456 DBGPRN(DBG_CDI)(errfp, "0x%lx %ld tracks\n", ret, ntrks);
6457
6458 for (i = 0; i < (int) ntrks; i++) {
6459 DBGPRN(DBG_CDI)(errfp, "CddbDisc_GetTrack[%02d]: ", i+1);
6460 ret = CddbDisc_GetTrack(discp, (long) (i+1), &trkp);
6461 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
6462
6463 if (ret != Cddb_OK || trkp == NULL)
6464 continue;
6465
6466 (void) cdinfo_put_str(" CddbTrack_PutArtist",
6467 CddbTrack_PutArtist, trkp,
6468 cdinfo_dbp->track[i].artist
6469 );
6470 (void) cdinfo_put_str(" CddbTrack_PutTitle",
6471 CddbTrack_PutTitle, trkp,
6472 cdinfo_dbp->track[i].title
6473 );
6474 (void) cdinfo_put_str(" CddbTrack_PutTitleSort",
6475 CddbTrack_PutTitleSort, trkp,
6476 cdinfo_dbp->track[i].sorttitle
6477 );
6478 (void) cdinfo_put_str(" CddbTrack_PutTitleThe",
6479 CddbTrack_PutTitleThe, trkp,
6480 cdinfo_dbp->track[i].title_the
6481 );
6482 (void) cdinfo_put_str(" CddbTrack_PutYear",
6483 CddbTrack_PutYear, trkp,
6484 cdinfo_dbp->track[i].year
6485 );
6486 (void) cdinfo_put_str(" CddbTrack_PutLabel",
6487 CddbTrack_PutLabel, trkp,
6488 cdinfo_dbp->track[i].label
6489 );
6490 (void) cdinfo_put_str(" CddbTrack_PutGenreId",
6491 CddbTrack_PutGenreId, trkp,
6492 cdinfo_dbp->track[i].genre
6493 );
6494 (void) cdinfo_put_str(" CddbTrack_PutSecondaryGenreId",
6495 CddbTrack_PutSecondaryGenreId, trkp,
6496 cdinfo_dbp->track[i].genre2
6497 );
6498 (void) cdinfo_put_str(" CddbTrack_PutBeatsPerMinute",
6499 CddbTrack_PutBeatsPerMinute, trkp,
6500 cdinfo_dbp->track[i].bpm
6501 );
6502 (void) cdinfo_put_str(" CddbTrack_PutNotes",
6503 CddbTrack_PutNotes, trkp,
6504 cdinfo_dbp->track[i].notes
6505 );
6506 (void) cdinfo_put_str(" CddbTrack_PutISRC",
6507 CddbTrack_PutISRC, trkp,
6508 cdinfo_dbp->track[i].isrc
6509 );
6510
6511 (void) cdinfo_put_fullname(" CddbTrack_PutArtistFullName",
6512 CddbTrack_PutArtistFullName, trkp,
6513 cdinfo_dbp->track[i].artistfname.dispname,
6514 cdinfo_dbp->track[i].artistfname.lastname,
6515 cdinfo_dbp->track[i].artistfname.firstname,
6516 cdinfo_dbp->track[i].artistfname.the
6517 );
6518
6519 for (p = cdinfo_dbp->track[i].credit_list; p != NULL;
6520 p = p->next) {
6521 DBGPRN(DBG_CDI)(errfp, " CddbTrack_AddCredit: ");
6522 ret = CddbTrack_AddCredit(trkp,
6523 p->crinfo.role->id,
6524 p->crinfo.name,
6525 &credp);
6526 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
6527
6528 if (ret != Cddb_OK || credp == NULL)
6529 continue;
6530
6531 (void) cdinfo_put_fullname(
6532 " CddbCredit_PutFullName",
6533 CddbCredit_PutFullName, credp,
6534 p->crinfo.fullname.dispname,
6535 p->crinfo.fullname.lastname,
6536 p->crinfo.fullname.firstname,
6537 p->crinfo.fullname.the
6538 );
6539
6540 (void) cdinfo_put_str(" CddbCredit_PutNotes",
6541 CddbCredit_PutNotes, credp,
6542 p->notes
6543 );
6544
6545 CddbReleaseObject(credp);
6546 }
6547
6548 CddbReleaseObject(trkp);
6549 }
6550
6551 /* Submit the disc info */
6552 DBGPRN(DBG_CDI)(errfp, "CddbControl_SubmitDisc: ");
6553 ret = CddbControl_SubmitDisc(cp->ctrlp, discp, 0, &pval);
6554 DBGPRN(DBG_CDI)(errfp, "0x%lx pval=%lx\n", ret, pval);
6555
6556 cdinfo_set_errstr(ret);
6557
6558 CddbReleaseObject(discp);
6559
6560 *retcode = (ret == Cddb_OK) ? 0 : SUBMIT_ERR;
6561 util_delayms(1000);
6562 return (ret == Cddb_OK);
6563 }
6564
6565
6566 /*
6567 * cdinfo_submiturlcddb
6568 * Submit to CDDB a URL pertaining to the current CD
6569 *
6570 * Args:
6571 * cp - Pointer to the cdinfo_cddb_t structure returned from
6572 * cdinfo_opencddb.
6573 * up - Pointer to the cdinfo_url_t structure
6574 * retcode - Return pointer of status code
6575 *
6576 * Return:
6577 * TRUE - Success
6578 * FALSE - Failure
6579 */
6580 bool_t
cdinfo_submiturlcddb(cdinfo_cddb_t * cp,cdinfo_url_t * up,cdinfo_ret_t * retcode)6581 cdinfo_submiturlcddb(cdinfo_cddb_t *cp, cdinfo_url_t *up,
6582 cdinfo_ret_t *retcode)
6583 {
6584 CddbDiscPtr discp = NULL;
6585 CddbDiscsPtr discsp = NULL;
6586 CddbURLManagerPtr urlmgrp = NULL;
6587 CddbURLPtr urlp = NULL;
6588 CddbResult ret;
6589
6590 if (!cdinfo_initcddb(cp, retcode))
6591 return FALSE;
6592
6593 if ((cdinfo_dbp->flags & CDINFO_NEEDREG) != 0)
6594 return TRUE;
6595
6596 DBGPRN(DBG_CDI)(errfp, "CddbControl_GetDiscInfo: ");
6597 ret = CddbControl_GetDiscInfo(
6598 cp->ctrlp,
6599 cdinfo_dbp->disc.mediaid,
6600 cdinfo_dbp->disc.muiid,
6601 NULL, NULL, 0,
6602 &discp, &discsp
6603 );
6604 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
6605
6606 cdinfo_set_errstr(ret);
6607
6608 if (ret != Cddb_OK || discp == NULL) {
6609 if (discp != NULL)
6610 CddbReleaseObject(discp);
6611 if (discsp != NULL)
6612 CddbReleaseObject(discsp);
6613 *retcode = SUBMIT_ERR;
6614 return FALSE;
6615 }
6616
6617 if (discsp != NULL)
6618 CddbReleaseObject(discsp);
6619
6620 DBGPRN(DBG_CDI)(errfp, "CddbControl_GetURLManager: ");
6621 ret = CddbControl_GetURLManager(cp->ctrlp, &urlmgrp);
6622 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
6623
6624 cdinfo_set_errstr(ret);
6625
6626 if (ret != Cddb_OK || urlmgrp == NULL) {
6627 CddbReleaseObject(discp);
6628 *retcode = SUBMIT_ERR;
6629 return FALSE;
6630 }
6631
6632 urlp = (CddbURLPtr) CddbCreateObject(CddbURLType);
6633
6634 (void) cdinfo_put_str("CddbURL_PutType",
6635 CddbURL_PutType, urlp, up->type
6636 );
6637 (void) cdinfo_put_str("CddbURL_PutHref",
6638 CddbURL_PutHref, urlp, up->href
6639 );
6640 (void) cdinfo_put_str("CddbURL_PutDisplayLink",
6641 CddbURL_PutDisplayLink, urlp, up->displink
6642 );
6643 (void) cdinfo_put_str("CddbURL_PutDisplayText",
6644 CddbURL_PutDisplayText, urlp, up->disptext
6645 );
6646 (void) cdinfo_put_str("CddbURL_PutCategory",
6647 CddbURL_PutCategory, urlp, up->categ
6648 );
6649 (void) cdinfo_put_str("CddbURL_PutDescription",
6650 CddbURL_PutDescription, urlp, up->desc
6651 );
6652 (void) cdinfo_put_str("CddbURL_PutSize",
6653 CddbURL_PutSize, urlp, up->size
6654 );
6655 (void) cdinfo_put_str("CddbURL_PutWeight",
6656 CddbURL_PutWeight, urlp, up->weight
6657 );
6658
6659 DBGPRN(DBG_CDI)(errfp, "CddbURLManager_SubmitURL: ");
6660 ret = CddbURLManager_SubmitURL(urlmgrp, discp, urlp);
6661 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
6662
6663 cdinfo_set_errstr(ret);
6664
6665 CddbReleaseObject(urlp);
6666 CddbReleaseObject(urlmgrp);
6667 CddbReleaseObject(discp);
6668
6669 util_delayms(1000);
6670 return (ret == Cddb_OK);
6671 }
6672
6673
6674 /*
6675 * cdinfo_flushcddb
6676 * Flush local CDDB cache.
6677 *
6678 * Args:
6679 * cp - Pointer to the cdinfo_cddb_t structure returned from
6680 * cdinfo_opencddb.
6681 *
6682 * Return:
6683 * TRUE - Success
6684 * FALSE - Failure
6685 */
6686 /*ARGSUSED*/
6687 bool_t
cdinfo_flushcddb(cdinfo_cddb_t * cp)6688 cdinfo_flushcddb(cdinfo_cddb_t *cp)
6689 {
6690 CddbResult ret;
6691
6692 DBGPRN(DBG_CDI)(errfp, "CddbControl_FlushLocalCache: ");
6693 ret = CddbControl_FlushLocalCache(cp->ctrlp, FLUSH_DEFAULT);
6694 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
6695
6696 cdinfo_set_errstr(ret);
6697
6698 util_delayms(1000);
6699 return (ret == Cddb_OK ? TRUE : FALSE);
6700 }
6701
6702
6703 /*
6704 * cdinfo_infobrowsercddb
6705 * Invoke CDDB info browser for the current disc
6706 *
6707 * Args:
6708 * cp - Pointer to the cdinfo_cddb_t structure returned from
6709 * cdinfo_opencddb.
6710 *
6711 * Return:
6712 * TRUE - Success
6713 * FALSE - Failure
6714 */
6715 bool_t
cdinfo_infobrowsercddb(cdinfo_cddb_t * cp)6716 cdinfo_infobrowsercddb(cdinfo_cddb_t *cp)
6717 {
6718 CddbDiscPtr discp = NULL;
6719 CddbDiscsPtr discsp = NULL;
6720 CddbResult ret;
6721 int retcode;
6722
6723 if (!cdinfo_initcddb(cp, &retcode))
6724 return FALSE;
6725
6726 if ((cdinfo_dbp->flags & CDINFO_NEEDREG) != 0)
6727 return TRUE;
6728
6729 DBGPRN(DBG_CDI)(errfp, "CddbControl_GetDiscInfo: ");
6730 ret = CddbControl_GetDiscInfo(
6731 cp->ctrlp,
6732 cdinfo_dbp->disc.mediaid,
6733 cdinfo_dbp->disc.muiid,
6734 NULL, NULL, 0,
6735 &discp, &discsp
6736 );
6737 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
6738
6739 cdinfo_set_errstr(ret);
6740
6741 if (ret != Cddb_OK || discp == NULL) {
6742 if (discp != NULL)
6743 CddbReleaseObject(discp);
6744 if (discsp != NULL)
6745 CddbReleaseObject(discsp);
6746 return FALSE;
6747 }
6748
6749 if (discsp != NULL)
6750 CddbReleaseObject(discsp);
6751
6752 DBGPRN(DBG_CDI)(errfp, "CddbControl_InvokeInfoBrowser: ");
6753 ret = CddbControl_InvokeInfoBrowser(cp->ctrlp, discp, 0, UI_NONE);
6754 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
6755
6756 cdinfo_set_errstr(ret);
6757
6758 CddbReleaseObject(discp);
6759
6760 return (ret == Cddb_OK);
6761 }
6762
6763
6764 /*
6765 * cdinfo_urlcddb
6766 * Go to a CDDB-supplied URL
6767 *
6768 * Args:
6769 * cp - Pointer to the cdinfo_cddb_t structure returned from
6770 * cdinfo_opencddb.
6771 * wtype - WTYPE_GEN or WTYPE_ALBUM
6772 * idx - index number into the URL list
6773 *
6774 * Return:
6775 * TRUE - Success
6776 * FALSE - Failure
6777 */
6778 bool_t
cdinfo_urlcddb(cdinfo_cddb_t * cp,int wtype,int idx)6779 cdinfo_urlcddb(cdinfo_cddb_t *cp, int wtype, int idx)
6780 {
6781 CddbDiscPtr discp = NULL;
6782 CddbDiscsPtr discsp = NULL;
6783 CddbURLManagerPtr urlmgrp = NULL;
6784 CddbURLListPtr urllistp = NULL;
6785 CddbURLPtr urlp = NULL;
6786 CddbResult ret;
6787 int retcode;
6788
6789 if (!cdinfo_initcddb(cp, &retcode))
6790 return FALSE;
6791
6792 if ((cdinfo_dbp->flags & CDINFO_NEEDREG) != 0)
6793 return TRUE;
6794
6795 if (wtype == WTYPE_ALBUM) {
6796 DBGPRN(DBG_CDI)(errfp, "CddbControl_GetDiscInfo: ");
6797 ret = CddbControl_GetDiscInfo(
6798 cp->ctrlp,
6799 cdinfo_dbp->disc.mediaid,
6800 cdinfo_dbp->disc.muiid,
6801 NULL, NULL, 0,
6802 &discp, &discsp
6803 );
6804 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
6805
6806 cdinfo_set_errstr(ret);
6807
6808 if (ret != Cddb_OK || discp == NULL) {
6809 if (discp != NULL)
6810 CddbReleaseObject(discp);
6811 if (discsp != NULL)
6812 CddbReleaseObject(discsp);
6813 return FALSE;
6814 }
6815 }
6816
6817 if (discsp != NULL)
6818 CddbReleaseObject(discsp);
6819
6820 DBGPRN(DBG_CDI)(errfp, "CddbControl_GetURLManager: ");
6821 ret = CddbControl_GetURLManager(cp->ctrlp, &urlmgrp);
6822 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
6823
6824 cdinfo_set_errstr(ret);
6825
6826 if (ret != Cddb_OK || urlmgrp == NULL) {
6827 if (discp != NULL)
6828 CddbReleaseObject(discp);
6829 return FALSE;
6830 }
6831
6832 /* Get the appropriate URL list */
6833 DBGPRN(DBG_CDI)(errfp, "CddbURLManager_GetMenuURLs: ");
6834 ret = CddbURLManager_GetMenuURLs(urlmgrp, discp, &urllistp);
6835 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
6836
6837 cdinfo_set_errstr(ret);
6838
6839 if (ret != Cddb_OK || urllistp == NULL) {
6840 CddbReleaseObject(urlmgrp);
6841 if (discp != NULL)
6842 CddbReleaseObject(discp);
6843 return FALSE;
6844 }
6845
6846 /* Get the appropriate URL */
6847 DBGPRN(DBG_CDI)(errfp, "CddbURLList_GetURL: ");
6848 ret = CddbURLList_GetURL(urllistp, (long) idx, &urlp);
6849 DBGPRN(DBG_CDI)(errfp, "0x%lx idx=%d\n", ret, idx);
6850
6851 cdinfo_set_errstr(ret);
6852
6853 if (ret != Cddb_OK || urlp == NULL) {
6854 CddbReleaseObject(urllistp);
6855 CddbReleaseObject(urlmgrp);
6856 if (discp != NULL)
6857 CddbReleaseObject(discp);
6858 return FALSE;
6859 }
6860
6861 /* Go to the URL */
6862 DBGPRN(DBG_CDI)(errfp, "CddbURLManager_GotoURL: ");
6863 ret = CddbURLManager_GotoURL(urlmgrp, urlp, 0);
6864 DBGPRN(DBG_CDI)(errfp, "0x%lx\n", ret);
6865
6866 cdinfo_set_errstr(ret);
6867
6868 CddbReleaseObject(urlp);
6869 CddbReleaseObject(urllistp);
6870 CddbReleaseObject(urlmgrp);
6871 if (discp != NULL)
6872 CddbReleaseObject(discp);
6873
6874 return (ret == Cddb_OK);
6875 }
6876
6877
6878 /*
6879 * cdinfo_free_matchlist
6880 * Deallocate the match list.
6881 *
6882 * Args:
6883 * None.
6884 *
6885 * Return:
6886 * Nothing.
6887 */
6888 void
cdinfo_free_matchlist(void)6889 cdinfo_free_matchlist(void)
6890 {
6891 cdinfo_match_t *p,
6892 *q;
6893
6894 for (p = q = cdinfo_dbp->matchlist; p != NULL; p = q) {
6895 q = p->next;
6896 if (p->artist != NULL)
6897 MEM_FREE(p->artist);
6898 if (p->title != NULL)
6899 MEM_FREE(p->title);
6900 if (p->genre != NULL)
6901 MEM_FREE(p->genre);
6902 MEM_FREE(p);
6903 }
6904
6905 cdinfo_dbp->matchlist = NULL;
6906 cdinfo_dbp->match_aux = NULL;
6907 cdinfo_dbp->match_tag = -1;
6908 cdinfo_dbp->sav_cddbp = NULL;
6909 cdinfo_dbp->sav_rpp = cdinfo_dbp->sav_spp = NULL;
6910 }
6911
6912
6913 /*
6914 * cdinfo_skip_whitespace
6915 * Given a string, return a pointer to the first non-whitespace
6916 * character in it.
6917 *
6918 * Args:
6919 * str - String pointer
6920 *
6921 * Return:
6922 * Pointer to first non-whitespace character in the string
6923 */
6924 char *
cdinfo_skip_whitespace(char * str)6925 cdinfo_skip_whitespace(char *str)
6926 {
6927 for (; *str != '\0' && (*str == ' ' || *str == '\t'); str++)
6928 ;
6929
6930 return (str);
6931 }
6932
6933
6934 /*
6935 * cdinfo_skip_nowhitespace
6936 * Given a string, return a pointer to the first whitespace
6937 * character in it.
6938 *
6939 * Args:
6940 * str - String pointer
6941 *
6942 * Return:
6943 * Pointer to first whitespace character in the string
6944 */
6945 char *
cdinfo_skip_nowhitespace(char * str)6946 cdinfo_skip_nowhitespace(char *str)
6947 {
6948 for (; *str != '\0' && (*str != ' ' && *str != '\t'); str++)
6949 ;
6950
6951 return (str);
6952 }
6953
6954
6955 /*
6956 * cdinfo_fgetline
6957 * Read a line from the file stream fp, and allocate a dynamic
6958 * buffer to hold it. If a line is terminated with a '\' character,
6959 * that is considered a "continuation" marker, and another line
6960 * is read and contactenated. The caller should use MEM_FREE to
6961 * deallocate the buffer that is returned when it's done using it.
6962 *
6963 * Args:
6964 * fp - The stdio file stream
6965 *
6966 * Return:
6967 * Allocated buffer containing the line read from stream.
6968 */
6969 char *
cdinfo_fgetline(FILE * fp)6970 cdinfo_fgetline(FILE *fp)
6971 {
6972 size_t n;
6973 char *buf;
6974 static char rbuf[2048];
6975
6976 buf = NULL;
6977 for (;;) {
6978 if (fgets(rbuf, sizeof(rbuf), fp) == NULL)
6979 break;
6980
6981 if ((n = strlen(rbuf)) == 0)
6982 break;
6983
6984 if (buf == NULL) {
6985 buf = (char *) MEM_ALLOC("fgetline_buf", n + 1);
6986 if (buf != NULL)
6987 buf[0] = '\0';
6988 }
6989 else {
6990 buf = (char *) MEM_REALLOC("fgetline_buf",
6991 buf, strlen(buf) + n + 1
6992 );
6993 }
6994
6995 if (buf == NULL) {
6996 CDINFO_FATAL(app_data.str_nomemory);
6997 return NULL;
6998 }
6999
7000 if (rbuf[n-1] == '\n') {
7001 if (n > 1 && rbuf[n-2] == '\\') {
7002 rbuf[n-2] = '\0';
7003 (void) strcat(buf, rbuf);
7004 }
7005 else {
7006 rbuf[n-1] = '\0';
7007 (void) strcat(buf, rbuf);
7008 break;
7009 }
7010 }
7011 else
7012 (void) strcat(buf, rbuf);
7013 }
7014
7015 return (buf);
7016 }
7017
7018
7019 /*
7020 * cdinfo_wwwchk_cleanup
7021 * Clean up the check list created in cdinfo_wwwmenu_chk.
7022 *
7023 * Args:
7024 * None.
7025 *
7026 * Return:
7027 * Nothing.
7028 */
7029 void
cdinfo_wwwchk_cleanup(void)7030 cdinfo_wwwchk_cleanup(void)
7031 {
7032 w_entchk_t *c,
7033 *c1;
7034
7035 /* Clean up check list */
7036 for (c = c1 = cdinfo_wentchk_head; c != NULL; c = c1) {
7037 c1 = c->next;
7038 MEM_FREE(c);
7039 }
7040 cdinfo_wentchk_head = NULL;
7041 }
7042
7043
7044 /*
7045 * cdinfo_wwwmenu_chk
7046 * Given a wwwwarp menu, traverse all its submenus and make sure
7047 * there are no circular menu links.
7048 *
7049 * Args:
7050 * menu - The first entry of a menu
7051 * topmenu - boolean indicating whether this is called from the
7052 * top level menu.
7053 */
7054 bool_t
cdinfo_wwwmenu_chk(w_ent_t * menu,bool_t topmenu)7055 cdinfo_wwwmenu_chk(w_ent_t *menu, bool_t topmenu)
7056 {
7057 bool_t ret;
7058 w_ent_t *p;
7059 w_entchk_t *c,
7060 *c1;
7061 static w_entchk_t *c2;
7062
7063 ret = TRUE;
7064
7065 for (p = menu; p != NULL; p = p->nextent) {
7066 if (p->type != WTYPE_SUBMENU)
7067 continue;
7068
7069 /* Check to see if this submenu points to an ancester menu */
7070 for (c1 = cdinfo_wentchk_head; c1 != NULL; c1 = c1->next) {
7071 if (strcmp(c1->ent->name, p->submenu->name) == 0) {
7072 p->type = WTYPE_NULL;
7073 p->submenu = NULL;
7074 ret = FALSE;
7075 break;
7076 }
7077 }
7078 if (!ret)
7079 break;
7080
7081 /* Add this submenu to link */
7082 c = (w_entchk_t *)(void *) MEM_ALLOC(
7083 "w_entchk_t", sizeof(w_entchk_t)
7084 );
7085 if (c == NULL) {
7086 CDINFO_FATAL(app_data.str_nomemory);
7087 ret = FALSE;
7088 break;
7089 }
7090 c->ent = p->submenu;
7091 c->next = NULL;
7092
7093 if (cdinfo_wentchk_head == NULL)
7094 cdinfo_wentchk_head = c2 = c;
7095 else {
7096 c2->next = c;
7097 c2 = c;
7098 }
7099
7100 /* Recurse to the next level */
7101 if (!cdinfo_wwwmenu_chk(p->submenu, FALSE)) {
7102 ret = FALSE;
7103 break;
7104 }
7105
7106 if (topmenu)
7107 cdinfo_wwwchk_cleanup();
7108 }
7109
7110 if (topmenu)
7111 cdinfo_wwwchk_cleanup();
7112 return (ret);
7113 }
7114
7115
7116 /*
7117 * cdinfo_scan_url_attrib
7118 * Scan a URL template string and record its attributes.
7119 *
7120 * Args:
7121 * url - The URL template string
7122 *
7123 * Return:
7124 * Nothing.
7125 */
7126 void
cdinfo_scan_url_attrib(char * url,url_attrib_t * up)7127 cdinfo_scan_url_attrib(char *url, url_attrib_t *up)
7128 {
7129 char *cp;
7130
7131 /* Scan URL string to get a count of the number of
7132 * substitutions needed.
7133 */
7134 up->xcnt = up->vcnt = 0;
7135 up->ncnt = up->hcnt = 0;
7136 up->lcnt = up->ccnt = 0;
7137 up->icnt = up->acnt = 0;
7138 up->dcnt = up->tcnt = 0;
7139 up->rcnt = up->pcnt = 0;
7140 for (cp = url; *cp != '\0'; cp++) {
7141 if (*cp == '%') {
7142 switch ((int) *(++cp)) {
7143 case 'X':
7144 up->xcnt++;
7145 break;
7146 case 'V':
7147 up->vcnt++;
7148 break;
7149 case 'N':
7150 up->ncnt++;
7151 break;
7152 case 'H':
7153 up->hcnt++;
7154 break;
7155 case 'L':
7156 up->lcnt++;
7157 break;
7158 case 'C':
7159 up->ccnt++;
7160 break;
7161 case 'I':
7162 up->icnt++;
7163 break;
7164 case 'A':
7165 case 'a':
7166 up->acnt++;
7167 break;
7168 case 'D':
7169 case 'd':
7170 up->dcnt++;
7171 break;
7172 case 'R':
7173 case 'r':
7174 up->rcnt++;
7175 break;
7176 case 'T':
7177 case 't':
7178 up->tcnt++;
7179 break;
7180 case 'B':
7181 case 'b':
7182 up->acnt++;
7183 up->dcnt++;
7184 break;
7185 case '#':
7186 up->pcnt++;
7187 break;
7188 default:
7189 break;
7190 }
7191 }
7192 }
7193 }
7194
7195
7196 /*
7197 * cdinfo_add_pathent
7198 * Add a cdinfo path list component.
7199 *
7200 * Args:
7201 * path - The path component string
7202 *
7203 * Return:
7204 * TRUE - success
7205 * FALSE - failure
7206 */
7207 bool_t
cdinfo_add_pathent(char * path)7208 cdinfo_add_pathent(char *path)
7209 {
7210 int n;
7211 char *cp,
7212 *cp2;
7213 cdinfo_path_t *pp;
7214 STATIC cdinfo_path_t *pp2 = NULL;
7215
7216 if (*path == '\0' || *path == '\n')
7217 return TRUE;
7218 if (strncmp(path, "cddbp://", 8) == 0 ||
7219 strncmp(path, "http://", 7) == 0) {
7220 (void) fprintf(errfp,
7221 "NOTICE: Skipped unsupported item in cdinfoPath: %s\n",
7222 path);
7223 return TRUE;
7224 }
7225
7226 pp = (cdinfo_path_t *)(void *) MEM_ALLOC(
7227 "cdinfo_path_t",
7228 sizeof(cdinfo_path_t)
7229 );
7230 if (pp == NULL) {
7231 CDINFO_FATAL(app_data.str_nomemory);
7232 return FALSE;
7233 }
7234 (void) memset(pp, 0, sizeof(cdinfo_path_t));
7235
7236 if (cdinfo_dbp->pathlist == NULL) {
7237 cdinfo_dbp->pathlist = pp2 = pp;
7238 }
7239 else {
7240 pp2->next = pp;
7241 pp2 = pp;
7242 }
7243
7244 /* Determine path type */
7245 if (strcmp(path, "CDDB") == 0) {
7246 /* CDDB service */
7247 pp->type = CDINFO_RMT;
7248 }
7249 else if (strcmp(path, "CDTEXT") == 0) {
7250 /* CD-TEXT from the disc */
7251 pp->type = CDINFO_CDTEXT;
7252 }
7253 else if (strncmp(path, "file://", 7) == 0) {
7254 /* Syntax: file://dirpath */
7255 pp->type = CDINFO_LOC;
7256 path += 7;
7257 }
7258 else {
7259 /* Syntax: dirpath */
7260 pp->type = CDINFO_LOC;
7261 }
7262
7263 /* Parse the rest of the line */
7264 switch (pp->type) {
7265 case CDINFO_RMT:
7266 case CDINFO_CDTEXT:
7267 /* Do nothing here */
7268 break;
7269
7270 case CDINFO_LOC:
7271 n = strlen(path);
7272 if (path[0] == '/') {
7273 /* Absolute local path name */
7274 if (!util_newstr(&pp->path, path)) {
7275 CDINFO_FATAL(app_data.str_nomemory);
7276 return FALSE;
7277 }
7278 }
7279 else if (path[0] == '~') {
7280 /* Perform tilde expansion a la [ck]sh */
7281 if (path[1] == '/') {
7282 cp2 = util_homedir(util_get_ouid());
7283
7284 pp->path = (char *) MEM_ALLOC(
7285 "pp->path",
7286 n + strlen(cp2)
7287 );
7288 if (pp->path == NULL) {
7289 CDINFO_FATAL(app_data.str_nomemory);
7290 return FALSE;
7291 }
7292
7293 (void) sprintf(pp->path, "%s%s",
7294 cp2, &path[1]);
7295 }
7296 else if (path[1] == '\0') {
7297 cp2 = util_homedir(util_get_ouid());
7298
7299 if (!util_newstr(&pp->path, cp2)) {
7300 CDINFO_FATAL(app_data.str_nomemory);
7301 return FALSE;
7302 }
7303 }
7304 else {
7305 cp = strchr(path, '/');
7306 if (cp == NULL) {
7307 cp2 = util_uhomedir(&path[1]);
7308 if (!util_newstr(&pp->path, cp2)) {
7309 CDINFO_FATAL(
7310 app_data.str_nomemory
7311 );
7312 return FALSE;
7313 }
7314 }
7315 else {
7316 *cp = '\0';
7317 cp2 = util_uhomedir(&path[1]);
7318 pp->path = (char *) MEM_ALLOC(
7319 "pp->path",
7320 n + strlen(cp2)
7321 );
7322 if (pp->path == NULL) {
7323 CDINFO_FATAL(
7324 app_data.str_nomemory
7325 );
7326 return FALSE;
7327 }
7328
7329 (void) sprintf(pp->path, CONCAT_PATH,
7330 cp2, cp+1);
7331 }
7332 }
7333 }
7334 else {
7335 /* Relative local path name */
7336 pp->path = (char *) MEM_ALLOC(
7337 "pp->path",
7338 n + strlen(app_data.libdir) +
7339 strlen(REL_DBDIR_PATH)
7340 );
7341 if (pp->path == NULL) {
7342 CDINFO_FATAL(app_data.str_nomemory);
7343 return FALSE;
7344 }
7345
7346 (void) sprintf(pp->path, REL_DBDIR_PATH,
7347 app_data.libdir, path);
7348
7349 }
7350
7351 /* Set category name for CDDB1 to CDDB2 genre mapping */
7352 cp = util_basename(pp->path);
7353 if (cp != NULL && !util_newstr(&pp->categ, cp)) {
7354 MEM_FREE(cp);
7355 CDINFO_FATAL(app_data.str_nomemory);
7356 return FALSE;
7357 }
7358 MEM_FREE(cp);
7359
7360 /* Make sure that the whole path name + discid can
7361 * fit in a FILE_PATH_SZ buffer. Also, make sure the
7362 * category name is less than FILE_BASE_SZ.
7363 */
7364 if ((int) strlen(pp->path) >= (FILE_PATH_SZ - 12)) {
7365 CDINFO_FATAL(app_data.str_longpatherr);
7366 return FALSE;
7367 }
7368
7369 if ((cp = util_basename(pp->path)) == NULL) {
7370 CDINFO_FATAL("cdinfoPath component error");
7371 return FALSE;
7372 }
7373
7374 if ((int) strlen(cp) >= FILE_BASE_SZ) {
7375 MEM_FREE(cp);
7376 CDINFO_FATAL(app_data.str_longpatherr);
7377 return FALSE;
7378 }
7379 MEM_FREE(cp);
7380
7381 break;
7382 }
7383
7384 return TRUE;
7385 }
7386
7387
7388 /*
7389 * cdinfo_load_locdb
7390 * Attempt to load CD information from the specified local CD info file.
7391 *
7392 * Args:
7393 * path - File path
7394 * categ - CDDB1 category string
7395 * s - Pointer to the curstat_t structure
7396 * retcode - Return status code
7397 *
7398 * Return:
7399 * TRUE - success
7400 * FALSE - failure
7401 */
7402 /*ARGSUSED*/
7403 bool_t
cdinfo_load_locdb(char * path,char * categ,curstat_t * s,int * retcode)7404 cdinfo_load_locdb(char *path, char *categ, curstat_t *s, int *retcode)
7405 {
7406 int i,
7407 pos,
7408 bufsz = STR_BUF_SZ * 3;
7409 char *buf,
7410 *tmpbuf;
7411 FILE *fp;
7412
7413 errno = 0;
7414 *retcode = 0;
7415
7416 if ((fp = fopen(path, "r")) == NULL) {
7417 /* File not found */
7418 *retcode = 0;
7419 DBGPRN(DBG_CDI)(errfp, "\n");
7420 return TRUE;
7421 }
7422
7423 if ((buf = (char *) MEM_ALLOC("read_buf", bufsz)) == NULL) {
7424 *retcode = MEM_ERR;
7425 DBGPRN(DBG_CDI)(errfp, "\n");
7426 (void) fclose(fp);
7427 CDINFO_FATAL(app_data.str_nomemory);
7428 return FALSE;
7429 }
7430
7431 if ((tmpbuf = (char *) MEM_ALLOC("read_tmpbuf", bufsz)) == NULL) {
7432 *retcode = MEM_ERR;
7433 DBGPRN(DBG_CDI)(errfp, "\n");
7434 MEM_FREE(buf);
7435 (void) fclose(fp);
7436 CDINFO_FATAL(app_data.str_nomemory);
7437 return FALSE;
7438 }
7439
7440 /* Read first line of database entry */
7441 if (fgets(buf, bufsz, fp) == NULL) {
7442 /* Can't read file */
7443 DBGPRN(DBG_CDI)(errfp, "\n");
7444 MEM_FREE(buf);
7445 MEM_FREE(tmpbuf);
7446 (void) fclose(fp);
7447 return TRUE;
7448 }
7449
7450 /* Database file signature check */
7451 if (strncmp(buf, "# xmcd", 6) != 0) {
7452 /* Not a supported database file */
7453 DBGPRN(DBG_CDI)(errfp, "\n");
7454 MEM_FREE(buf);
7455 MEM_FREE(tmpbuf);
7456 (void) fclose(fp);
7457 return TRUE;
7458 }
7459
7460 /* Read the rest of the database entry */
7461 while (fgets(buf, bufsz, fp) != NULL) {
7462 /* Comment line */
7463 if (buf[0] == '#') {
7464 /* Concatenated cdinfo file */
7465 if (strncmp(buf, "# xmcd", 6) == 0)
7466 break;
7467
7468 continue;
7469 }
7470
7471 buf[strlen(buf)-1] = '\n';
7472
7473 /* Disc IDs */
7474 if (sscanf(buf, "DISCID=%[^\n]\n", tmpbuf) > 0) {
7475 /* Do nothing for this line */
7476 continue;
7477 }
7478
7479 /* Disk title */
7480 if (sscanf(buf, "DTITLE=%[^\n]\n", tmpbuf) > 0) {
7481 cdinfo_disc_t *dp;
7482 char *cp;
7483
7484 cdinfo_line_filter(tmpbuf);
7485
7486 dp = &cdinfo_dbp->disc;
7487
7488 /* This assumes that artist and title are separated
7489 * " / " (may not be true in all cases; shrug)
7490 */
7491 if ((cp = strchr(tmpbuf, '/')) != NULL &&
7492 cp > (tmpbuf + 3) &&
7493 *(cp-1) == ' ' && *(cp+1) == ' ') {
7494 char *cp2;
7495
7496 cp2 = cp - 1;
7497 *cp2 = '\0';
7498 if (!cdinfo_concatstr(
7499 &dp->artistfname.dispname,
7500 tmpbuf)) {
7501 CDINFO_FATAL(app_data.str_nomemory);
7502 break;
7503 }
7504 if (!cdinfo_concatstr(&dp->artist,
7505 tmpbuf)) {
7506 CDINFO_FATAL(app_data.str_nomemory);
7507 break;
7508 }
7509
7510 cp2 = cp + 2;
7511 if (!cdinfo_concatstr(&dp->title, cp2)) {
7512 CDINFO_FATAL(app_data.str_nomemory);
7513 break;
7514 }
7515 }
7516 else if (!cdinfo_concatstr(&dp->title, tmpbuf)) {
7517 CDINFO_FATAL(app_data.str_nomemory);
7518 break;
7519 }
7520 continue;
7521 }
7522
7523 /* Track titles */
7524 if (sscanf(buf, "TTITLE%u=%[^\n]\n", &pos, tmpbuf) >= 2) {
7525 cdinfo_track_t *tp;
7526
7527 if (pos >= (int) (cdinfo_dbp->discid & 0xff))
7528 continue;
7529
7530 cdinfo_line_filter(tmpbuf);
7531
7532 tp = &cdinfo_dbp->track[pos];
7533
7534 if (!cdinfo_concatstr(&tp->title, tmpbuf)) {
7535 CDINFO_FATAL(app_data.str_nomemory);
7536 break;
7537 }
7538 continue;
7539 }
7540
7541 /* Disk notes */
7542 if (sscanf(buf, "EXTD=%[^\n]\n", tmpbuf) > 0) {
7543 cdinfo_disc_t *dp;
7544
7545 dp = &cdinfo_dbp->disc;
7546
7547 if (!cdinfo_concatstr(&dp->notes, tmpbuf)) {
7548 CDINFO_FATAL(app_data.str_nomemory);
7549 break;
7550 }
7551 continue;
7552 }
7553
7554 /* Track extended info */
7555 if (sscanf(buf, "EXTT%u=%[^\n]\n", &pos, tmpbuf) >= 2) {
7556 cdinfo_track_t *tp;
7557
7558 if (pos >= (int) (cdinfo_dbp->discid & 0xff))
7559 continue;
7560
7561 tp = &cdinfo_dbp->track[pos];
7562
7563 if (!cdinfo_concatstr(&tp->notes, tmpbuf)) {
7564 CDINFO_FATAL(app_data.str_nomemory);
7565 break;
7566 }
7567 continue;
7568 }
7569
7570 #ifdef USE_XMCD2_PLAYORDER
7571 /* Play order - this is deprecated */
7572 if (sscanf(buf, "PLAYORDER=%[^\n]\n", tmpbuf) > 0) {
7573 if (s->program || s->shuffle)
7574 /* Play program or shuffle already in
7575 * progress, do not override it.
7576 */
7577 continue;
7578
7579 if (!cdinfo_concatstr(&cdinfo_dbp->playorder, tmpbuf)){
7580 CDINFO_FATAL(app_data.str_nomemory);
7581 break;
7582 }
7583 continue;
7584 }
7585 #endif
7586 }
7587
7588 MEM_FREE(buf);
7589 MEM_FREE(tmpbuf);
7590
7591 (void) fclose(fp);
7592
7593 /* Do CDDB1 -> CDDB2 genre mapping if possible */
7594 for (i = 0; cdinfo_genre_map[i].cddb1_genre != NULL; i++) {
7595 if (categ != NULL &&
7596 strcmp(categ, cdinfo_genre_map[i].cddb1_genre) == 0) {
7597 if (!util_newstr(&cdinfo_dbp->disc.genre,
7598 cdinfo_genre_map[i].cddb2_genre)) {
7599 CDINFO_FATAL(app_data.str_nomemory);
7600 }
7601 break;
7602 }
7603 }
7604
7605 /* Set the match bit */
7606 cdinfo_dbp->flags |= (CDINFO_MATCH | CDINFO_FROMLOC);
7607
7608 DBGPRN(DBG_CDI)(errfp, ": Loaded.\n");
7609 return TRUE;
7610 }
7611
7612
7613 /*
7614 * cdinfo_out_discog
7615 * Output local discography HTML content for the currently loaded CD
7616 *
7617 * Args:
7618 * path - File path to the local discography file
7619 * s - Pointer to the curstat_t structure
7620 * baseurl - The URL to the output file
7621 *
7622 * Return:
7623 * TRUE - success
7624 * FALSE - failure
7625 */
7626 bool_t
cdinfo_out_discog(char * path,curstat_t * s,char * baseurl)7627 cdinfo_out_discog(char *path, curstat_t *s, char *baseurl)
7628 {
7629 int i,
7630 fmt,
7631 ncreds,
7632 nrows,
7633 ntrkrows;
7634 unsigned int dmode,
7635 fmode;
7636 char *p,
7637 *q,
7638 *tblparms1,
7639 *tblparms2,
7640 *tdparms1,
7641 *tdparms2,
7642 *tdparms3,
7643 *srchact,
7644 *gname,
7645 *gpath,
7646 *dhome,
7647 *relpath,
7648 *cmd,
7649 outdir[FILE_PATH_SZ],
7650 filepath[FILE_PATH_SZ + 40],
7651 plspath[FILE_PATH_SZ + 480];
7652 FILE *fp,
7653 *pls_fp;
7654 DIR *dp;
7655 struct dirent *de;
7656 cdinfo_credit_t *cp;
7657 playls_t *lheads[MAX_FILEFMTS],
7658 *sp;
7659 filefmt_t *fmp;
7660 struct stat stbuf;
7661 bool_t first,
7662 newdiscog;
7663
7664 (void) sscanf(app_data.cdinfo_filemode, "%o", &fmode);
7665 /* Make sure file is at least accessible by user */
7666 fmode |= S_IRUSR | S_IWUSR;
7667 fmode &= ~(S_ISUID | S_ISGID);
7668
7669 /* Set directory perm based on file perm */
7670 dmode = (fmode | S_IXUSR);
7671 if (fmode & S_IRGRP)
7672 dmode |= (S_IRGRP | S_IXGRP);
7673 if (fmode & S_IWGRP)
7674 dmode |= (S_IWGRP | S_IXGRP);
7675 if (fmode & S_IROTH)
7676 dmode |= (S_IROTH | S_IXOTH);
7677 if (fmode & S_IWOTH)
7678 dmode |= (S_IWOTH | S_IXOTH);
7679
7680 if ((p = util_dirname(path)) == NULL) {
7681 DBGPRN(DBG_CDI)(errfp, "Directory path error: %s\n", path);
7682 return FALSE;
7683 }
7684 (void) strcpy(outdir, p);
7685 MEM_FREE(p);
7686
7687 newdiscog = FALSE;
7688 if (util_dirstat(outdir, &stbuf, FALSE) < 0) {
7689 if (errno == ENOENT)
7690 newdiscog = TRUE;
7691 else {
7692 DBGPRN(DBG_CDI)(errfp, "Cannot stat %s\n", outdir);
7693 return FALSE;
7694 }
7695 }
7696
7697 /* Make directories and fix perms */
7698 if (!util_mkdir(outdir, (mode_t) dmode)) {
7699 DBGPRN(DBG_CDI)(errfp, "Cannot create directory %s\n", outdir);
7700 return FALSE;
7701 }
7702
7703 /* Remove original file */
7704 if (UNLINK(path) < 0 && errno != ENOENT) {
7705 DBGPRN(DBG_CDI)(errfp, "Cannot unlink old %s\n", path);
7706 return FALSE;
7707 }
7708
7709 /* Write new file */
7710 if ((fp = fopen(path, "w")) == NULL) {
7711 DBGPRN(DBG_CDI)(errfp,
7712 "Cannot open file for writing: %s\n", path);
7713 return FALSE;
7714 }
7715 (void) chmod(path, (mode_t) fmode);
7716
7717 DBGPRN(DBG_CDI)(errfp, "\nWriting local Discography: %s\n", path);
7718
7719 /* Set up the CDDB search URL string */
7720 srchact = NULL;
7721 if (cdinfo_scddb != NULL && cdinfo_scddb->arg != NULL) {
7722 if (!util_newstr(&srchact, cdinfo_scddb->arg)) {
7723 CDINFO_FATAL(app_data.str_nomemory);
7724 return FALSE;
7725 }
7726 if ((p = strrchr(srchact, '%')) != NULL)
7727 *p = '\0';
7728 else {
7729 MEM_FREE(srchact);
7730 srchact = NULL;
7731 }
7732 }
7733
7734 /* Get genre name and path */
7735 gname = cdinfo_genre_name(cdinfo_dbp->disc.genre);
7736 if (util_strstr(gname, " -> ") != NULL)
7737 dhome = "../../..";
7738 else
7739 dhome = "../..";
7740
7741 /* Start HTML output */
7742 tblparms1 = "CELLSPACING=\"0\" CELLPADDING=\"1\" BORDER=\"0\"";
7743 tblparms2 = "CELLSPACING=\"0\" CELLPADDING=\"3\" BORDER=\"1\"";
7744 tdparms1 = "ALIGN=\"center\"";
7745 tdparms2 = "ALIGN=\"left\"";
7746 tdparms3 = "ALIGN=\"left\" VALIGN=\"top\"";
7747
7748 /* Comments */
7749 (void) fprintf(fp, "<!-- xmcd Local Discography\n");
7750 (void) fprintf(fp, " DO NOT EDIT: Generated by %s %s.%s.%s\n",
7751 cdinfo_clinfo->prog, VERSION_MAJ, VERSION_MIN, VERSION_TEENY);
7752 (void) fprintf(fp, " %s\n URL: %s E-mail: %s -->\n",
7753 COPYRIGHT, XMCD_URL, EMAIL);
7754 (void) fputs("<!-- tItLe: ", fp);
7755
7756 /* Album artist and title info in comments, for sorting by genidx */
7757 if (cdinfo_dbp->disc.artistfname.lastname != NULL ||
7758 cdinfo_dbp->disc.artistfname.firstname != NULL) {
7759 /* Use sorted artist name if possible */
7760 if (cdinfo_dbp->disc.artistfname.lastname != NULL) {
7761 util_html_fputs(cdinfo_dbp->disc.artistfname.lastname,
7762 fp, FALSE, NULL, 0);
7763 (void) fputs(", ", fp);
7764 }
7765 if (cdinfo_dbp->disc.artistfname.firstname != NULL) {
7766 util_html_fputs(cdinfo_dbp->disc.artistfname.firstname,
7767 fp, FALSE, NULL, 0);
7768 }
7769 if (cdinfo_dbp->disc.artistfname.the != NULL) {
7770 (void) fputs(", ", fp);
7771 util_html_fputs(cdinfo_dbp->disc.artistfname.the,
7772 fp, FALSE, NULL, 0);
7773 }
7774 }
7775 else if (cdinfo_dbp->disc.artist != NULL) {
7776 /* Use display name */
7777 util_html_fputs(cdinfo_dbp->disc.artist, fp, FALSE, NULL, 0);
7778 }
7779 else {
7780 (void) fputs(app_data.str_unknartist, fp);
7781 }
7782
7783 if (cdinfo_dbp->disc.sorttitle != NULL) {
7784 /* Use sort title if possible */
7785 (void) fputs(" / ", fp);
7786 util_html_fputs(cdinfo_dbp->disc.sorttitle,
7787 fp, FALSE, NULL, 0);
7788 if (cdinfo_dbp->disc.title_the != NULL) {
7789 (void) fputs(", ", fp);
7790 util_html_fputs(cdinfo_dbp->disc.title_the,
7791 fp, FALSE, NULL, 0);
7792 }
7793 }
7794 else if (cdinfo_dbp->disc.title != NULL) {
7795 /* Use display title */
7796 (void) fputs(" / ", fp);
7797 util_html_fputs(cdinfo_dbp->disc.title, fp, FALSE, NULL, 0);
7798 }
7799 else {
7800 (void) fputs(" / ", fp);
7801 (void) fputs(app_data.str_unkndisc, fp);
7802 }
7803 (void) fputs(" -->\n", fp);
7804
7805 (void) fputs("<HTML>\n<HEAD>\n", fp);
7806
7807 /* All in-core CD information is encoded in UTF-8 */
7808 (void) fputs("<META HTTP-EQUIV=\"Content-type\" "
7809 "CONTENT=\"text/html; charset=utf-8\">\n", fp);
7810
7811 (void) fputs("<TITLE>\nxmcd: ", fp);
7812
7813 if (cdinfo_dbp->disc.artist != NULL)
7814 util_html_fputs(cdinfo_dbp->disc.artist, fp, FALSE, NULL, 0);
7815 else
7816 (void) fputs(app_data.str_unknartist, fp);
7817
7818 (void) fputs(" / ", fp);
7819
7820 if (cdinfo_dbp->disc.title != NULL)
7821 util_html_fputs(cdinfo_dbp->disc.title, fp, FALSE, NULL, 0);
7822 else
7823 (void) fputs(app_data.str_unkndisc, fp);
7824
7825 (void) fputs("\n</TITLE>\n", fp);
7826
7827 #ifdef __VMS
7828 (void) sprintf(filepath, "%s.discog]bkgnd.gif", app_data.libdir);
7829 if ((p = util_vms_urlconv(filepath, VMS_2_UNIX)) != NULL) {
7830 (void) strncpy(filepath, p, sizeof(filepath)-1);
7831 filepath[sizeof(filepath)-1] = '\0';
7832 MEM_FREE(p);
7833 }
7834 #else
7835 (void) sprintf(filepath, "%s/bkgnd.gif", dhome);
7836 #endif
7837 (void) fprintf(fp,
7838 "</HEAD>\n<BODY BGCOLOR=\"%s\" BACKGROUND=\"%s\">\n",
7839 "#FFFFFF", /* Background color */
7840 filepath
7841 );
7842
7843 (void) fputs("<DIV ALIGN=\"center\">\n", fp);
7844
7845 /* xmcd logo */
7846 (void) fprintf(fp, "<A HREF=\"%s\">\n", XMCD_URL);
7847 #ifdef __VMS
7848 (void) sprintf(filepath, "%s.discog]xmcdlogo.gif", app_data.libdir);
7849 if ((p = util_vms_urlconv(filepath, VMS_2_UNIX)) != NULL) {
7850 (void) strncpy(filepath, p, sizeof(filepath)-1);
7851 filepath[sizeof(filepath)-1] = '\0';
7852 MEM_FREE(p);
7853 }
7854 #else
7855 (void) sprintf(filepath, "%s/xmcdlogo.gif", dhome);
7856 #endif
7857 (void) fprintf(fp, "<IMG SRC=\"%s\" ALT=\"xmcd\" BORDER=\"0\">",
7858 filepath);
7859 (void) fprintf(fp, "</A><P>\n<H4>Local Discography</H4><P>\n");
7860
7861 /* Disc artist / title */
7862 (void) fputs("<H3>\n", fp);
7863 if (cdinfo_dbp->disc.artist == NULL)
7864 (void) fprintf(fp, "(%s)", app_data.str_unknartist);
7865 else {
7866 if (srchact != NULL) {
7867 p = cdinfo_txtreduce(cdinfo_dbp->disc.artist, TRUE);
7868 (void) fprintf(fp, "<A HREF=\"%s%s\">", srchact, p);
7869 MEM_FREE(p);
7870 }
7871 util_html_fputs(cdinfo_dbp->disc.artist, fp, FALSE, NULL, 0);
7872 if (srchact != NULL)
7873 (void) fputs("</A>\n", fp);
7874 }
7875
7876 (void) fputs(" / ", fp);
7877
7878 if (cdinfo_dbp->disc.title == NULL)
7879 (void) fprintf(fp, "(%s)", app_data.str_unkndisc);
7880 else {
7881 if (srchact != NULL) {
7882 p = cdinfo_txtreduce(cdinfo_dbp->disc.title, TRUE);
7883 (void) fprintf(fp, "<A HREF=\"%s%s\">", srchact, p);
7884 MEM_FREE(p);
7885 }
7886 util_html_fputs(cdinfo_dbp->disc.title, fp, FALSE, NULL, 0);
7887 if (srchact != NULL)
7888 (void) fputs("</A>\n", fp);
7889 }
7890 (void) fputs("</H3>\n", fp);
7891
7892 /* Album information */
7893 (void) fprintf(fp, "<P>\n<TABLE %s>\n", tblparms1);
7894 (void) fprintf(fp, "<TR><TH %s>Total time:</TH><TD %s> %02d:%02d"
7895 "</TD></TR>\n",
7896 tdparms2, tdparms2,
7897 s->discpos_tot.min, s->discpos_tot.sec
7898 );
7899 (void) fprintf(fp, "<TR><TH %s>Primary genre:</TH><TD %s> ",
7900 tdparms2, tdparms2
7901 );
7902 util_html_fputs(gname, fp, FALSE, NULL, 0);
7903 (void) fputs("</TD></TR>\n", fp);
7904 (void) fprintf(fp, "<TR><TH %s>Secondary genre:</TH><TD %s> ",
7905 tdparms2, tdparms2
7906 );
7907 util_html_fputs(cdinfo_genre_name(cdinfo_dbp->disc.genre2),
7908 fp, FALSE, NULL, 0);
7909 (void) fputs("</TD></TR>\n", fp);
7910 (void) fprintf(fp,
7911 "<TR><TH %s>Xmcd disc ID:</TH><TD %s> %08x</TD></TR>\n",
7912 tdparms2, tdparms2, cdinfo_dbp->discid
7913 );
7914 (void) fprintf(fp, "<TR><TH %s>Artist full name:</TH><TD %s> ",
7915 tdparms2, tdparms2
7916 );
7917 if (cdinfo_dbp->disc.artistfname.lastname != NULL) {
7918 util_html_fputs(cdinfo_dbp->disc.artistfname.lastname,
7919 fp, FALSE, NULL, 0);
7920 (void) fputs(", ", fp);
7921 }
7922 if (cdinfo_dbp->disc.artistfname.firstname != NULL) {
7923 util_html_fputs(cdinfo_dbp->disc.artistfname.firstname,
7924 fp, FALSE, NULL, 0);
7925 }
7926 if (cdinfo_dbp->disc.artistfname.the != NULL) {
7927 (void) fputs(", ", fp);
7928 util_html_fputs(cdinfo_dbp->disc.artistfname.the,
7929 fp, FALSE, NULL, 0);
7930 }
7931 (void) fputs("</TD></TR>\n", fp);
7932 (void) fprintf(fp, "<TR><TH %s>Sort title:</TH><TD %s> ",
7933 tdparms2, tdparms2
7934 );
7935 if (cdinfo_dbp->disc.sorttitle != NULL) {
7936 util_html_fputs(cdinfo_dbp->disc.sorttitle,
7937 fp, FALSE, NULL, 0);
7938 }
7939 if (cdinfo_dbp->disc.title_the != NULL) {
7940 (void) fputs(", ", fp);
7941 util_html_fputs(cdinfo_dbp->disc.title_the,
7942 fp, FALSE, NULL, 0);
7943 }
7944 (void) fputs("</TD></TR>\n", fp);
7945 (void) fprintf(fp, "<TR><TH %s>Year:</TH><TD %s> %s</TD></TR>\n",
7946 tdparms2, tdparms2,
7947 cdinfo_dbp->disc.year == NULL ? "" : cdinfo_dbp->disc.year
7948 );
7949 (void) fprintf(fp, "<TR><TH %s>Record label:</TH><TD %s> ",
7950 tdparms2, tdparms2
7951 );
7952 if (cdinfo_dbp->disc.label != NULL)
7953 util_html_fputs(cdinfo_dbp->disc.label, fp, FALSE, NULL, 0);
7954 (void) fputs("</TD></TR>\n", fp);
7955 (void) fprintf(fp,
7956 "<TR><TH %s>Compilation:</TH><TD %s> %s</TD></TR>\n",
7957 tdparms2, tdparms2,
7958 cdinfo_dbp->disc.compilation ? "Yes" : "No"
7959 );
7960 (void) fprintf(fp,
7961 "<TR><TH %s>Disc:</TH><TD %s> %s of %s</TD></TR>\n",
7962 tdparms2, tdparms2,
7963 cdinfo_dbp->disc.dnum == NULL ? "?" : cdinfo_dbp->disc.dnum,
7964 cdinfo_dbp->disc.tnum == NULL ? "?" : cdinfo_dbp->disc.tnum
7965 );
7966 (void) fprintf(fp, "<TR><TH %s>Region:</TH><TD %s> ",
7967 tdparms2, tdparms2
7968 );
7969 util_html_fputs(cdinfo_region_name(cdinfo_dbp->disc.region),
7970 fp, FALSE, NULL, 0);
7971 (void) fputs("</TD></TR>\n", fp);
7972 (void) fprintf(fp, "<TR><TH %s>Language:</TH><TD %s> ",
7973 tdparms2, tdparms2
7974 );
7975 util_html_fputs(cdinfo_lang_name(cdinfo_dbp->disc.lang),
7976 fp, FALSE, NULL, 0);
7977 (void) fputs("</TD></TR>\n", fp);
7978 (void) fputs("</TABLE>\n", fp);
7979
7980 /* Big info table */
7981 (void) fprintf(fp, "<P>\n<TABLE %s>\n", tblparms2);
7982 (void) fputs("<TR>\n", fp);
7983 (void) fprintf(fp, "<TH %s>Track</TH>\n", tdparms1);
7984 (void) fprintf(fp, "<TH %s>Start</TH>\n", tdparms1);
7985 (void) fprintf(fp, "<TH %s>Length</TH>\n", tdparms1);
7986 (void) fprintf(fp, "<TH %s>Artist</TH>\n", tdparms1);
7987 (void) fprintf(fp, "<TH %s>Title</TH>\n", tdparms1);
7988 (void) fprintf(fp, "<TH %s>Pri genre</TH>\n", tdparms1);
7989 (void) fprintf(fp, "<TH %s>Sec genre</TH>\n", tdparms1);
7990 (void) fprintf(fp, "<TH %s>BPM</TH>\n", tdparms1);
7991 (void) fprintf(fp, "<TH %s>Year</TH>\n", tdparms1);
7992 (void) fprintf(fp, "<TH %s>Record label</TH>\n", tdparms1);
7993 (void) fputs("</TR>\n", fp);
7994
7995 ntrkrows = 0;
7996 for (i = 0; i < (int) s->tot_trks; i++) {
7997 int min,
7998 sec,
7999 secs;
8000
8001 secs = ((s->trkinfo[i+1].min * 60 + s->trkinfo[i+1].sec) -
8002 (s->trkinfo[i].min * 60 + s->trkinfo[i].sec));
8003 min = (byte_t) (secs / 60);
8004 sec = (byte_t) (secs % 60);
8005
8006 (void) fprintf(fp, "<TR>\n<TD %s>%d</TD>\n",
8007 tdparms1,
8008 s->trkinfo[i].trkno
8009 );
8010 (void) fprintf(fp, "<TD %s>%02d:%02d</TD>\n",
8011 tdparms1, s->trkinfo[i].min, s->trkinfo[i].sec);
8012 (void) fprintf(fp, "<TD %s>%02d:%02d</TD>\n",
8013 tdparms1, min, sec);
8014
8015 if (cdinfo_dbp->track[i].artist == NULL) {
8016 (void) fprintf(fp, "<TD %s><B> </B></TD>\n",
8017 tdparms2
8018 );
8019 }
8020 else {
8021 (void) fprintf(fp, "<TD %s><B>", tdparms2);
8022 if (srchact != NULL) {
8023 p = cdinfo_txtreduce(
8024 cdinfo_dbp->track[i].artist,
8025 TRUE
8026 );
8027 (void) fprintf(fp, "<A HREF=\"%s%s\">",
8028 srchact, p
8029 );
8030 MEM_FREE(p);
8031 }
8032 util_html_fputs(
8033 cdinfo_dbp->track[i].artist,
8034 fp,
8035 FALSE,
8036 NULL,
8037 0
8038 );
8039 if (srchact != NULL)
8040 (void) fputs("</A>", fp);
8041 (void) fputs("</B></TD>\n", fp);
8042 }
8043
8044 if (cdinfo_dbp->track[i].title == NULL) {
8045 (void) fprintf(fp, "<TD %s><B>(%s)</B></TD>\n",
8046 tdparms2,
8047 app_data.str_unkntrk
8048 );
8049 }
8050 else {
8051 (void) fprintf(fp, "<TD %s><B>", tdparms2);
8052 if (srchact != NULL) {
8053 p = cdinfo_txtreduce(
8054 cdinfo_dbp->track[i].title,
8055 TRUE
8056 );
8057 (void) fprintf(fp, "<A HREF=\"%s%s\">",
8058 srchact, p
8059 );
8060 MEM_FREE(p);
8061 }
8062 util_html_fputs(
8063 cdinfo_dbp->track[i].title,
8064 fp,
8065 FALSE,
8066 NULL,
8067 0
8068 );
8069 if (srchact != NULL)
8070 (void) fputs("</A>", fp);
8071 (void) fputs("</B></TD>\n", fp);
8072 }
8073
8074 (void) fprintf(fp, "<TD %s>", tdparms2);
8075 util_html_fputs(cdinfo_genre_name(cdinfo_dbp->track[i].genre),
8076 fp, FALSE, NULL, 0);
8077 fputs(" </TD>\n", fp);
8078
8079 (void) fprintf(fp, "<TD %s>", tdparms2);
8080 util_html_fputs(cdinfo_genre_name(cdinfo_dbp->track[i].genre2),
8081 fp, FALSE, NULL, 0);
8082 fputs(" </TD>\n", fp);
8083
8084 (void) fprintf(fp, "<TD %s>%s</TD>\n",
8085 tdparms2,
8086 cdinfo_dbp->track[i].bpm == NULL ? " " :
8087 cdinfo_dbp->track[i].bpm);
8088
8089 (void) fprintf(fp, "<TD %s>%s</TD>\n",
8090 tdparms2,
8091 cdinfo_dbp->track[i].year == NULL ? " " :
8092 cdinfo_dbp->track[i].year);
8093
8094 (void) fprintf(fp, "<TD %s>", tdparms2);
8095 if (cdinfo_dbp->track[i].label != NULL)
8096 util_html_fputs(cdinfo_dbp->track[i].label,
8097 fp, FALSE, NULL, 0);
8098 else
8099 (void) fputs(" ", fp);
8100 (void) fputs("</TD>\n</TR>\n", fp);
8101
8102 /* Count the number of rows needed for track credits and
8103 * track notes
8104 */
8105 for (cp = cdinfo_dbp->track[i].credit_list; cp != NULL;
8106 cp = cp->next)
8107 ntrkrows++;
8108 if (cdinfo_dbp->track[i].notes != NULL)
8109 ntrkrows++;
8110 }
8111 (void) fputs("<TR><TD COLSPAN=\"10\"> </TD></TR>\n", fp);
8112
8113 /* Album credits and notes */
8114 ncreds = 0;
8115 for (cp = cdinfo_dbp->disc.credit_list; cp != NULL; cp = cp->next)
8116 ncreds++;
8117
8118 nrows = ncreds + (cdinfo_dbp->disc.notes == NULL ? 0 : 1);
8119 if (nrows > 0) {
8120 first = TRUE;
8121 (void) fprintf(fp,
8122 "<TR>\n<TH %s ROWSPAN=\"%d\">Album<BR>"
8123 "Credits<BR>& Notes</TH>\n",
8124 tdparms3, nrows
8125 );
8126
8127 /* credits */
8128 for (cp = cdinfo_dbp->disc.credit_list; cp != NULL;
8129 cp = cp->next) {
8130 if (first)
8131 first = FALSE;
8132 else
8133 (void) fputs("<TR>\n", fp);
8134
8135 (void) fprintf(fp, "<TD %s COLSPAN=\"4\">", tdparms2);
8136 if (cp->crinfo.name != NULL) {
8137 if (srchact != NULL) {
8138 p = cdinfo_txtreduce(cp->crinfo.name,
8139 TRUE);
8140 (void) fprintf(fp, "<A HREF=\"%s%s\">",
8141 srchact, p
8142 );
8143 MEM_FREE(p);
8144 }
8145 (void) fputs(cp->crinfo.name, fp);
8146 if (srchact != NULL)
8147 (void) fputs("</A>", fp);
8148 }
8149 else
8150 (void) fputs("unknown", fp);
8151
8152 (void) fputs(" (", fp);
8153 if (cp->crinfo.role != NULL)
8154 util_html_fputs(cp->crinfo.role->name,
8155 fp, FALSE, NULL, 0);
8156 else
8157 fputs("unknown", fp);
8158 (void) fputs(")</TD>\n", fp);
8159
8160 (void) fprintf(fp, "<TD %s COLSPAN=\"5\">", tdparms2);
8161 if (cp->notes != NULL)
8162 util_html_fputs(cp->notes, fp, TRUE,
8163 "courier", -1);
8164 else
8165 (void) fputs(" ", fp);
8166 (void) fputs("</TD>\n</TR>\n", fp);
8167 }
8168
8169 /* notes */
8170 if (cdinfo_dbp->disc.notes != NULL) {
8171 if (!first)
8172 (void) fputs("<TR>\n", fp);
8173 (void) fprintf(fp, "<TD %s COLSPAN=\"9\">", tdparms2);
8174 util_html_fputs(cdinfo_dbp->disc.notes,
8175 fp, TRUE, "courier", -1);
8176 (void) fputs("</TD>\n</TR>\n", fp);
8177 }
8178 }
8179
8180 /* Track credits and notes */
8181 if (ntrkrows > 0) {
8182 (void) fprintf(fp,
8183 "<TH %s ROWSPAN=\"%d\">"
8184 "Track<BR>Credits<BR>& Notes</TH>\n",
8185 tdparms3, ntrkrows);
8186
8187 for (i = 0; i < (int) s->tot_trks; i++) {
8188 if (cdinfo_dbp->track[i].credit_list == NULL &&
8189 cdinfo_dbp->track[i].notes == NULL)
8190 continue;
8191
8192 ncreds = 0;
8193 for (cp = cdinfo_dbp->track[i].credit_list; cp != NULL;
8194 cp = cp->next)
8195 ncreds++;
8196
8197 nrows = ncreds + (cdinfo_dbp->track[i].notes == NULL ?
8198 0 : 1);
8199
8200 (void) fprintf(fp,
8201 "<TD %s ROWSPAN=\"%d\">Track %d</TD>\n",
8202 tdparms3,
8203 nrows,
8204 (int) s->trkinfo[i].trkno);
8205
8206 first = TRUE;
8207 /* credits */
8208 for (cp = cdinfo_dbp->track[i].credit_list; cp != NULL;
8209 cp = cp->next) {
8210 if (first)
8211 first = FALSE;
8212 else
8213 (void) fputs("<TR>\n", fp);
8214
8215 (void) fprintf(fp, "<TD %s COLSPAN=\"3\">",
8216 tdparms2);
8217
8218 if (cp->crinfo.name != NULL) {
8219 if (srchact != NULL) {
8220 p = cdinfo_txtreduce(
8221 cp->crinfo.name,
8222 TRUE
8223 );
8224 (void) fprintf(fp,
8225 "<A HREF=\"%s%s\">",
8226 srchact, p
8227 );
8228 MEM_FREE(p);
8229 }
8230 (void) fputs(cp->crinfo.name, fp);
8231 if (srchact != NULL)
8232 (void) fputs("</A>", fp);
8233 }
8234 else
8235 (void) fputs("unknown", fp);
8236
8237 (void) fputs(" (", fp);
8238 if (cp->crinfo.role != NULL)
8239 util_html_fputs(cp->crinfo.role->name,
8240 fp, TRUE, NULL, 0);
8241 else
8242 (void) fputs("unknown", fp);
8243 (void) fputs(")</TD>\n", fp);
8244
8245 (void) fprintf(fp, "<TD %s COLSPAN=\"5\">",
8246 tdparms2);
8247 if (cp->notes == NULL)
8248 (void) fputs(" ", fp);
8249 else
8250 util_html_fputs(cp->notes, fp, TRUE,
8251 "courier", -1);
8252 (void) fputs("</TD>\n</TR>\n", fp);
8253 }
8254
8255 /* notes */
8256 if (cdinfo_dbp->track[i].notes != NULL) {
8257 if (!first)
8258 (void) fputs("<TR>\n", fp);
8259
8260 (void) fprintf(fp, "<TD %s COLSPAN=\"8\">",
8261 tdparms2);
8262 util_html_fputs(cdinfo_dbp->track[i].notes,
8263 fp, TRUE,
8264 "courier", -1);
8265 (void) fputs("</TD>\n</TR>\n", fp);
8266 }
8267 }
8268 }
8269
8270 (void) fputs("</TABLE>\n", fp);
8271
8272 /* end of <DIV ALIGN="center"> */
8273 (void) fputs("</DIV>\n<P>\n", fp);
8274
8275 /* Local discography */
8276 (void) fputs("<H4>Local Discography</H4>\n<P>\n<UL>\n", fp);
8277
8278 /* Initialize list heads */
8279 for (i = 0; i < MAX_FILEFMTS; i++)
8280 lheads[i] = NULL;
8281
8282 /* Check directory and add links to files */
8283 if (((util_urlchk(baseurl, &p, &i) & IS_REMOTE_URL) == 0) &&
8284 (dp = OPENDIR(outdir)) != NULL) {
8285 while ((de = READDIR(dp)) != NULL) {
8286 if (strcmp(de->d_name, ".") == 0 ||
8287 strcmp(de->d_name, "..") == 0)
8288 /* Skip . and .. */
8289 continue;
8290
8291 #ifdef __VMS
8292 /* Discard version number */
8293 if ((p = strrchr(de->d_name, ';')) != NULL)
8294 *p = '\0';
8295
8296 p = util_vms_urlconv(outdir, VMS_2_UNIX);
8297 if (p != NULL) {
8298 (void) strncpy(filepath, p,
8299 sizeof(filepath)-1);
8300 filepath[sizeof(filepath)-1] = '\0';
8301 MEM_FREE(p);
8302 }
8303 #else
8304 filepath[0] = '\0';
8305 #endif
8306
8307 if (util_strcasecmp(de->d_name, "index.html") == 0)
8308 /* Skip index.html which we're generating */
8309 continue;
8310
8311 fmt = -1;
8312 if ((p = strrchr(de->d_name, '.')) != NULL) {
8313 if (util_strcasecmp(p, ".m3u") == 0 ||
8314 util_strcasecmp(p, ".pls") == 0)
8315 /* Skip playlist files */
8316 continue;
8317
8318 /* Check if the file is an audio track */
8319 for (i = 0; i < MAX_FILEFMTS; i++) {
8320 if ((fmp = cdda_filefmt(i)) == NULL)
8321 continue;
8322
8323 if (util_strcasecmp(p, fmp->suf) == 0)
8324 fmt = fmp->fmt;
8325 }
8326 }
8327
8328 if (fmt >= 0) {
8329 playls_t **hp;
8330
8331 /* An audio track: Add to appropriate list */
8332
8333 hp = &lheads[fmt];
8334
8335 sp = (playls_t *) MEM_ALLOC(
8336 "playls_t",
8337 sizeof(playls_t)
8338 );
8339 if (sp != NULL) {
8340 sp->prev = sp->next = NULL;
8341 sp->prev2 = sp->next2 = NULL;
8342 sp->path = NULL;
8343
8344 if (!util_newstr(&sp->path,
8345 de->d_name)) {
8346 MEM_FREE(sp);
8347 }
8348 else {
8349 /* Add to list */
8350 if (*hp != NULL)
8351 (*hp)->prev = sp;
8352 sp->next = *hp;
8353 *hp = sp;
8354 }
8355 }
8356 }
8357 else {
8358 /* Not an audio track */
8359 (void) fprintf(fp,
8360 "<LI><A HREF=\"%s%s\">%s: %s</A></LI>\n",
8361 filepath, de->d_name, "File", de->d_name
8362 );
8363 }
8364 }
8365
8366 (void) CLOSEDIR(dp);
8367 }
8368
8369 #ifdef __VMS
8370 p = util_vms_urlconv(outdir, VMS_2_UNIX);
8371 if (p != NULL) {
8372 (void) strncpy(filepath, p, sizeof(filepath)-1);
8373 filepath[sizeof(filepath)-1] = '\0';
8374 MEM_FREE(p);
8375 }
8376 #else
8377 filepath[0] = '\0';
8378 #endif
8379
8380 relpath = NULL;
8381 if (app_data.discog_url_pfx != NULL &&
8382 (p = util_basename(app_data.discog_url_pfx)) != NULL) {
8383 if ((q = util_strstr(outdir, p)) != NULL)
8384 q += strlen(p);
8385 else
8386 q = NULL;
8387
8388 MEM_FREE(p);
8389
8390 if (q != NULL) {
8391 if (!util_newstr(&relpath, q)) {
8392 CDINFO_FATAL(app_data.str_nomemory);
8393 return FALSE;
8394 }
8395 #ifdef __VMS
8396 /* Convert VMS file path name separators into
8397 * URL path separators
8398 */
8399 for (p = relpath; *p != '\0'; p++) {
8400 if (*p == '.')
8401 *p = '/';
8402 else if (*p == ']')
8403 *p = '\0';
8404 }
8405 #endif
8406 }
8407 }
8408
8409 /* For each file format, generate audio track playlists */
8410 for (i = 0; i < MAX_FILEFMTS; i++) {
8411 playls_t *shead;
8412
8413 if (lheads[i] == NULL || (fmp = cdda_filefmt(i)) == NULL)
8414 continue;
8415
8416 #ifdef __VMS
8417 (void) sprintf(plspath, "%s%s.m3u", outdir, fmp->name);
8418 #else
8419 (void) sprintf(plspath, "%s%c%s.m3u",
8420 outdir, DIR_END, fmp->name);
8421 #endif
8422 (void) UNLINK(plspath);
8423
8424 /* Sort the track list */
8425 shead = cdinfo_sort_playlist(lheads[i]);
8426
8427 /* Write audio track list in discography file */
8428 (void) fprintf(fp, "<LI>%s audio tracks:</LI>\n", fmp->name);
8429 (void) fputs("<UL>\n", fp);
8430
8431 /* Write .m3u format playlist file */
8432 if ((pls_fp = fopen(plspath, "w")) == NULL) {
8433 DBGPRN(DBG_CDI)(errfp,
8434 "Cannot open %s for writing.\n", plspath);
8435 }
8436 else {
8437 (void) chmod(plspath, (mode_t) fmode);
8438
8439 for (sp = shead; sp != NULL; sp = sp->next2) {
8440 if (relpath == NULL) {
8441 (void) fprintf(pls_fp, "%s\n",
8442 sp->path
8443 );
8444 }
8445 else {
8446 p = (char *) MEM_ALLOC("plsurl",
8447 strlen(relpath) +
8448 strlen(sp->path) + 4
8449 );
8450 if (p != NULL) {
8451 /* This is a URL, so use '/'
8452 * even for VMS.
8453 */
8454 (void) sprintf(p, "%s/%s",
8455 relpath,
8456 sp->path
8457 );
8458
8459 q = util_urlencode(p);
8460 if (q != NULL) {
8461 (void) fprintf(
8462 pls_fp, "%s%s\n",
8463 app_data.discog_url_pfx,
8464 q
8465 );
8466 MEM_FREE(q);
8467 }
8468
8469 MEM_FREE(p);
8470 }
8471 }
8472 }
8473
8474 (void) fclose(pls_fp);
8475
8476 /* Add playlist file entry to local discography */
8477 (void) fprintf(fp,
8478 "<LI><A HREF=\"%s%s.m3u\">"
8479 "Playlist</A> (.m3u format)</LI>\n",
8480 filepath, fmp->name
8481 );
8482 }
8483
8484 #ifdef __VMS
8485 (void) sprintf(plspath, "%s%s.pls", outdir, fmp->name);
8486 #else
8487 (void) sprintf(plspath, "%s%c%s.pls",
8488 outdir, DIR_END, fmp->name);
8489 #endif
8490 (void) UNLINK(plspath);
8491
8492 /* Write .pls format playlist file */
8493 if ((pls_fp = fopen(plspath, "w")) == NULL) {
8494 DBGPRN(DBG_CDI)(errfp,
8495 "Cannot open %s for writing.\n", plspath);
8496 }
8497 else {
8498 int n;
8499
8500 (void) chmod(plspath, (mode_t) fmode);
8501 (void) fprintf(pls_fp, "[playlist]\n");
8502
8503 n = 1;
8504 for (sp = shead; sp != NULL; sp = sp->next2) {
8505 char *cp,
8506 *cp2;
8507 int len;
8508
8509 (void) sprintf(plspath, "%s%c%s",
8510 outdir, DIR_END, sp->path);
8511 if (stat(plspath, &stbuf) < 0 ||
8512 !S_ISREG(stbuf.st_mode))
8513 len = -1;
8514 else
8515 len = (int) stbuf.st_size;
8516
8517 if (relpath == NULL) {
8518 (void) fprintf(pls_fp, "File%d=%s\n",
8519 n, sp->path
8520 );
8521 }
8522 else {
8523 p = (char *) MEM_ALLOC("plsurl",
8524 strlen(relpath) +
8525 strlen(sp->path) + 4
8526 );
8527 /* This is a URL, so use '/'
8528 * even for VMS.
8529 */
8530 if (p != NULL) {
8531 (void) sprintf(p, "%s/%s",
8532 relpath,
8533 sp->path
8534 );
8535
8536 q = util_urlencode(p);
8537 if (q != NULL) {
8538 (void) fprintf(
8539 pls_fp, "File%d=%s%s\n",
8540 n,
8541 app_data.discog_url_pfx,
8542 q
8543 );
8544 MEM_FREE(q);
8545 }
8546
8547 MEM_FREE(p);
8548 }
8549 }
8550
8551 cp = NULL;
8552 if (!util_newstr(&cp, sp->path)) {
8553 cp = sp->path;
8554 }
8555 else for (cp2 = cp; *cp2 != '\0'; cp2++) {
8556 if (util_strcasecmp(cp2, fmp->suf) == 0) {
8557 *cp2 = '\0';
8558 break;
8559 }
8560 else if (*cp2 == '_' || *cp2 == '-')
8561 *cp2 = ' ';
8562 }
8563
8564 (void) fprintf(pls_fp, "Title%d=%s\n",
8565 n, cp);
8566 (void) fprintf(pls_fp, "Length%d=%d\n",
8567 n, len);
8568
8569 if (cp != sp->path)
8570 MEM_FREE(cp);
8571 n++;
8572 }
8573
8574 (void) fprintf(pls_fp, "NumberOfEntries=%d\n", n - 1);
8575 (void) fprintf(pls_fp, "Version=2\n");
8576 (void) fclose(pls_fp);
8577
8578 /* Add playlist file entry to local discography */
8579 (void) fprintf(fp,
8580 "<LI><A HREF=\"%s%s.pls\">"
8581 "Playlist</A> (.pls format)</LI>\n",
8582 filepath, fmp->name
8583 );
8584 }
8585
8586 /* Add audio track files to local discography */
8587 for (sp = shead; sp != NULL; sp = sp->next2) {
8588 (void) fprintf(fp,
8589 "<LI><A HREF=\"%s%s\">Track: %s</A></LI>\n",
8590 filepath, sp->path, sp->path
8591 );
8592 }
8593 (void) fputs("</UL>\n", fp);
8594
8595 /* Deallocate the playlist for the file format */
8596 sp = lheads[i];
8597 while (sp != NULL) {
8598 playls_t *sp2;
8599
8600 sp2 = sp->next;
8601 if (sp->path != NULL)
8602 MEM_FREE(sp->path);
8603 MEM_FREE(sp);
8604 sp = sp2;
8605 }
8606 lheads[i] = NULL;
8607 }
8608
8609 if (relpath != NULL)
8610 MEM_FREE(relpath);
8611
8612 #ifdef __VMS
8613 (void) sprintf(filepath, "%s.discog]index.html", app_data.libdir);
8614 if ((p = util_vms_urlconv(filepath, VMS_2_UNIX)) != NULL) {
8615 (void) strncpy(filepath, p, sizeof(filepath)-1);
8616 filepath[sizeof(filepath)-1] = '\0';
8617 MEM_FREE(p);
8618 }
8619 #else
8620 (void) sprintf(filepath, "%s/index.html", dhome);
8621 #endif
8622 (void) fprintf(fp, "<LI><A HREF=\"%s\">Main index</A></LI>\n",
8623 filepath);
8624
8625 #ifdef __VMS
8626 if ((p = util_dirname(outdir)) == NULL) {
8627 (void) sprintf(filepath, "index.html");
8628 }
8629 else {
8630 (void) sprintf(filepath, "%sindex.html", p);
8631 MEM_FREE(p);
8632 }
8633
8634 if ((p = util_vms_urlconv(filepath, VMS_2_UNIX)) != NULL) {
8635 (void) strncpy(filepath, p, sizeof(filepath)-1);
8636 filepath[sizeof(filepath)-1] = '\0';
8637 MEM_FREE(p);
8638 }
8639 #else
8640 (void) sprintf(filepath, "../index.html");
8641 #endif
8642 if (cdinfo_dbp->disc.genre != NULL) {
8643 (void) fprintf(fp, "<LI><A HREF=\"%s\">", filepath);
8644 util_html_fputs(
8645 cdinfo_genre_name(cdinfo_dbp->disc.genre),
8646 fp, TRUE, NULL, 0
8647 );
8648 (void) fputs(" index</A></LI>\n", fp);
8649 }
8650
8651 if (cdinfo_dbp->disc.genre2 != NULL) {
8652 gpath = cdinfo_genre_path(cdinfo_dbp->disc.genre2);
8653 #ifdef __VMS
8654 (void) sprintf(filepath, "%s.discog.%s]index.html",
8655 app_data.libdir, gpath);
8656 if ((p = util_vms_urlconv(filepath, VMS_2_UNIX)) != NULL) {
8657 (void) strncpy(filepath, p, sizeof(filepath)-1);
8658 filepath[sizeof(filepath)-1] = '\0';
8659 MEM_FREE(p);
8660 }
8661 #else
8662 (void) sprintf(filepath, "%s/%s/index.html", dhome, gpath);
8663 #endif
8664 (void) fprintf(fp, "<LI><A HREF=\"%s\">", filepath);
8665 util_html_fputs(
8666 cdinfo_genre_name(cdinfo_dbp->disc.genre2),
8667 fp, TRUE, NULL, 0
8668 );
8669 (void) fputs(" index</A></LI>\n", fp);
8670 }
8671
8672 #ifdef __VMS
8673 (void) sprintf(filepath, "%s.discog]discog.html", app_data.libdir);
8674 if ((p = util_vms_urlconv(filepath, VMS_2_UNIX)) != NULL) {
8675 (void) strncpy(filepath, p, sizeof(filepath)-1);
8676 filepath[sizeof(filepath)-1] = '\0';
8677 MEM_FREE(p);
8678 }
8679 #else
8680 (void) sprintf(filepath, "%s/discog.html", dhome);
8681 #endif
8682 (void) fprintf(fp, "<LI><A HREF=\"%s\">%s</A></LI>\n",
8683 filepath, "How to use Local Discography");
8684
8685 (void) fputs("</UL>\n<P>\n", fp);
8686
8687 /* Directory info */
8688 (void) fprintf(fp, "<HR>\nThis directory: <B>%s</B><BR>\n", outdir);
8689 (void) fputs("</BODY>\n</HTML>\n", fp);
8690
8691 if (srchact != NULL)
8692 MEM_FREE(srchact);
8693
8694 (void) fclose(fp);
8695
8696 if (newdiscog) {
8697 /* Generate local discography index for the primary genre */
8698
8699 gpath = cdinfo_genre_path(cdinfo_dbp->disc.genre);
8700 cmd = (char *) MEM_ALLOC("genidx_cmd",
8701 strlen(gpath) + STR_BUF_SZ
8702 );
8703 if (cmd == NULL) {
8704 CDINFO_FATAL(app_data.str_nomemory);
8705 return FALSE;
8706 }
8707 #ifdef __VMS
8708 (void) sprintf(cmd, "genidx %s", gpath);
8709 #else
8710 (void) sprintf(cmd, "genidx %s >/dev/null 2>&1 &", gpath);
8711 #endif
8712
8713 DBGPRN(DBG_CDI)(errfp,
8714 "\nGenerating local discography index for %s\n",
8715 gpath);
8716
8717 (void) util_runcmd(cmd, cdinfo_clinfo->workproc,
8718 cdinfo_clinfo->arg);
8719 MEM_FREE(cmd);
8720 }
8721
8722 if (cdinfo_dbp->disc.genre2 != NULL) {
8723 gpath = cdinfo_genre_path(cdinfo_dbp->disc.genre2);
8724 #ifdef __VMS
8725 (void) sprintf(filepath, "%s.discog.%s]index.html",
8726 app_data.libdir, gpath);
8727 if ((p = util_vms_urlconv(filepath, VMS_2_UNIX)) != NULL) {
8728 (void) strncpy(filepath, p, sizeof(filepath)-1);
8729 filepath[sizeof(filepath)-1] = '\0';
8730 MEM_FREE(p);
8731 }
8732 #else
8733 (void) sprintf(filepath, "%s/%s/%s/index.html",
8734 outdir, dhome, gpath);
8735 #endif
8736 if (stat(filepath, &stbuf) < 0 && errno == ENOENT) {
8737 /* Generate local discography index for the
8738 * secondary genre, if applicable
8739 */
8740 cmd = (char *) MEM_ALLOC("genidx_cmd",
8741 strlen(gpath) + STR_BUF_SZ
8742 );
8743 if (cmd == NULL) {
8744 CDINFO_FATAL(app_data.str_nomemory);
8745 return FALSE;
8746 }
8747 #ifdef __VMS
8748 (void) sprintf(cmd, "genidx %s", gpath);
8749 #else
8750 (void) sprintf(cmd, "genidx %s >/dev/null 2>&1 &",
8751 gpath);
8752 #endif
8753
8754 DBGPRN(DBG_CDI)(errfp,
8755 "\nGenerating local discography index for %s\n",
8756 gpath);
8757
8758 (void) util_runcmd(cmd, cdinfo_clinfo->workproc,
8759 cdinfo_clinfo->arg);
8760 MEM_FREE(cmd);
8761 }
8762 }
8763
8764 return TRUE;
8765 }
8766
8767
8768 /*
8769 * cdinfo_map_cdtext
8770 * Move CD-TEXT data to the incore CD information main structure.
8771 *
8772 * Args:
8773 * s - Pointer to the curstat_t structure.
8774 * cdt - Pointer to the di_cdtext_t structure.
8775 *
8776 * Return:
8777 * Nothing.
8778 */
8779 void
cdinfo_map_cdtext(curstat_t * s,di_cdtext_t * cdt)8780 cdinfo_map_cdtext(curstat_t *s, di_cdtext_t *cdt)
8781 {
8782 int i;
8783 char *cp = NULL;
8784
8785 if (cdinfo_dbp == NULL || cdt == NULL)
8786 return;
8787
8788 /* Disc artist and title */
8789 cdinfo_dbp->disc.artist = cdt->disc.performer;
8790 cdinfo_dbp->disc.title = cdt->disc.title;
8791 cdt->disc.performer = NULL;
8792 cdt->disc.title = NULL;
8793
8794 /* Media catalog number (UPC/MCN) */
8795 (void) strncpy(s->mcn, cdt->disc.catno, sizeof(s->mcn) - 1);
8796 s->mcn[sizeof(s->mcn) - 1] = '\0';
8797 MEM_FREE(cdt->disc.catno);
8798 cdt->disc.catno = NULL;
8799
8800 /* Disc identification, songwriter, composer, composer and message:
8801 * put in the notes field
8802 */
8803 if (cdt->ident != NULL) {
8804 cp = (char *) MEM_ALLOC("ident",
8805 strlen(cdt->ident) + 16
8806 );
8807 if (cp == NULL) {
8808 CDINFO_FATAL(app_data.str_nomemory);
8809 return;
8810 }
8811 (void) sprintf(cp, "Identification:\t%s\n", cdt->ident);
8812 MEM_FREE(cdt->ident);
8813 cdt->ident = NULL;
8814 }
8815 if (cdt->disc.songwriter != NULL) {
8816 if (cp == NULL) {
8817 cp = (char *) MEM_ALLOC("songwriter",
8818 strlen(cdt->disc.songwriter) + 16
8819 );
8820 if (cp == NULL) {
8821 CDINFO_FATAL(app_data.str_nomemory);
8822 return;
8823 }
8824 (void) sprintf(cp, "Songwriter:\t%s\n",
8825 cdt->disc.songwriter);
8826 }
8827 else {
8828 cp = (char *) MEM_REALLOC("songwriter", cp,
8829 strlen(cp) + strlen(cdt->disc.songwriter) + 16
8830 );
8831 if (cp == NULL) {
8832 CDINFO_FATAL(app_data.str_nomemory);
8833 return;
8834 }
8835 (void) sprintf(cp, "%sSongwriter:\t%s\n",
8836 cp, cdt->disc.songwriter);
8837 }
8838 MEM_FREE(cdt->disc.songwriter);
8839 cdt->disc.songwriter = NULL;
8840 }
8841 if (cdt->disc.composer != NULL) {
8842 if (cp == NULL) {
8843 cp = (char *) MEM_ALLOC("composer",
8844 strlen(cdt->disc.composer) + 16
8845 );
8846 if (cp == NULL) {
8847 CDINFO_FATAL(app_data.str_nomemory);
8848 return;
8849 }
8850 (void) sprintf(cp, "Composer:\t%s\n",
8851 cdt->disc.composer);
8852 }
8853 else {
8854 cp = (char *) MEM_REALLOC("composer", cp,
8855 strlen(cp) + strlen(cdt->disc.composer) + 16
8856 );
8857 if (cp == NULL) {
8858 CDINFO_FATAL(app_data.str_nomemory);
8859 return;
8860 }
8861 (void) sprintf(cp, "%sComposer:\t%s\n",
8862 cp, cdt->disc.composer);
8863 }
8864 MEM_FREE(cdt->disc.composer);
8865 cdt->disc.composer = NULL;
8866 }
8867 if (cdt->disc.arranger != NULL) {
8868 if (cp == NULL) {
8869 cp = (char *) MEM_ALLOC("arranger",
8870 strlen(cdt->disc.arranger) + 16
8871 );
8872 if (cp == NULL) {
8873 CDINFO_FATAL(app_data.str_nomemory);
8874 return;
8875 }
8876 (void) sprintf(cp, "Composer:\t%s\n",
8877 cdt->disc.arranger);
8878 }
8879 else {
8880 cp = (char *) MEM_REALLOC("arranger", cp,
8881 strlen(cp) + strlen(cdt->disc.arranger) + 16
8882 );
8883 if (cp == NULL) {
8884 CDINFO_FATAL(app_data.str_nomemory);
8885 return;
8886 }
8887 (void) sprintf(cp, "%sArranger:\t\t%s\n",
8888 cp, cdt->disc.arranger);
8889 }
8890 MEM_FREE(cdt->disc.arranger);
8891 cdt->disc.arranger = NULL;
8892 }
8893 if (cdt->disc.message != NULL) {
8894 if (cp == NULL) {
8895 cp = (char *) MEM_ALLOC("message",
8896 strlen(cdt->disc.message) + 16
8897 );
8898 if (cp == NULL) {
8899 CDINFO_FATAL(app_data.str_nomemory);
8900 return;
8901 }
8902 (void) sprintf(cp, "Composer:\t%s\n",
8903 cdt->disc.message);
8904 }
8905 else {
8906 cp = (char *) MEM_REALLOC("message", cp,
8907 strlen(cp) + strlen(cdt->disc.message) + 16
8908 );
8909 if (cp == NULL) {
8910 CDINFO_FATAL(app_data.str_nomemory);
8911 return;
8912 }
8913 (void) sprintf(cp, "%s\n%s\n",
8914 cp, cdt->disc.message);
8915 }
8916 MEM_FREE(cdt->disc.message);
8917 cdt->disc.message = NULL;
8918 }
8919
8920 cdinfo_dbp->disc.notes = cp;
8921
8922 for (i = 0; i < (int) s->tot_trks; i++) {
8923 /* Track artist, title and ISRC */
8924 cdinfo_dbp->track[i].artist = cdt->track[i].performer;
8925 cdinfo_dbp->track[i].title = cdt->track[i].title;
8926 cdinfo_dbp->track[i].isrc = cdt->track[i].catno;
8927
8928 cdt->track[i].performer = NULL;
8929 cdt->track[i].title = NULL;
8930 cdt->track[i].catno = NULL;
8931
8932 /* Track songwriter, composer, arranger and message:
8933 * put in the notes section.
8934 */
8935 cp = NULL;
8936
8937 if (cdt->track[i].songwriter != NULL) {
8938 cp = (char *) MEM_ALLOC("songwriter",
8939 strlen(cdt->track[i].songwriter) + 16
8940 );
8941 if (cp == NULL) {
8942 CDINFO_FATAL(app_data.str_nomemory);
8943 return;
8944 }
8945 (void) sprintf(cp, "Songwriter:\t%s\n",
8946 cdt->track[i].songwriter);
8947 MEM_FREE(cdt->track[i].songwriter);
8948 cdt->track[i].songwriter = NULL;
8949 }
8950 if (cdt->track[i].composer != NULL) {
8951 if (cp == NULL) {
8952 cp = (char *) MEM_ALLOC("composer",
8953 strlen(cdt->track[i].composer) + 16
8954 );
8955 if (cp == NULL) {
8956 CDINFO_FATAL(app_data.str_nomemory);
8957 return;
8958 }
8959 (void) sprintf(cp, "Composer:\t%s\n",
8960 cdt->track[i].composer);
8961 }
8962 else {
8963 cp = (char *) MEM_REALLOC("composer", cp,
8964 strlen(cp) +
8965 strlen(cdt->track[i].composer) + 16
8966 );
8967 if (cp == NULL) {
8968 CDINFO_FATAL(app_data.str_nomemory);
8969 return;
8970 }
8971 (void) sprintf(cp, "%sComposer:\t%s\n",
8972 cp, cdt->track[i].composer);
8973 }
8974 MEM_FREE(cdt->track[i].composer);
8975 cdt->track[i].composer = NULL;
8976 }
8977 if (cdt->track[i].arranger != NULL) {
8978 if (cp == NULL) {
8979 cp = (char *) MEM_ALLOC("arranger",
8980 strlen(cdt->track[i].arranger) + 16
8981 );
8982 if (cp == NULL) {
8983 CDINFO_FATAL(app_data.str_nomemory);
8984 return;
8985 }
8986 (void) sprintf(cp, "Composer:\t%s\n",
8987 cdt->track[i].arranger);
8988 }
8989 else {
8990 cp = (char *) MEM_REALLOC("arranger", cp,
8991 strlen(cp) +
8992 strlen(cdt->track[i].arranger) + 16
8993 );
8994 if (cp == NULL) {
8995 CDINFO_FATAL(app_data.str_nomemory);
8996 return;
8997 }
8998 (void) sprintf(cp, "%sArranger:\t%s\n",
8999 cp, cdt->track[i].arranger);
9000 }
9001 MEM_FREE(cdt->track[i].arranger);
9002 cdt->track[i].arranger = NULL;
9003 }
9004 if (cdt->track[i].message != NULL) {
9005 if (cp == NULL) {
9006 cp = (char *) MEM_ALLOC("message",
9007 strlen(cdt->track[i].message) + 16
9008 );
9009 if (cp == NULL) {
9010 CDINFO_FATAL(app_data.str_nomemory);
9011 return;
9012 }
9013 (void) sprintf(cp, "Composer:\t%s\n",
9014 cdt->track[i].message);
9015 }
9016 else {
9017 cp = (char *) MEM_REALLOC("message", cp,
9018 strlen(cp) +
9019 strlen(cdt->track[i].message) + 16
9020 );
9021 if (cp == NULL) {
9022 CDINFO_FATAL(app_data.str_nomemory);
9023 return;
9024 }
9025 (void) sprintf(cp, "%s\n%s\n",
9026 cp, cdt->track[i].message);
9027 }
9028 MEM_FREE(cdt->track[i].message);
9029 cdt->track[i].message = NULL;
9030 }
9031
9032 cdinfo_dbp->track[i].notes = cp;
9033 }
9034 }
9035
9036
9037