cddb.c (21691B)
1 /* --------------------------------------------------------------------- 2 basic cddb functions for XfreeCD 3 4 Copyright 1998 by Brian C. Lane 5 nexus@tatoosh.com 6 http://www.tatoosh.com/nexus 7 8 This program is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License 10 as published by the Free Software Foundation; either version 2 11 of the License, or (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 22 =============================[ HISTORY ]============================= 23 06/19/98 Adding write extended data to the database. DONE. 24 Switching to using g_malloc, g_free, g_realloc -- they're 25 safer than libc and can provide usage stats. 26 27 06/16/98 Need to add support for extended data lines. Split lines 28 too of course. This data needs to make it into the 29 database, and be able to send it to the server when 30 the CD is edited. 31 32 Revision # support needs to be added to. Read it and 33 increment it when the CD is submitted to the server. 34 FIXED. 35 36 06/06/98 I need to support split TTITLE lines, and get the 37 track # from the TTITLE line instead of assuming they 38 just go in order. 39 I found my garbage at the end of the file problem. If 40 A long file was written then it was shortened it 41 wouldn't erase it first, it would just write over 42 the top and leave the old stuff hanging off the end. 43 So I added an unlink to delete it first. 44 45 05/27/98 Adding creation of the cddb database directories if 46 they don't exist (only creates the ones that don't 47 exist). Added to write_cddb(). Only creates what it 48 needs to. This way it isn't limited to a static list of 49 categories. Works. 50 Found a bug. CDDB read/write don't handle multiple 51 DTITLEs very well. 52 53 05/16/98 Added expansion of ~/ to $HOME enviornmental variable 54 Added a local_cddb path in the cdinfo structure to point 55 to the local storage location for writing and reading 56 cd information. 57 58 05/11/98 Split off reading code to read_cddb_file so it can be 59 used to read a specific temporary file after the data 60 is downloaded from the server. 61 62 05/09/98 Started this part of the XfreeCD code. 63 Correct operation confirmed for discid using 64 Bryan Adams / Waking up the Neighbors id 0xce118c0f 65 Writing database entries works well so far, frames, 66 length, and discid are correct. Default track and title 67 strings are saved ok too. 68 find_discid works. 69 70 --------------------------------------------------------------------- 71 This file includes support for saving and loading local database 72 information. 73 --------------------------------------------------------------------- */ 74 #include <stdio.h> 75 #include <sys/types.h> 76 #include <unistd.h> 77 #include <sys/stat.h> 78 #include <fcntl.h> 79 #include <string.h> 80 #include <dirent.h> 81 #include <stdlib.h> 82 #include <errno.h> 83 #include <gtk/gtk.h> 84 #include "xfreecd.h" 85 #include "cd_control.h" 86 #include "cddb.h" 87 88 #undef DEBUG1 89 #undef DEBUG2 90 #undef DEBUG3 91 #undef DEBUG6 92 #undef DEBUG9 93 94 int 95 cddb_sum(int n) 96 { 97 char buf[12], 98 *p; 99 int ret = 0; 100 101 /* For backward compatibility this algorithm must not change */ 102 sprintf(buf, "%lu", n); 103 for (p = buf; *p != '\0'; p++) 104 ret += (*p - '0'); 105 106 return (ret); 107 } 108 109 unsigned long cddb_discid( struct CDINFO *cdinfo ) 110 { 111 int i, 112 t = 0, 113 n = 0, 114 tot_trks; 115 116 tot_trks = cdinfo->tochdr.cdth_trk1; 117 118 /* For backward compatibility this algorithm must not change */ 119 for (i = 0; i < tot_trks; i++) 120 n += cddb_sum((cdinfo->track[i].te.cdte_addr.msf.minute * 60) + cdinfo->track[i].te.cdte_addr.msf.second); 121 122 t = ((cdinfo->leadout.cdte_addr.msf.minute * 60) + cdinfo->leadout.cdte_addr.msf.second) - ((cdinfo->track[0].te.cdte_addr.msf.minute * 60) + cdinfo->track[0].te.cdte_addr.msf.second); 123 124 return ((n % 0xff) << 24 | t << 8 | tot_trks); 125 } 126 127 128 /* ------------------------------------------------------------------------- 129 Write the data from cdinfo structure to the correct file in the selected 130 category. 131 132 The master database directory is in cdinfo->local_cddb 133 134 How do I check for the same CD with a different ID so I can symlink? 135 136 if over is 0 then check to make sure the file doesn't already exist 137 if over is 1 then go ahead and overwrite it. 138 139 return -2 if the file already exists. 140 return -3 if the HOME variable cannot be found 141 return -4 if we had trouble creating the local cddb directories 142 ------------------------------------------------------------------------- */ 143 int write_cddb( struct CDINFO *cdinfo, int over ) 144 { 145 char fname[1024], 146 tmp_fname[1024], 147 tmpstr[255], 148 idstr[9], 149 *p; 150 int fd, 151 x, 152 i; 153 struct stat sbuf; 154 155 /* Copy the path to the local datbase to a temporary variable */ 156 strncpy( fname, cdinfo->local_cddb, 1023 ); 157 158 /* Convert a leading ~ into the user's HOME directory */ 159 if( fname[0] == '~' ) 160 { 161 /* Copy the reset of the path/filename to tmp_fname */ 162 strncpy( tmp_fname, &fname[1], 1023 ); 163 164 if( ( p = getenv("HOME") ) == NULL ) 165 { 166 return(-3); 167 } 168 strncpy( fname, p, 1023 ); 169 170 /* Make sure there is a slash inbetween */ 171 if( (fname[strlen(fname)-1] != '/') && (tmp_fname[0] != '/') ) 172 { 173 strcat( fname, "/" ); 174 } 175 176 strncat( fname, tmp_fname, 1023-strlen( p ) ); 177 } 178 179 #ifdef DEBUG1 180 g_print("write_cddb( %s )\n", fname ); 181 #endif 182 183 /* 184 See if we have the top level directory. If not, try to create it. 185 */ 186 if( stat( fname, &sbuf ) < 0 ) 187 { 188 /* If the top level directory doesn't exist, create it */ 189 if( errno == ENOENT ) 190 { 191 /* Try to make the top level directory, if it fails, quit */ 192 if( mkdir( fname, S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH | S_IROTH ) < 0 ) 193 { 194 return(-4); 195 } 196 } else { 197 return(-4); 198 } 199 } 200 201 202 /* Make sure we have slashes between the path and category directory */ 203 if( fname[strlen(fname)] != '/' ) 204 strcat( fname, "/" ); 205 strcat( fname, cdinfo->category->str ); 206 if( fname[strlen(fname)] != '/' ) 207 strcat( fname, "/" ); 208 209 /* 210 See if the category directory exists. If not, create it. 211 */ 212 if( stat( fname, &sbuf ) < 0 ) 213 { 214 /* If the top level directory doesn't exist, create it */ 215 if( errno == ENOENT ) 216 { 217 /* Try to make the category directory, if it fails, quit with an error*/ 218 if( mkdir( fname, S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH | S_IROTH ) < 0 ) 219 { 220 return(-4); 221 } 222 } else { 223 return(-4); 224 } 225 } 226 227 sprintf( idstr, "%08lx", cdinfo->discid ); 228 strcat( fname, idstr ); 229 230 /* Should we check for prior existance? */ 231 if( !over ) 232 { 233 if( ( fd = open( fname, O_RDONLY ) ) != -1 ) 234 { 235 close( fd ); 236 return(-2); 237 } 238 } 239 240 /* Make sure it is deleted */ 241 unlink( fname ); 242 243 if( ( fd = open( fname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ) ) < 0 ) 244 { 245 return(-1); 246 } 247 248 /* Write the cddb entry from the info in the cdinfostructure */ 249 sprintf( tmpstr, "# xmcd CD database file generated by XfreeCD %s\n", VERSION ); 250 251 if( write( fd, tmpstr, strlen( tmpstr) ) < 0 ) 252 { 253 close( fd ); 254 return(-1); 255 } 256 257 sprintf( tmpstr, "#\n# Track frame offsets:\n" ); 258 if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 ) 259 { 260 close( fd ); 261 return(-1); 262 } 263 264 /* Write the frame offset for each track */ 265 for( x = 0; x < cdinfo->tochdr.cdth_trk1; x++ ) 266 { 267 sprintf( tmpstr, "#\t%ld\n", cdinfo->track[x].frame_offset ); 268 if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 ) 269 { 270 close( fd ); 271 return(-1); 272 } 273 } 274 275 strcpy( tmpstr, "#\n" ); 276 if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 ) 277 { 278 close( fd ); 279 return(-1); 280 } 281 282 sprintf( tmpstr, "# Disc length: %d seconds\n#\n", cdinfo->cd_length ); 283 if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 ) 284 { 285 close( fd ); 286 return(-1); 287 } 288 289 sprintf( tmpstr, "# Revision: %d\n", cdinfo->revision ); 290 if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 ) 291 { 292 close( fd ); 293 return(-1); 294 } 295 296 sprintf( tmpstr, "# Submitted via: XfreeCD %s\n#\n", VERSION ); 297 if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 ) 298 { 299 close( fd ); 300 return(-1); 301 } 302 303 sprintf( tmpstr, "DISCID=%08lx\n", cddb_discid( cdinfo ) ); 304 if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 ) 305 { 306 close( fd ); 307 return(-1); 308 } 309 310 if( (cdinfo->title == NULL) || (cdinfo->title->len == 0) ) 311 { 312 if( write( fd, "DTITLE=\n", 8 ) < 0 ) 313 { 314 close( fd ); 315 return(-1); 316 } 317 } else { 318 /* If the title is too long, split it up into 70 byte chunks */ 319 i = 0; 320 p = cdinfo->title->str; 321 while( i < cdinfo->title->len ) 322 { 323 strcpy( tmpstr, "DTITLE=" ); 324 strncat( tmpstr, p, 70 ); 325 strcat( tmpstr, "\n" ); 326 327 if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 ) 328 { 329 close( fd ); 330 return(-1); 331 } 332 333 if( cdinfo->title->len > 70 ) 334 { 335 p = p + 70; 336 i += 70; 337 } else { 338 i = cdinfo->title->len; 339 } 340 } 341 } 342 343 /* Write the titles */ 344 for( x = 0; x < cdinfo->tochdr.cdth_trk1; x++ ) 345 { 346 if( (cdinfo->name[x] == NULL) || (cdinfo->name[x]->len == 0) ) 347 { 348 sprintf( tmpstr, "TTITLE%d=\n", x ); 349 if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 ) 350 { 351 close( fd ); 352 return(-1); 353 } 354 } else { 355 356 /* If the track name is too long, split it up into 70 byte chunks */ 357 i = 0; 358 p = cdinfo->name[x]->str; 359 while( i < cdinfo->name[x]->len ) 360 { 361 sprintf( tmpstr, "TTITLE%d=", x ); 362 strncat( tmpstr, p, 70 ); 363 strcat( tmpstr, "\n" ); 364 365 if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 ) 366 { 367 close( fd ); 368 return(-1); 369 } 370 371 if( cdinfo->name[x]->len > 70 ) 372 { 373 p = p + 70; 374 i += 70; 375 } else { 376 i = cdinfo->name[x]->len; 377 } 378 } 379 } 380 } 381 382 /* Check for a null entry first */ 383 if( (cdinfo->extd == NULL) || (cdinfo->extd->len == 0) ) 384 { 385 if( write( fd, "EXTD=\n", 6 ) < 0 ) 386 { 387 close( fd ); 388 return(-1); 389 } 390 } else { 391 /* Write the extended disc data to the file. It it is too long, break it 392 up into 70 byte chuncks 393 */ 394 i = 0; 395 p = cdinfo->extd->str; 396 while( i < cdinfo->extd->len ) 397 { 398 strcpy( tmpstr, "EXTD=" ); 399 strncat( tmpstr, p, 70 ); 400 strcat( tmpstr, "\n" ); 401 402 if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 ) 403 { 404 close( fd ); 405 return(-1); 406 } 407 408 if( cdinfo->extd->len > 70 ) 409 { 410 p = p + 70; 411 i += 70; 412 } else { 413 i = cdinfo->extd->len; 414 } 415 } 416 } 417 418 /* Write the extended title information to the database */ 419 for( x = 0; x < cdinfo->tochdr.cdth_trk1; x++ ) 420 { 421 if( (cdinfo->extt[x] == NULL) || (cdinfo->extt[x]->len == 0) ) 422 { 423 sprintf( tmpstr, "EXTT%d=\n", x ); 424 if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 ) 425 { 426 close( fd ); 427 return(-1); 428 } 429 } else { 430 /* If the track name is too long, split it up into 70 byte chunks */ 431 i = 0; 432 p = cdinfo->extt[x]->str; 433 while( i < cdinfo->extt[x]->len ) 434 { 435 sprintf( tmpstr, "EXTT%d=", x ); 436 strncat( tmpstr, p, 70 ); 437 strcat( tmpstr, "\n" ); 438 439 if( write( fd, tmpstr, strlen( tmpstr ) ) < 0 ) 440 { 441 close( fd ); 442 return(-1); 443 } 444 445 if( cdinfo->extt[x]->len > 70 ) 446 { 447 p = p + 70; 448 i += 70; 449 } else { 450 i = cdinfo->extt[x]->len; 451 } 452 } 453 } 454 } 455 456 /* XfreeCD doesn't use this at all */ 457 if( write( fd, "PLAYORDER=\n", 11 ) < 0 ) 458 { 459 close( fd ); 460 return(-1); 461 } 462 463 close( fd ); 464 465 return(0); 466 } 467 468 469 /* ----------------------------------------------------------------------- 470 Search all sub-directories below CDDB_PATH for the file to read 471 Fills in the category with the name of the trailing directory that 472 it is found in. 473 474 475 Return 0 on file found 476 Return -1 on an error 477 Return -2 on no file found 478 ----------------------------------------------------------------------- */ 479 int find_discid( char *fname, /* Path to local database */ 480 unsigned long id, /* discid to search for */ 481 char *path, /* Return full path */ 482 GString **category ) /* Return category found */ 483 { 484 DIR *dp; 485 struct dirent *dirp; 486 char idstr[9], 487 tmp_fname[1024], 488 *p; 489 int fp; 490 491 /* Convert a leading ~ into the user's HOME directory */ 492 if( fname[0] == '~' ) 493 { 494 /* Copy the reset of the path/filename to tmp_fname */ 495 strncpy( tmp_fname, &fname[1], 1023 ); 496 497 if( ( p = (char *) getenv("HOME") ) == NULL ) 498 { 499 return(-2); 500 } 501 strncpy( fname, p, 1023 ); 502 503 /* Make sure there is a slash inbetween the two */ 504 if( (fname[strlen(fname)-1] != '/') && (tmp_fname[0] != '/') ) 505 { 506 strcat( fname, "/" ); 507 } 508 509 strncat( fname, tmp_fname, 1023-strlen( p ) ); 510 } 511 512 #ifdef DEBUG1 513 g_print("find_discid( %s )\n", fname ); 514 #endif 515 516 517 sprintf( idstr, "%08lx", id ); 518 519 if( ( dp = opendir( fname ) ) == NULL ) 520 return(-1); 521 522 while( ( dirp = readdir( dp ) ) != NULL ) 523 { 524 if( (strcmp(dirp->d_name,"." )==0) || (strcmp(dirp->d_name, "..")==0) ) 525 continue; 526 527 strcpy( path, fname ); 528 if( path[strlen(path)] != '/' ) 529 strcat( path, "/" ); 530 strcat( path, dirp->d_name ); 531 if( path[strlen(path)] != '/' ) 532 strcat( path, "/" ); 533 strcat( path, idstr ); 534 535 /* Copy the directory name as the category name */ 536 if( *category == NULL ) 537 *category = g_string_new( dirp->d_name ); 538 else 539 *category = g_string_assign( *category, dirp->d_name ); 540 541 #ifdef DEBUG1 542 g_print("Checking %s\n", path ); 543 #endif 544 545 /* Does this file exist? */ 546 if( ( fp = open( path, O_RDONLY ) ) != -1 ) 547 { 548 close( fp ); 549 closedir( dp ); 550 return(0); 551 } 552 } 553 554 closedir( dp ); 555 556 return(-2); 557 } 558 559 560 /* ----------------------------------------------------------------------- 561 Read the CDDB info from a filename into a cdinfo structure 562 Allocate all needed string storage using gtk's g_string functions 563 564 return -2 = failed to find HOME enviornmental variable 565 ----------------------------------------------------------------------- */ 566 int read_cddb_file( char *fname, struct CDINFO *tmpinfo ) 567 { 568 int gotid, 569 i, 570 x, 571 f; 572 FILE *fp; 573 char line[255], 574 discid[9], 575 *p; 576 577 if( ( fp = fopen( fname, "r" ) ) == NULL ) 578 { 579 return(-1); 580 } 581 582 /* Read the cddb file, placing data into tmpinfo */ 583 if( fgets( line, 255, fp ) == NULL ) 584 { 585 fclose( fp ); 586 return(-1); 587 } 588 589 /* Check the file to make sure its a cddb file */ 590 if( strncmp( line, "# xmcd", 6 ) != 0 ) 591 { 592 fclose( fp ); 593 return(-1); 594 } 595 596 #ifdef DEBUG1 597 g_print("%s", line ); 598 #endif 599 600 /* Find the track offsets, abort serarch at the end of comments */ 601 while( ( line[0] == '#' ) && ( strncmp( line, "# Track frame offsets:",22 ) != 0 ) ) 602 { 603 if( fgets( line, 255, fp ) == NULL ) 604 { 605 fclose( fp ); 606 return(-1); 607 } 608 } 609 610 /* Skip all the reset of the comments up to Revision: */ 611 while( line[0] == '#' && (strncmp( line, "# Revision:", 11)!=0) ) 612 { 613 if( fgets( line, 255, fp ) == NULL ) 614 { 615 fclose( fp ); 616 return(-1); 617 } 618 } 619 620 /* If we got the Revision line, get the revision # */ 621 if( strncmp( line, "# Revision:", 11)==0 ) 622 { 623 sscanf( line, "# Revision: %d", &tmpinfo->revision ); 624 625 /* Now read the rest of the comments */ 626 while( line[0] == '#' ) 627 { 628 if( fgets( line, 255, fp ) == NULL ) 629 { 630 fclose( fp ); 631 return(-1); 632 } 633 } 634 } 635 636 /* Read discid lines */ 637 /* 638 How should this be handled? check for our id, and discard all others 639 that may be present? 640 641 DISCID= lines are comma seperated and can be multiple lines 642 */ 643 gotid = 0; 644 sprintf( discid, "%08lx", tmpinfo->discid ); 645 while( strncmp( line, "DISCID=", 7 ) == 0 ) 646 { 647 if( strstr( line, discid ) != NULL ) 648 gotid = 1; 649 if( fgets( line, 255, fp ) == NULL ) 650 { 651 fclose( fp ); 652 return(-1); 653 } 654 } 655 656 /* Process multiple DTITLE lines and concatanate them */ 657 i = 0; 658 f = 0; 659 while( strncmp( line, "DTITLE", 6 ) == 0 ) 660 { 661 p = strtok( line, "=\n" ); 662 p = strtok( NULL, "=\n" ); 663 664 /* Add the title to the tmpinfo.title string */ 665 if( f == 0 ) 666 { 667 tmpinfo->title = g_string_new( p ); 668 f = 1; 669 } else { 670 tmpinfo->title = g_string_append( tmpinfo->title, p ); 671 } 672 673 /* Keep reading DTITLE no matter what */ 674 if( fgets( line, 255, fp ) == NULL ) 675 { 676 fclose( fp ); 677 return(-1); 678 } 679 } 680 681 #ifdef DEBUG1 682 g_print("title read = %s\n", tmpinfo->title->str ); 683 #endif 684 685 /* 686 Copy the titles from the TTITLE strings 687 688 This has to: 689 Get the track # from the TTITLEx 690 strcat split title lines up to the limit of storage (255) 691 */ 692 x = -1; 693 f = 0; 694 while( strncmp( line, "TTITLE", 6 ) == 0 ) 695 { 696 /* Get the track # */ 697 p = strtok( &line[6], "=\n" ); 698 699 /* Is it a new track? */ 700 if( atoi(p) != x ) 701 { 702 /* Yes, reset the length counter and track name */ 703 i = 0; 704 f = 0; 705 tmpinfo->name[atoi(p)] = NULL; 706 } 707 708 /* Get the track number and make sure its not too big. */ 709 if( ( x = atoi( p ) ) < 99 ) 710 { 711 /* Get the track name */ 712 p = strtok( NULL, "=\n" ); 713 714 /* If its blank, then insert default track name */ 715 if( p == NULL ) 716 { 717 tmpinfo->name[x] = NULL; 718 } else { 719 if( f == 0 ) 720 { 721 tmpinfo->name[x] = g_string_new( p ); 722 f = 1; 723 } else { 724 tmpinfo->name[x] = g_string_append( tmpinfo->name[x], p ); 725 } 726 } 727 } 728 729 /* Read the next line */ 730 if( fgets( line, 255, fp ) == NULL ) 731 { 732 fclose( fp ); 733 return(-1); 734 } 735 } 736 737 738 /* Process multiple EXTD lines and concatanate them, dynamically 739 allocating memory at tmpinfo->extd for it 740 */ 741 i = 0; 742 f = 0; 743 tmpinfo->extd = NULL; 744 while( strncmp( line, "EXTD", 4 ) == 0 ) 745 { 746 /* Add to the data until the end is reached */ 747 p = strtok( line, "=\n" ); 748 p = strtok( NULL, "=\n" ); 749 750 if( p != NULL ) 751 { 752 /* Move the pointer and copy the new string */ 753 if( f == 0 ) 754 { 755 tmpinfo->extd = g_string_new( p ); 756 f = 1; 757 } else { 758 tmpinfo->extd = g_string_append( tmpinfo->extd, p ); 759 } 760 } 761 762 /* Keep reading lines */ 763 if( fgets( line, 255, fp ) == NULL ) 764 { 765 fclose( fp ); 766 return(-1); 767 } 768 } 769 770 771 /* 772 Copy the extended title data from the EXTTx entries 773 774 This has to: 775 Get the track # from the EXTTx 776 Allocate storage for it and copy it over, and handle multiple lines 777 for each track entry. 778 */ 779 x = -1; 780 f = 0; 781 while( strncmp( line, "EXTT", 4 ) == 0 ) 782 { 783 /* Get the track # */ 784 p = strtok( &line[4], "=\n" ); 785 786 /* Is it a new track? */ 787 if( atoi(p) != x ) 788 { 789 /* Yes, reset the length counter and track name */ 790 i = 0; 791 f = 0; 792 tmpinfo->extt[atoi(p)] = NULL; 793 } 794 795 /* Get the track number, make sure it isn't too big */ 796 if( ( x = atoi( p ) ) < 99 ) 797 { 798 /* Get the extended data from the rest of the line*/ 799 p = strtok( NULL, "=\n" ); 800 801 /* Process multiple EXTT lines and concatanate them, dynamicly 802 allocating memory at tmpinfo->extd for it 803 */ 804 if( p != NULL ) 805 { 806 /* Move the pointer and copy the new string */ 807 if( f == 0 ) 808 { 809 tmpinfo->extt[x] = g_string_new( p ); 810 f = 1; 811 } else { 812 tmpinfo->extt[x] = g_string_append( tmpinfo->extt[x], p ); 813 } 814 } 815 } 816 817 /* Read the next line */ 818 if( fgets( line, 255, fp ) == NULL ) 819 { 820 fclose( fp ); 821 return(-1); 822 } 823 } 824 825 fclose( fp ); 826 827 return(0); 828 } 829 830 831 /* ----------------------------------------------------------------------- 832 Read a cddb entry for the current CD 833 834 This needs to search through the sub-directories in CDDB_PATH to find 835 the discid of the current CD. 836 837 We then read the file, filling in the track names, etc. 838 We should also compare the frame count to make sure it is the 839 correct CD. 840 841 Returns -1 if there was an error 842 Returns -2 if it cannot find the file 843 ----------------------------------------------------------------------- */ 844 int read_cddb( struct CDINFO *cdinfo ) 845 { 846 int x; 847 char fname[255]; 848 struct CDINFO tmpinfo; 849 850 /* Clean out the structure */ 851 bzero( &tmpinfo, sizeof( struct CDINFO ) ); 852 853 tmpinfo.discid = cdinfo->discid; 854 855 /* Find out where this ID lives and fill in fname with full name */ 856 if( find_discid( cdinfo->local_cddb, tmpinfo.discid, fname, &tmpinfo.category ) < 0 ) 857 { 858 /* Could not find an entry for this */ 859 return(-2); 860 } 861 862 if( read_cddb_file( fname, &tmpinfo ) == 0 ) 863 { 864 cdinfo->title = tmpinfo.title; 865 for( x = 0; x < cdinfo->tochdr.cdth_trk1; x++ ) 866 { 867 cdinfo->name[x] = tmpinfo.name[x]; 868 } 869 870 /* Copy the category over too */ 871 cdinfo->category = tmpinfo.category; 872 873 /* Copy the revision # over if it is valid */ 874 if( tmpinfo.revision >= 0 ) 875 cdinfo->revision = tmpinfo.revision; 876 else 877 cdinfo->revision = 1; 878 879 /* Copy the extd pointer over */ 880 cdinfo->extd = tmpinfo.extd; 881 882 /* Copy all the extended track pointers */ 883 for( x = 0; x < 99; x++ ) 884 cdinfo->extt[x] = tmpinfo.extt[x]; 885 } 886 887 return(0); 888 }