toc.c
上传用户:xiejiait
上传日期:2007-01-06
资源大小:881k
文件大小:69k
源码类别:

SCSI/ASPI

开发平台:

MultiPlatform

  1. /* @(#)toc.c 1.3 00/01/11 Copyright 1998,1999 Heiko Eissfeldt */
  2. #ifndef lint
  3. static char     sccsid[] =
  4. "@(#)toc.c 1.3 00/01/11 Copyright 1998,1999 Heiko Eissfeldt";
  5. #endif
  6. /*
  7.  * Copyright: GNU Public License 2 applies
  8.  *
  9.  *   This program is free software; you can redistribute it and/or modify
  10.  *   it under the terms of the GNU General Public License as published by
  11.  *   the Free Software Foundation; either version 2, or (at your option)
  12.  *   any later version.
  13.  *
  14.  *   This program is distributed in the hope that it will be useful,
  15.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  *   GNU General Public License for more details.
  18.  *
  19.  *   You should have received a copy of the GNU General Public License
  20.  *   along with this program; if not, write to the Free Software
  21.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  *
  23.  * CDDA2WAV (C) Heiko Eissfeldt heiko@colossus.escape.de
  24.  * CDDB routines (C) Ti Kan and Steve Scherf
  25.  */
  26. #include "config.h"
  27. #include <stdio.h>
  28. #include <standard.h>
  29. #include <stdlib.h>
  30. #include <strdefs.h>
  31. #if defined (HAVE_UNISTD_H) && (HAVE_UNISTD_H == 1)
  32. #include <sys/types.h>
  33. #include <unistd.h> /* sleep */
  34. #endif
  35. #include <ctype.h>
  36. #include <errno.h>
  37. #include <fcntl.h>
  38. #include <sys/ioctl.h>
  39. #define CD_TEXT
  40. #define CD_EXTRA
  41. #undef DEBUG_XTRA
  42. #undef DEBUG_CDTEXT
  43. #include <scg/scsitransp.h>
  44. #include "mytype.h"
  45. #include "byteorder.h"
  46. #include "interface.h"
  47. #include "cdda2wav.h"
  48. #include "global.h"
  49. #include "sha.h"
  50. #include "base64.h"
  51. #include "toc.h"
  52. #include "ringbuff.h"
  53. int have_CD_text;
  54. int have_CD_extra;
  55. static void UpdateTrackData __PR((int p_num));
  56. static void UpdateIndexData __PR((int p_num));
  57. static void UpdateTimeData __PR((int p_min, int p_sec, int p_frm));
  58. static unsigned int is_cd_extra __PR((unsigned int no_tracks));
  59. static unsigned int get_end_of_last_audio_track __PR((unsigned int mult_off, unsigned int no_tracks));
  60. static int cddb_sum __PR((int n));
  61. static void emit_cddb_form __PR((char *fname_baseval));
  62. static void emit_cdindex_form __PR((char *fname_baseval));
  63. static void dump_extra_info __PR((unsigned int from));
  64. static int GetIndexOfSector __PR((unsigned int sec, unsigned track));
  65. static int linear_search __PR((int searchInd, unsigned int Start, unsigned int End, unsigned track));
  66. static int binary_search __PR((int searchInd, unsigned int Start, unsigned int End, unsigned track));
  67. static unsigned char g_track=0xff, g_index=0xff; /* current track, index */
  68. static unsigned char g_minute=0xff, g_seconds=0xff; /* curr. minute, second */
  69. static unsigned char g_frame=0xff; /* current frame */
  70. /* print the track currently read */
  71. static void UpdateTrackData (p_num)
  72. int p_num;
  73. {
  74.   if (global.quiet == 0) { 
  75.     fprintf (stderr, "ntrack: %.2d, ", p_num); fflush(stderr);
  76.   }
  77.   g_track = (unsigned char) p_num;
  78. }
  79. /* print the index currently read */
  80. static void UpdateIndexData (p_num)
  81. int p_num;
  82. {
  83.   if (global.quiet == 0) { 
  84.     fprintf (stderr, "index: %.2dn", p_num); fflush(stderr);
  85.   }
  86.   g_index = (unsigned char) p_num;
  87. }
  88. /* print the time of track currently read */
  89. static void UpdateTimeData (p_min, p_sec, p_frm)
  90. int p_min;
  91. int p_sec;
  92. int p_frm;
  93. {
  94.   if (global.quiet == 0) {
  95.     fprintf (stderr, "time: %.2d:%.2d.%.2dr", p_min, p_sec, p_frm); 
  96.     fflush(stderr);
  97.   }
  98.   g_minute = (unsigned char) p_min;
  99.   g_seconds = (unsigned char) p_sec;
  100.   g_frame = (unsigned char) p_frm;
  101. }
  102. void AnalyzeQchannel ( frame )
  103. unsigned frame;
  104. {
  105.     subq_chnl *sub_ch;
  106.     if (trackindex_disp != 0) {
  107. sub_ch = ReadSubQ(get_scsi_p(), GET_POSITIONDATA,0);
  108. /* analyze sub Q-channel data */
  109. if (sub_ch->track != g_track ||
  110.     sub_ch->index != g_index) {
  111.     UpdateTrackData (sub_ch->track);
  112.     UpdateIndexData (sub_ch->index);
  113. }
  114.     }
  115.     frame += 150;
  116.     UpdateTimeData ((unsigned char) (frame / (60*75)), 
  117.     (unsigned char) ((frame % (60*75)) / 75), 
  118.     (unsigned char) (frame % 75));
  119. }
  120. unsigned cdtracks = 0;
  121. long GetStartSector ( p_track )
  122. unsigned long p_track;
  123. {
  124.   unsigned long i;
  125.   for (i = 0; i < cdtracks; i++) {
  126.     if (g_toc [i].bTrack == p_track) {
  127.       unsigned long dw = g_toc [i].dwStartSector;
  128.       if ((g_toc [i].bFlags & CDROM_DATA_TRACK) != 0)
  129. return -1;
  130.       return dw;
  131.     }
  132.   }
  133.   return -1;
  134. }
  135. long GetEndSector ( p_track )
  136. unsigned long p_track;
  137. {
  138.   unsigned long i;
  139.   for ( i = 1; i <= cdtracks; i++ ) {
  140.     if ( g_toc [i-1].bTrack == p_track ) {
  141.       unsigned long dw = g_toc [i].dwStartSector;
  142.       return dw-1;
  143.     }
  144.   }
  145.   return -1;
  146. }
  147. long FirstTrack ( )
  148. {
  149.   return g_toc[0].bTrack;
  150. }
  151. long FirstAudioTrack ( )
  152. {
  153.   unsigned long i;
  154.   
  155.   for ( i = 0; i < cdtracks; i++ ) {
  156.     if ( g_toc [i].bTrack != CDROM_LEADOUT &&
  157. ( g_toc [i].bFlags & CDROM_DATA_TRACK ) == 0 )
  158.       return g_toc [i].bTrack;
  159.   }
  160.   return 0;
  161. }
  162. long LastTrack ( )
  163. {
  164.   return g_toc[cdtracks-1].bTrack;
  165. }
  166. long LastAudioTrack ( )
  167. {
  168.   unsigned i;
  169.   long j = -1;
  170.   for ( i = 0; i < cdtracks; i++ ) {
  171.     if ( g_toc [i].bTrack != CDROM_LEADOUT &&
  172. ( g_toc [i].bFlags & CDROM_DATA_TRACK ) == 0 )
  173.       j = g_toc [i].bTrack;
  174.   }
  175.   return j;
  176. }
  177. long GetLastSectorOnCd( p_track )
  178. unsigned long p_track;
  179. {
  180.   unsigned long i;
  181.   long LastSec = 0;
  182.   for ( i = 1; i <= cdtracks; i++ ) {
  183.     if ( g_toc [i-1].bTrack < p_track )
  184.       continue;
  185.     /* break if a nonaudio track follows */
  186.     if ( (g_toc [i-1].bFlags & CDROM_DATA_TRACK) != 0) break;
  187.     LastSec = GetEndSector ( g_toc [i-1].bTrack ) + 1;
  188.   }
  189.   return LastSec;
  190. }
  191. int GetTrack( sector )
  192. unsigned long sector;
  193. {
  194.   unsigned long i;
  195.   for (i = 0; i < cdtracks; i++) {
  196.     if (g_toc[i  ].dwStartSector <= sector &&
  197. g_toc[i+1].dwStartSector > sector)
  198.       return (g_toc [i].bFlags & CDROM_DATA_TRACK) != 0 ? -1 : (int)(i+1);
  199.   }
  200.   return -1;
  201. }
  202. int CheckTrackrange( from, upto )
  203. unsigned long from;
  204. unsigned long upto;
  205. {
  206.   unsigned long i;
  207.   for ( i = 1; i <= cdtracks; i++ ) {
  208.     if ( g_toc [i-1].bTrack < from )
  209.       continue;
  210.     if ( g_toc [i-1].bTrack == upto )
  211.       return 1;
  212.     /* break if a nonaudio track follows */
  213.     if ( (g_toc [i-1].bFlags & CDROM_DATA_TRACK) != 0)
  214.       return 0;
  215.   }
  216.   /* track not found */
  217.   return 0;
  218. }
  219. unsigned
  220. find_an_off_sector __PR((unsigned lSector, unsigned SectorBurstVal));
  221. unsigned find_an_off_sector(lSector, SectorBurstVal)
  222. unsigned lSector;
  223. unsigned SectorBurstVal;
  224. {
  225. long track_of_start = GetTrack(lSector);
  226. long track_of_end = GetTrack(lSector + SectorBurstVal -1);
  227. long start = GetStartSector(track_of_start);
  228. long end = GetEndSector(track_of_end);
  229. if (lSector - start > end - lSector + SectorBurstVal -1)
  230. return start;
  231. else
  232. return end;
  233. }
  234. #ifdef CD_TEXT
  235. #include "scsi_cmds.h"
  236. #endif
  237. int   handle_cdtext __PR(( void ));
  238. int   handle_cdtext ()
  239. {
  240. #ifdef CD_TEXT
  241. if (bufferTOC[0] == 0 && bufferTOC[1] == 0) {
  242. have_CD_text = 0;
  243. return have_CD_text;
  244. }
  245. /* do a quick scan over all pack type indicators */
  246. {
  247. int i;
  248. int count_fails = 0;
  249. int len = (bufferTOC[0] << 8) | bufferTOC[1];
  250. len = min(len, 2048);
  251. for (i = 0; i < len-4; i += 18) {
  252. if (bufferTOC[4+i] < 0x80 || bufferTOC[4+i] > 0x8f) {
  253. count_fails++;
  254. }
  255. }
  256. have_CD_text = count_fails < 3;
  257. }
  258. #else
  259. have_CD_text = 0;
  260. #endif
  261. return have_CD_text;
  262. }
  263. #ifdef CD_TEXT
  264. /**************** CD-Text special treatment **********************************/
  265. typedef struct {
  266. unsigned char headerfield[4];
  267. unsigned char textdatafield[12];
  268. unsigned char crcfield[2];
  269. } cdtextpackdata;
  270. static unsigned short crctab[1<<8] = { /* as calculated by initcrctab() */
  271.     0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
  272.     0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
  273.     0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
  274.     0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
  275.     0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
  276.     0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
  277.     0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
  278.     0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
  279.     0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
  280.     0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
  281.     0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
  282.     0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
  283.     0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
  284.     0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
  285.     0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
  286.     0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
  287.     0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
  288.     0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
  289.     0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
  290.     0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
  291.     0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
  292.     0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
  293.     0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
  294.     0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
  295.     0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
  296.     0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
  297.     0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
  298.     0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
  299.     0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
  300.     0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
  301.     0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
  302.     0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0,
  303.     };
  304. #undef SLOWER_CRC
  305. #define SUBSIZE 18*8
  306. static unsigned short updcrc __PR((
  307.     unsigned int    p_crc,
  308.             register unsigned char   *cp,
  309.             register size_t  cnt));
  310. static unsigned short updcrc(p_crc, cp, cnt)
  311. unsigned int p_crc;
  312.         register unsigned char   *cp;
  313.         register size_t  cnt;
  314. {
  315.       register unsigned short crc = p_crc;
  316.       while( cnt-- ) {
  317. #ifdef SLOWERCRC
  318.             crc = (crc<<8) ^ crctab[(crc>>(16-8)) ^ ~(*cp++)];
  319. #else
  320.             crc = (crc<<8) ^ crctab[(crc>>(16-8)) ^ (*cp++)];
  321. #endif
  322.       }
  323.       return( crc );
  324. }
  325. static unsigned short calcCRC __PR((unsigned char *buf, unsigned bsize));
  326. static unsigned short calcCRC(buf, bsize)
  327. unsigned char *buf;
  328. unsigned bsize;
  329. {
  330. #ifdef SLOWERCRC
  331.       return updcrc( 0x0, (unsigned char *)buf, bsize );
  332. #else
  333.       return updcrc( 0x0, (unsigned char *)buf, bsize ) ^ 0x1d0f;
  334. #endif
  335. }
  336. unsigned char    fliptab[8] = {
  337.         0x01,
  338.         0x02,
  339.         0x04,
  340.         0x08,
  341.         0x10,
  342.         0x20,
  343.         0x40,
  344.         0x80,
  345. };
  346. static int flip_error_corr __PR((unsigned char *b, int crc));
  347. static int flip_error_corr(b, crc)
  348. unsigned char *b;
  349. int crc;
  350. {
  351.   if (crc != 0) {
  352.     int i;
  353.     for (i = 0; i < SUBSIZE; i++) {
  354.       char      c;
  355.       c = fliptab[i%8];
  356.       b[i / 8] ^= c;
  357.       if ((crc = calcCRC(b, SUBSIZE/8)) == 0) {
  358.         return crc;
  359.       }
  360.       b[i / 8] ^= c;
  361.     }
  362.   }
  363.   return crc & 0xffff;
  364. }
  365. static int cdtext_crc_ok __PR((cdtextpackdata *c));
  366. static int cdtext_crc_ok (c)
  367. cdtextpackdata *c;
  368. {
  369. int crc;
  370. crc = calcCRC(((unsigned char *)c), 18);
  371. return 0 == flip_error_corr((unsigned char *)c, crc);
  372. }
  373. static void dump_binary __PR((cdtextpackdata *c));
  374. static void dump_binary(c)
  375. cdtextpackdata *c;
  376. {
  377.           fprintf(stderr, ": header fields %02x %02x %02x  ",
  378.                           c->headerfield[1], c->headerfield[2], c->headerfield[3]);
  379.           fprintf(stderr,
  380. "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x"
  381.                         , c->textdatafield[0]
  382.                         , c->textdatafield[1]
  383.                         , c->textdatafield[2]
  384.                         , c->textdatafield[3]
  385.                         , c->textdatafield[4]
  386.                         , c->textdatafield[5]
  387.                         , c->textdatafield[6]
  388.                         , c->textdatafield[7]
  389.                         , c->textdatafield[8]
  390.                         , c->textdatafield[9]
  391.                         , c->textdatafield[10]
  392.                         , c->textdatafield[11]
  393.                  );
  394. }
  395. #define DETAILED 0
  396. static int process_header __PR((cdtextpackdata *c, int dbcc, unsigned char *line));
  397. static int process_header(c, dbcc, line)
  398. cdtextpackdata *c;
  399. int dbcc;
  400. unsigned char *line;
  401. {
  402.       switch ((int)c->headerfield[0]) {
  403.         case 0x80: /* Title of album or track */
  404.           if (DETAILED) fprintf (stderr, "Title");
  405.   if (c->headerfield[1] > 0 && c->headerfield[1] < 100
  406.     && global.tracktitle[c->headerfield[1]-1] == NULL) {
  407.     unsigned len;
  408.     len = strlen((char *)line);
  409.             if (len > 0)
  410.              global.tracktitle[c->headerfield[1]-1] = (unsigned char *) malloc(len + 1);
  411.             if (global.tracktitle[c->headerfield[1]-1] != NULL) {
  412.                memcpy(global.tracktitle[c->headerfield[1]-1], line, len);
  413.                global.tracktitle[c->headerfield[1]-1][len] = '';
  414.             }
  415.           } else 
  416.   if (c->headerfield[1] == 0
  417.     && global.disctitle == NULL) {
  418.     unsigned len;
  419.     len = strlen((char *)line);
  420.             if (len > 0)
  421.              global.disctitle = (unsigned char *) malloc(len + 1);
  422.             if (global.disctitle != NULL) {
  423.                memcpy(global.disctitle, line, len);
  424.                global.disctitle[len] = '';
  425.             }
  426.   }
  427.         break;
  428.         case 0x81: /* Name(s) of the performer(s) */
  429.           if (DETAILED) fprintf(stderr, "Performer(s)");
  430.   if (c->headerfield[1] > 0 && c->headerfield[1] < 100
  431.     && global.trackcreator[c->headerfield[1]-1] == NULL) {
  432.     unsigned len;
  433.     len = strlen((char *)line);
  434.             if (len > 0)
  435. global.trackcreator[c->headerfield[1]-1] = (unsigned char *) malloc(len + 1);
  436.             if (global.trackcreator[c->headerfield[1]-1] != NULL) {
  437.                memcpy(global.trackcreator[c->headerfield[1]-1], line, len);
  438.                global.trackcreator[c->headerfield[1]-1][len] = '';
  439.             }
  440.           } else 
  441.   if (c->headerfield[1] == 0
  442.     && global.creator == NULL) {
  443.     unsigned len;
  444.     len = strlen((char *)line);
  445.             if (len > 0)
  446.              global.creator = (unsigned char *) malloc(len + 1);
  447.             if (global.creator != NULL) {
  448.                memcpy(global.creator, line, len);
  449.                global.creator[len] = '';
  450.             }
  451.   }
  452.         break;
  453.         case 0x82: /* Name(s) of the songwriter(s) */
  454.           if (DETAILED) fprintf(stderr, "Songwriter(s)");
  455.         break;
  456.         case 0x83: /* Name(s) of the composer(s) */
  457.           if (DETAILED) fprintf(stderr, "Composer(s)");
  458.         break;
  459.         case 0x84: /* Name(s) of the arranger(s) */
  460.           if (DETAILED) fprintf(stderr, "Arranger(s)");
  461.         break;
  462.         case 0x85: /* Message from content provider and/or artist */
  463.           if (DETAILED) fprintf(stderr, "Message");
  464.         break;
  465.         case 0x86: /* Disc Identification and information */
  466.           if (DETAILED) fprintf(stderr, "Disc identification");
  467.         break;
  468.         case 0x87: /* Genre Identification and information */
  469.           if (DETAILED) fprintf(stderr, "Genre identification");
  470.         break;
  471.         case 0x8e: /* UPC/EAN code or ISRC code */
  472.           if (DETAILED) fprintf(stderr, "UPC or ISRC");
  473.   if (c->headerfield[1] > 0 && c->headerfield[1] < 100) {
  474.     memcpy(g_toc[c->headerfield[1]-1].ISRC, line, sizeof(g_toc[0].ISRC));
  475.   } else
  476.   if (c->headerfield[1] == 0) {
  477.     memcpy((char *)MCN, line, 13);
  478.     MCN[13] = '';
  479.   }
  480.         break;
  481.         case 0x88: /* Table of Content information */
  482.           if (DETAILED) fprintf(stderr, "Table of Content identification");
  483.   if (DETAILED) dump_binary(c); 
  484.         return 0;
  485.         case 0x89: /* Second Table of Content information */
  486.           if (DETAILED) fprintf(stderr, "Second Table of Content identification");
  487.   if (DETAILED) dump_binary(c); 
  488.         return 0;
  489.         case 0x8f: /* Size information of the block */
  490.   if (!(DETAILED)) break;
  491.           switch (c->headerfield[1]) {
  492.     case 0:
  493.   fprintf(stderr, "first track is %d, last track is %dn", 
  494. c->textdatafield[1],
  495. c->textdatafield[2]);
  496.   if (c->textdatafield[3] & 0x80) {
  497. fprintf(stderr, "Program Area CD Text information availablen");
  498.         if (c->textdatafield[3] & 0x40) {
  499.   fprintf(stderr, "Program Area copy protection availablen");
  500.         }
  501.   }
  502.   if (c->textdatafield[3] & 0x07) {
  503. fprintf(stderr, "message information is %scopyrightedn", 
  504. c->textdatafield[3] & 0x04 ? "": "not ");
  505. fprintf(stderr, "Names of performer/songwriter/composer/arranger(s) are %scopyrightedn", 
  506. c->textdatafield[3] & 0x02 ? "": "not ");
  507. fprintf(stderr, "album and track names are %scopyrightedn", 
  508. c->textdatafield[3] & 0x01 ? "": "not ");
  509.   }
  510.   fprintf(stderr, "%d packs with album/track namesn", c->textdatafield[4]);
  511.   fprintf(stderr, "%d packs with performer namesn", c->textdatafield[5]);
  512.   fprintf(stderr, "%d packs with songwriter namesn", c->textdatafield[6]);
  513.   fprintf(stderr, "%d packs with composer namesn", c->textdatafield[7]);
  514.   fprintf(stderr, "%d packs with arranger namesn", c->textdatafield[8]);
  515.   fprintf(stderr, "%d packs with artist or content provider messagesn", c->textdatafield[9]);
  516.   fprintf(stderr, "%d packs with disc identification informationn", c->textdatafield[10]);
  517.   fprintf(stderr, "%d packs with genre identification/informationn", c->textdatafield[11]);
  518.   break;
  519. case 1:
  520.   fprintf(stderr, "%d packs with table of contents informationn", c->textdatafield[0]);
  521.   fprintf(stderr, "%d packs with second table of contents informationn", c->textdatafield[1]);
  522.   fprintf(stderr, "%d packs with reserved informationn", c->textdatafield[2]);
  523.   fprintf(stderr, "%d packs with reserved informationn", c->textdatafield[3]);
  524.   fprintf(stderr, "%d packs with reserved informationn", c->textdatafield[4]);
  525.   fprintf(stderr, "%d packs with closed informationn", c->textdatafield[5]);
  526.   fprintf(stderr, "%d packs with UPC/EAN ISRC informationn", c->textdatafield[6]);
  527.   fprintf(stderr, "%d packs with size informationn", c->textdatafield[7]);
  528.   fprintf(stderr, "last sequence numbers for blocks 1-8: %d %d %d %d "
  529.  ,c->textdatafield[8]
  530.  ,c->textdatafield[9]
  531.  ,c->textdatafield[10]
  532.  ,c->textdatafield[11]
  533. );
  534.   break;
  535. case 2:
  536.   fprintf(stderr, "%d %d %d %dn"
  537.  ,c->textdatafield[0]
  538.  ,c->textdatafield[1]
  539.  ,c->textdatafield[2]
  540.  ,c->textdatafield[3]
  541. );
  542.   fprintf(stderr, "Language codes for blocks 1-8: %d %d %d %d %d %d %d %dn"
  543.  ,c->textdatafield[4]
  544.  ,c->textdatafield[5]
  545.  ,c->textdatafield[6]
  546.  ,c->textdatafield[7]
  547.  ,c->textdatafield[8]
  548.  ,c->textdatafield[9]
  549.  ,c->textdatafield[10]
  550.  ,c->textdatafield[11]
  551. );
  552.   break;
  553.         }
  554.           if (DETAILED) fprintf(stderr, "Blocksize");
  555.   if (DETAILED) dump_binary(c); 
  556.         return 0;
  557. #if !defined DEBUG_CDTEXT
  558.         default:
  559. #else
  560.       }
  561. #endif
  562.           if (DETAILED) fprintf(stderr, ": header fields %02x %02x %02x  ",
  563.                           c->headerfield[1], c->headerfield[2], c->headerfield[3]);
  564. #if !defined DEBUG_CDTEXT
  565.       }
  566.       if (c->headerfield[1] == 0) {
  567.             if (DETAILED) fprintf(stderr, " for album   : ->");
  568.       } else {
  569.             if (DETAILED) fprintf(stderr, " for track %2u: ->", c->headerfield[1]);
  570.       }
  571.       if (DETAILED) fputs ((char *) line, stderr);
  572.       if (DETAILED) fputs ("<-", stderr);
  573.       if (dbcc != 0) {
  574. #else
  575.       {
  576. #endif
  577.           if (DETAILED) fprintf(stderr,
  578. "  %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x"
  579.                         , c->textdatafield[0]
  580.                         , c->textdatafield[1]
  581.                         , c->textdatafield[2]
  582.                         , c->textdatafield[3]
  583.                         , c->textdatafield[4]
  584.                         , c->textdatafield[5]
  585.                         , c->textdatafield[6]
  586.                         , c->textdatafield[7]
  587.                         , c->textdatafield[8]
  588.                         , c->textdatafield[9]
  589.                         , c->textdatafield[10]
  590.                         , c->textdatafield[11]
  591.                  );
  592.       }
  593.       return 0;
  594. }
  595. #endif
  596. #if defined CDROMMULTISESSION
  597. static int tmp_fd;
  598. #endif
  599. #ifdef CD_EXTRA
  600. /**************** CD-Extra special treatment *********************************/
  601. static unsigned char Extra_buffer[CD_FRAMESIZE_RAW];
  602. static int Read_CD_Extra_Info __PR(( unsigned long sector));
  603. static int Read_CD_Extra_Info(sector)
  604. unsigned long sector;
  605. {
  606.   unsigned i;
  607.   static int offsets[] = {
  608.      75,  /* this is observed for 12 cm discs */
  609.      60 }; /* this has been observed for 5 cm disks */
  610.   for (i = 0; i < sizeof(offsets)/sizeof(int); i++) {
  611. #ifdef DEBUG_XTRA
  612.     fprintf(stderr, "debug: Read_CD_Extra_Info at sector %lun", sector+offsets[i]);
  613. #endif
  614.     ReadCdRomData(get_scsi_p(), Extra_buffer, sector+offsets[i], 1);
  615.     /* If we are unlucky the drive cannot handle XA sectors by default.
  616.        We try to compensate by ignoring the first eight bytes.
  617.        Of course then we lack the last 8 bytes of the sector...
  618.      */
  619. #ifdef DEBUG_XTRA
  620.     { int ijk;
  621.       for (ijk = 0; ijk < 96; ijk++) {
  622.         fprintf(stderr, "%02x  ", Extra_buffer[ijk]);
  623.         if ((ijk+1) % 16 == 0) fprintf(stderr, "n");
  624.       }
  625.     } 
  626. #endif
  627.     if (Extra_buffer[0] == 0)
  628.       movebytes(Extra_buffer +8, Extra_buffer, CD_FRAMESIZE - 8);
  629.     /* check for cd extra */
  630.     if (Extra_buffer[0] == 'C' && Extra_buffer[1] == 'D')
  631. return sector+offsets[i];
  632.   }
  633.   return 0;
  634. }
  635. static void Read_Subinfo __PR(( unsigned pos, unsigned length));
  636. static void Read_Subinfo(pos, length)
  637. unsigned pos;
  638. unsigned length;
  639. {
  640.   unsigned num_infos, num;
  641.   unsigned char *Subp, *orgSubp;
  642.   unsigned this_track = 0xff;
  643. #ifdef DEBUG_XTRA
  644.   unsigned char *up;
  645.   unsigned char *sp;
  646.   unsigned u;
  647.   unsigned short s;
  648. #endif
  649.   length += 8;
  650.   length = (length + CD_FRAMESIZE_RAW-1) / CD_FRAMESIZE_RAW;
  651.   length *= CD_FRAMESIZE_RAW;
  652.   orgSubp = Subp = (unsigned char *) malloc(length);
  653.   if (Subp == NULL) {
  654.     fprintf(stderr, "Read_Subinfo alloc error(%d)n",length);
  655.     goto errorout;
  656.   }
  657.   ReadCdRomData(get_scsi_p(), Subp, pos, 1);
  658.   num_infos = Subp[45]+(Subp[44] << 8);
  659. #ifdef DEBUG_XTRA
  660.   fprintf(stderr, "subinfo version %c%c.%c%c, %d info packetsn",
  661.   Subp[8],
  662.   Subp[9],
  663.   Subp[10],
  664.   Subp[11],
  665.   num_infos);
  666. #endif
  667.   length -= 46;
  668.   Subp += 46;
  669.   for (num = 0; num < num_infos && length > 0; num++) {
  670.     static const char *infopacketID[] = { "0", 
  671.       "track identifier", 
  672.       "album title",
  673.       "universal product code", 
  674.       "international standard book number",
  675.       "copyright",
  676.       "track title",
  677.       "notes",
  678.       "main interpret",
  679.       "secondary interpret",
  680.       "composer",
  681.       "original composer",
  682.       "creation date",
  683.       "release  date",
  684.       "publisher",
  685.       "0f",
  686.       "isrc audio track",
  687.       "isrc lyrics",
  688.       "isrc pictures",
  689.       "isrc MIDI data",
  690.       "14", "15", "16", "17", "18", "19",
  691.       "copyright state SUB_INFO",
  692.       "copyright state intro lyrics",
  693.       "copyright state lyrics",
  694.       "copyright state MIDI data",
  695.       "1e", "1f",
  696.       "intro lyrics",
  697.       "pointer to lyrics text file and length", 
  698.       "22", "23", "24", "25", "26", "27", "28",
  699.       "29", "2a", "2b", "2c", "2d", "2e", "2f",
  700.       "still picture descriptor",
  701.       "31",
  702.       "32", "33", "34", "35", "36", "37", "38",
  703.       "39", "3a", "3b", "3c", "3d", "3e", "3f",
  704.       "MIDI file descriptor",
  705.       "genre code",
  706.       "tempo",
  707.       "key"
  708.      };
  709.     unsigned id = *Subp;
  710.     unsigned len = *(Subp +1);
  711.     if (id >= sizeof(infopacketID)/sizeof(const char *)) {
  712.       fprintf(stderr, "Off=%4d, ind=%2d/%2d, unknown Id=%2u, len=%2u ",
  713. Subp - orgSubp, num, num_infos, id, len);
  714.       Subp += 2 + 1;
  715.       length -= 2 + 1;
  716.       break;
  717.     }
  718.     switch (id) {
  719.     case 1:    /* track nummer or 0 */
  720.       this_track = 10 * (*(Subp + 2) - '0') + (*(Subp + 3) - '0');
  721.       break;
  722.     case 0x02: /* album title */
  723. if (global.disctitle == NULL) {
  724.     global.disctitle = (unsigned char *) malloc(len + 1);
  725.     if (global.disctitle != NULL) {
  726.                memcpy(global.disctitle, Subp + 2, len);
  727.        global.disctitle[len] = '';
  728.             }
  729.         }
  730.       break;
  731.     case 0x06: /* track title */
  732. if (this_track > 0 && this_track < 100
  733.     && global.tracktitle[this_track-1] == NULL) {
  734.             global.tracktitle[this_track-1] = (unsigned char *) malloc(len + 1);
  735.             if (global.tracktitle[this_track-1] != NULL) {
  736.                memcpy(global.tracktitle[this_track-1], Subp + 2, len);
  737.                global.tracktitle[this_track-1][len] = '';
  738.             }
  739.         }
  740.       break;
  741.     case 0x05: /* copyright message */
  742. if (global.copyright_message == NULL) {
  743.     global.copyright_message = (unsigned char *) malloc(len + 1);
  744.     if (global.copyright_message != NULL) {
  745.                memcpy(global.copyright_message, Subp + 2, len);
  746.        global.copyright_message[len] = '';
  747.             }
  748.         }
  749.       break;
  750.     case 0x08: /* creator */
  751. if (global.creator == NULL) {
  752.     global.creator = (unsigned char *) malloc(len + 1);
  753.     if (global.creator != NULL) {
  754.                memcpy(global.creator, Subp + 2, len);
  755.        global.creator[len] = '';
  756.             }
  757.         }
  758.       break;
  759. #if 0
  760.     case 0x03:
  761.     case 0x04:
  762.     case 0x07:
  763.     case 0x09:
  764.     case 0x0a:
  765.     case 0x0b:
  766.     case 0x0c:
  767.     case 0x0d:
  768.     case 0x0e:
  769.     case 0x0f:
  770.       fprintf(stderr, "%s: %*.*sn",infopacketID[id], (int) len, (int) len, (Subp +2));
  771.       break;
  772. #ifdef DEBUG_XTRA
  773.     case 0x1a:
  774.     case 0x1b:
  775.     case 0x1c:
  776.     case 0x1d:
  777. fprintf(stderr, "%s %scopyrightedn", infopacketID[id], *(Subp + 2) == 0 ? "not " : "");
  778.       break;
  779.     case 0x21:
  780.       fprintf(stderr, "lyrics file beginning at sector %u",
  781.       (unsigned) GET_BE_UINT_FROM_CHARP(Subp + 2));
  782.       if (len == 8)
  783. fprintf(stderr, ", having length: %un", 
  784.                 (unsigned) GET_BE_UINT_FROM_CHARP(Subp + 6));
  785.       else
  786. fputs("n", stderr);
  787.       break;
  788.     case 0x30:
  789.       sp = Subp + 2;
  790.       while (sp < Subp + 2 + len) {
  791.       /*while (len >= 10) {*/
  792.         s = be16_to_cpu((*(sp)) | (*(sp) << 8));
  793.         fprintf(stderr, "%04x, ", s);
  794. sp += 2;
  795.         up = sp;
  796. switch (s) {
  797. case 0:
  798. break;
  799. case 4:
  800. break;
  801. case 5:
  802. break;
  803. case 6:
  804. break;
  805.         }
  806.         u = GET_BE_UINT_FROM_CHARP(up);
  807.         fprintf(stderr, "%04lx, ", (long) u);
  808.         up += 4;
  809.         u = GET_BE_UINT_FROM_CHARP(up);
  810.         fprintf(stderr, "%04lx, ", (long) u);
  811.         up += 4;
  812. sp += 8;
  813.       }
  814.       fputs("n", stderr);
  815.       break;
  816.     case 0x40:
  817.       fprintf(stderr, "MIDI file beginning at sector %u",
  818.       (unsigned) GET_BE_UINT_FROM_CHARP(Subp + 2));
  819.       if (len == 8)
  820. fprintf(stderr, ", having length: %un", 
  821. (unsigned) GET_BE_UINT_FROM_CHARP(Subp + 6));
  822.       else
  823. fputs("n", stderr);
  824.       break;
  825.     case 0x42:
  826.       fprintf(stderr, "%s: %d beats per minuten",infopacketID[id], *(Subp + 2));
  827.       break;
  828.     case 0x41:
  829.       if (len == 8)
  830.         fprintf(stderr, "%s: %x, %x, %x, %x, %x, %x, %x, %xn",
  831. infopacketID[id],
  832. *(Subp + 2),
  833. *(Subp + 3),
  834. *(Subp + 4),
  835. *(Subp + 5),
  836. *(Subp + 6),
  837. *(Subp + 7),
  838. *(Subp + 8),
  839. *(Subp + 9)
  840. );
  841.       else
  842.         fprintf(stderr, "%s:n",infopacketID[id]);
  843.       break;
  844.     case 0x43:
  845.       fprintf(stderr, "%s: %xn",infopacketID[id], *(Subp + 2));
  846.       break;
  847.     default:
  848.       fprintf(stderr, "%s: %*.*sn",infopacketID[id], (int) len, (int) len, (Subp +2));
  849. #endif
  850. #endif
  851.     }
  852.     if (len & 1) len++;
  853.     Subp += 2 + len;
  854.     length -= 2 + len;
  855.   }
  856. /* cleanup */
  857.   free(orgSubp);
  858.   return;
  859. errorout:
  860.   exit(2);
  861. }
  862. #endif
  863. static unsigned session_start;
  864. /*
  865.    A Cd-Extra is detected, if it is a multisession CD with
  866.    only audio tracks in the first session and a data track
  867.    in the last session.
  868.  */
  869. static unsigned is_cd_extra(no_tracks)
  870. unsigned no_tracks;
  871. {
  872.   unsigned mult_off;
  873. #if defined CDROMMULTISESSION
  874.   /*
  875.    * FIXME: we would have to do a ioctl (CDROMMULTISESSION)
  876.    *        for the cdrom device associated with the generic device
  877.    *     not just AUX_DEVICE
  878.    */
  879.   struct cdrom_multisession ms_str;
  880.   if (interface == GENERIC_SCSI)
  881.     tmp_fd = open (global.aux_name, O_RDONLY);
  882.   else
  883.     tmp_fd = global.cooked_fd;
  884.   if (tmp_fd != -1) {
  885.     int result;
  886.     ms_str.addr_format = CDROM_LBA;
  887.     result = ioctl(tmp_fd, CDROMMULTISESSION, &ms_str);
  888.     if (result == -1) {
  889.       if (global.verbose != 0)
  890.         perror("multi session ioctl not supported: ");
  891.     } else {
  892. #ifdef DEBUG_XTRA
  893.   fprintf(stderr, "current ioctl multisession_offset = %un", ms_str.addr.lba);
  894. #endif
  895. if (interface == GENERIC_SCSI)
  896. close (tmp_fd);
  897. if (ms_str.addr.lba > 0)
  898.   return ms_str.addr.lba;
  899.     }
  900.   }
  901. #endif
  902.   mult_off = (no_tracks > 2 && !IS_AUDIO(no_tracks-2) && IS_AUDIO(no_tracks-3))
  903.                       ? g_toc[no_tracks-2].dwStartSector : 0;
  904. #ifdef DEBUG_XTRA
  905.   fprintf(stderr, "current guessed multisession_offset = %un", mult_off);
  906. #endif
  907.   return mult_off;
  908. }
  909. #define SESSIONSECTORS (152*75)
  910. /*
  911.    The solution is to read the Table of Contents of the first
  912.    session only (if the drive permits that) and directly use
  913.    the start of the leadout. If this is not supported, we subtract
  914.    a constant of SESSIONSECTORS sectors (found heuristically).
  915.  */
  916. static unsigned get_end_of_last_audio_track(mult_off, no_tracks)
  917. unsigned mult_off;
  918. unsigned no_tracks;
  919. {
  920.    unsigned retval;
  921.    /* Try to read the first session table of contents.
  922.       This works for Sony and mmc type drives. */
  923.    if (ReadLastAudio && (retval = ReadLastAudio(get_scsi_p(), no_tracks)) != 0) {
  924.      return retval;
  925.    } else {
  926.      return mult_off - SESSIONSECTORS;
  927.    }
  928. }
  929. static void dump_cdtext_info __PR((void));
  930. /* The Table of Contents needs to be corrected if we
  931.    have a CD-Extra. In this case all audio tracks are
  932.    followed by a data track (in the second session).
  933.    Unlike for single session CDs the end of the last audio
  934.    track cannot be set to the start of the following
  935.    track, since the lead-out and lead-in would then
  936.    errenously be part of the audio track. This would
  937.    lead to read errors when trying to read into the
  938.    lead-out area.
  939.    So the length of the last track in case of Cd-Extra
  940.    has to be fixed.
  941.  */
  942. unsigned FixupTOC(no_tracks)
  943. unsigned no_tracks;
  944. {
  945.     unsigned mult_off;
  946.     unsigned offset = 0;
  947.     /* get the multisession offset in sectors */
  948.     mult_off = is_cd_extra(no_tracks);
  949.     /* if the first track address had been the victim of an underflow,
  950.      * set it to zero.
  951.      */
  952.     if (g_toc[0].dwStartSector > g_toc[no_tracks-1].dwStartSector) {
  953. fprintf(stderr, "Warning: first sector has negative start sector! Setting to zero.n");
  954. g_toc[0].dwStartSector = 0;
  955.     }
  956. #ifdef DEBUG_XTRA
  957.     fprintf(stderr, "current multisession_offset = %un", mult_off);
  958. #endif
  959.     dump_cdtext_info();
  960.     if (mult_off > 100) { /* the offset has to have a minimum size */
  961.       int j;
  962.       unsigned real_end;
  963.       /* believe the multisession offset :-) */
  964.       /* adjust end of last audio track to be in the first session */
  965.       real_end = get_end_of_last_audio_track(mult_off, no_tracks);
  966. #ifdef DEBUG_XTRA
  967.     fprintf(stderr, "current end = %un", real_end);
  968. #endif
  969.       for (j = no_tracks-2; j > 0; j--) {
  970. if (!IS_AUDIO(j) && IS_AUDIO(j-1)) {
  971.   if (g_toc[j].dwStartSector > real_end) {
  972.     session_start = mult_off;
  973. #ifdef CD_EXTRA
  974.     offset = Read_CD_Extra_Info(g_toc[j].dwStartSector);
  975. #endif
  976. have_CD_extra = g_toc[j].dwStartSector;
  977.         dump_extra_info(offset);
  978. #if defined CDINDEX_SUPPORT || defined CDDB_SUPPORT
  979. {
  980.     unsigned long count_audio_tracks = 0;
  981.     unsigned i;
  982.     for (i = 0; i < cdtracks; i++)
  983. if (IS_AUDIO(i)) count_audio_tracks++;
  984.     if (count_audio_tracks > 0 && global.no_cddbfile == 0) {
  985. #if defined CDINDEX_SUPPORT
  986. emit_cdindex_form(global.fname_base);
  987. #endif
  988. #if defined CDDB_SUPPORT
  989. emit_cddb_form(global.fname_base);
  990. #endif
  991.     }
  992. }
  993. #endif
  994.             /* set start of track to beginning of lead-out */
  995.     g_toc[j].dwStartSector = real_end;
  996. #if defined CD_EXTRA && defined DEBUG_XTRA
  997.     fprintf(stderr, "setting end of session to %un", real_end);
  998. #endif
  999.   }
  1000.   break;
  1001. }
  1002.       }
  1003.     } else {
  1004. #if defined CDINDEX_SUPPORT || defined CDDB_SUPPORT
  1005. if (have_CD_text) {
  1006.     unsigned long count_audio_tracks = 0;
  1007.     unsigned i;
  1008.     for (i = 0; i < cdtracks; i++)
  1009. if (IS_AUDIO(i)) count_audio_tracks++;
  1010.     if (count_audio_tracks > 0 && global.no_cddbfile == 0) {
  1011. #if defined CDINDEX_SUPPORT
  1012. emit_cdindex_form(global.fname_base);
  1013. #endif
  1014. #if defined CDDB_SUPPORT
  1015. emit_cddb_form(global.fname_base);
  1016. #endif
  1017.     }
  1018. }
  1019. #endif
  1020.     }
  1021.     return offset;
  1022. }
  1023. static int cddb_sum(n)
  1024. int n;
  1025. {
  1026.   int ret;
  1027.   for (ret = 0; n > 0; n /= 10) {
  1028.     ret += (n % 10);
  1029.   }
  1030.   return ret;
  1031. }
  1032. void calc_cddb_id()
  1033. {
  1034.   UINT4 i;
  1035.   UINT4 t = 0;
  1036.   UINT4 n = 0;
  1037.   for (i = 0; i < cdtracks; i++) {
  1038.     n += cddb_sum(g_toc[i].dwStartSector/75 + 2);
  1039.   }
  1040.   t = g_toc[i].dwStartSector/75 - g_toc[0].dwStartSector/75;
  1041.   global.cddb_id = (n % 0xff) << 24 | (t << 8) | cdtracks;
  1042. }
  1043. #undef TESTCDINDEX
  1044. #ifdef TESTCDINDEX
  1045. void TestGenerateId()
  1046. {
  1047.    SHA_INFO       sha;
  1048.    unsigned char  digest[20], *base64;
  1049.    unsigned long  size;
  1050.    sha_init(&sha);
  1051.    sha_update(&sha, (unsigned char *)"0123456789", 10);
  1052.    sha_final(digest, &sha);
  1053.    base64 = rfc822_binary((char *)digest, 20, &size);
  1054.    if (strncmp((char*) base64, "h6zsF82dzSCnFsws9nQXtxyKcBY-", size))
  1055.    {
  1056.        free(base64);
  1057.        printf("The SHA-1 hash function failed to properly generate then");
  1058.        printf("test key.n");
  1059.        exit(0);
  1060.    }
  1061.    free(base64);
  1062. }
  1063. #endif
  1064. void calc_cdindex_id()
  1065. {
  1066. SHA_INFO  sha;
  1067. unsigned char digest[20], *base64;
  1068. unsigned long size;
  1069. unsigned i;
  1070. char temp[9];
  1071. #ifdef TESTCDINDEX
  1072. TestGenerateId();
  1073. g_toc[0].bTrack = 1;
  1074. cdtracks = 15;
  1075. g_toc[cdtracks-1].bTrack = 15;
  1076. i = 0;
  1077. g_toc[i++].dwStartSector = 0U;
  1078. g_toc[i++].dwStartSector = 18641U;
  1079. g_toc[i++].dwStartSector = 34667U;
  1080. g_toc[i++].dwStartSector = 56350U;
  1081. g_toc[i++].dwStartSector = 77006U;
  1082. g_toc[i++].dwStartSector = 106094U;
  1083. g_toc[i++].dwStartSector = 125729U;
  1084. g_toc[i++].dwStartSector = 149785U;
  1085. g_toc[i++].dwStartSector = 168885U;
  1086. g_toc[i++].dwStartSector = 185910U;
  1087. g_toc[i++].dwStartSector = 205829U;
  1088. g_toc[i++].dwStartSector = 230142U;
  1089. g_toc[i++].dwStartSector = 246659U;
  1090. g_toc[i++].dwStartSector = 265614U;
  1091. g_toc[i++].dwStartSector = 289479U;
  1092. g_toc[i++].dwStartSector = 325732U;
  1093. #endif
  1094. sha_init(&sha);
  1095. sprintf(temp, "%02X", g_toc[0].bTrack);
  1096. sha_update(&sha, (unsigned char *)temp, 2);
  1097. sprintf(temp, "%02X", g_toc[cdtracks-1].bTrack);
  1098. sha_update(&sha, (unsigned char *)temp, 2);
  1099. /* the position of the leadout comes first. */
  1100. sprintf(temp, "%08X", 150+g_toc[cdtracks].dwStartSector);
  1101. sha_update(&sha, (unsigned char *)temp, 8);
  1102. /* now 99 tracks follow with their positions. */
  1103. for (i = 0; i < cdtracks; i++) {
  1104. sprintf(temp, "%08X", 150+g_toc[i].dwStartSector);
  1105. sha_update(&sha, (unsigned char *)temp, 8);
  1106. }
  1107. for (i++  ; i < 100; i++) {
  1108. sha_update(&sha, (unsigned char *)"00000000", 8);
  1109. }
  1110. sha_final(digest, &sha);
  1111. base64 = rfc822_binary((char *)digest, 20, &size);
  1112. global.cdindex_id = base64;
  1113. }
  1114. #if defined CDDB_SUPPORT
  1115. static void emit_cddb_form(fname_baseval)
  1116. char *fname_baseval;
  1117. {
  1118.   unsigned i;
  1119.   unsigned first_audio;
  1120.   FILE *cddb_form;
  1121.   char fname[200];
  1122.   char *pp;
  1123.   if (fname_baseval == NULL || fname_baseval[0] == 0)
  1124. return;
  1125.   strncpy(fname, fname_baseval, sizeof(fname) -1);
  1126.   fname[sizeof(fname) -1] = 0;
  1127.   pp = strrchr(fname, '.');
  1128.   if (pp == NULL) {
  1129.     pp = fname + strlen(fname);
  1130.   }
  1131.   strncpy(pp, ".cddb", sizeof(fname) - 1 - (pp - fname));
  1132.   cddb_form = fopen(fname, "w");
  1133.   if (cddb_form == NULL) return;
  1134.   first_audio = FirstAudioTrack();
  1135.   fprintf( cddb_form, "# xmcdn#n");
  1136.   fprintf( cddb_form, "# Track frame offsets:n#n");
  1137.   for (i = first_audio - 1; i < cdtracks; i++) {
  1138.     if (!IS_AUDIO(i)) break;
  1139.     fprintf( cddb_form, "# %un", 150 + g_toc[i].dwStartSector);
  1140.   }
  1141.   fprintf( cddb_form, "#n# Disc length: %lu secondsn#n", 
  1142.            (GetLastSectorOnCd(first_audio) - GetStartSector(first_audio)) / 75);
  1143.   fprintf( cddb_form, "# Revision: 0n" );
  1144.   fprintf( cddb_form, "# Submitted via: cdda2wav ");
  1145.   fprintf( cddb_form, VERSION);
  1146.   fprintf( cddb_form, "n" );
  1147.   fprintf( cddb_form, "DISCID=%8lxn", global.cddb_id);
  1148.   if (global.disctitle == NULL && global.creator == NULL) {
  1149.     fprintf( cddb_form, "DTITLE=n");
  1150.   } else {
  1151.     if (global.creator == NULL) {
  1152.       fprintf( cddb_form, "DTITLE=%sn", global.disctitle);
  1153.     } else if (global.disctitle == NULL) {
  1154.       fprintf( cddb_form, "DTITLE=%sn", global.creator);
  1155.     } else {
  1156.       fprintf( cddb_form, "DTITLE=%s / %sn", global.creator, global.disctitle);
  1157.     }
  1158.   }
  1159.   for (i = first_audio - 1; i < cdtracks; i++) {
  1160.     if (!IS_AUDIO(i)) break;
  1161.     if (global.tracktitle[i] != NULL) {
  1162.       fprintf( cddb_form, "TTITLE%d=%sn", i, global.tracktitle[i]);
  1163.     } else {
  1164.       fprintf( cddb_form, "TTITLE%d=n", i);
  1165.     }
  1166.   }
  1167.   if (global.copyright_message == NULL) {
  1168.     fprintf( cddb_form, "EXTD=n");
  1169.   } else {
  1170.     fprintf( cddb_form, "EXTD=Copyright %sn", global.copyright_message);
  1171.   }
  1172.   for (i = first_audio - 1; i < cdtracks; i++) {
  1173.     if (!IS_AUDIO(i)) break;
  1174.     fprintf( cddb_form, "EXTT%d=n", i);
  1175.   }
  1176.   fprintf( cddb_form, "PLAYORDER=n");
  1177.   fclose( cddb_form );
  1178. }
  1179. #ifdef NOTYET
  1180. /* network access for cddb servers */
  1181. static int get_list_of_servers()
  1182. {
  1183. /*
  1184. CDDB_SITES_SERVER=cddb.cddb.com
  1185. CDDB_SITES_SERVERPORT=8880
  1186. */
  1187. return 0;
  1188. }
  1189. static int scan_servers(cddb_id)
  1190. unsigned cddb_id;
  1191. {
  1192. return 0;
  1193. }
  1194. int resolve_id(cddb_id)
  1195. unsigned cddb_idr;)
  1196. {
  1197.   unsigned servers;
  1198.   servers = get_list_of_servers();
  1199.   if (servers == 0) return 0;
  1200.   return scan_servers(cddb_id);
  1201. }
  1202. #endif
  1203. #endif
  1204. #if defined CDINDEX_SUPPORT
  1205. static int IsSingleArtist __PR((void));
  1206. /* check, if there are more than one track creators */
  1207. static int IsSingleArtist()
  1208. {
  1209. unsigned i;
  1210. for (i = 0; i < cdtracks; i++) {
  1211. if (!IS_AUDIO(i)) continue;
  1212. if (global.creator && global.trackcreator[i]
  1213. && strcmp((char *) global.creator,
  1214.   (char *) global.trackcreator[i]) != 0)
  1215. return 0;
  1216. }
  1217. return 1;
  1218. }
  1219. static void emit_cdindex_form(fname_baseval)
  1220. char *fname_baseval;
  1221. {
  1222.   int i;
  1223.   FILE *cdindex_form;
  1224.   char fname[200];
  1225.   char *pp;
  1226.   if (fname_baseval == NULL || fname_baseval[0] == 0)
  1227. return;
  1228.   strncpy(fname, fname_baseval, sizeof(fname) -1);
  1229.   fname[sizeof(fname) -1] = 0;
  1230.   pp = strrchr(fname, '.');
  1231.   if (pp == NULL) {
  1232.     pp = fname + strlen(fname);
  1233.   }
  1234.   strncpy(pp, ".cdindex", sizeof(fname) - 1 - (pp - fname));
  1235.   cdindex_form = fopen(fname, "w");
  1236.   if (cdindex_form == NULL) return;
  1237. #define CDINDEX_URL "http://www.cdindex.org/dtd/CDInfo.dtd"
  1238.   /* format XML page according to cdindex DTD (see www.cdindex.org) */
  1239.   fprintf( cdindex_form, "<?xml version="1.0" encoding="ISO-8859-1"?>n<!DOCTYPE CDInfo SYSTEM "%s">nn<CDInfo>n",
  1240.   CDINDEX_URL);
  1241.   fprintf( cdindex_form, "   <Title>%s</Title>n",
  1242.  global.disctitle ? (char *) global.disctitle : "");
  1243.   /* 
  1244.    * In case of mixed mode and Extra-CD, nonaudio tracks are included!
  1245.    */
  1246.   fprintf( cdindex_form, "   <NumTracks>%d</NumTracks>nn", cdtracks);
  1247.   fprintf( cdindex_form, "   <IdInfo>n      <DiskId>n         <Id>%s</Id>n      </DiskId>n", global.cdindex_id); 
  1248.   fprintf( cdindex_form, "   </IdInfo>nn");
  1249.   if (IsSingleArtist()) {
  1250.     fprintf( cdindex_form, "   <SingleArtistCD>n      <Artist>%s</Artist>n",
  1251.  global.creator ? (char *) global.creator : "");
  1252.     for (i = FirstTrack() - 1; i <= LastTrack() - 1; i++) {
  1253.       if (IS_AUDIO(i)) {
  1254.         fprintf( cdindex_form,
  1255.  "      <Track Num="%d">n         <Name>%s</Name>n      </Track>n",
  1256.   i+1, global.tracktitle[i] ? (char *) global.tracktitle[i] : "");
  1257.       } else {
  1258.         fprintf( cdindex_form,
  1259.  "      <Track Num="%d">n         <Name>data track</Name>n      </Track>n",
  1260.   i+1 );
  1261.       }
  1262.     }
  1263.     fprintf( cdindex_form, "   </SingleArtistCD>n");
  1264.   } else {
  1265.     fprintf( cdindex_form, "   <MultipleArtistCD>n");
  1266.     for (i = FirstTrack() - 1; i <= LastTrack() - 1; i++) {
  1267.       fprintf( cdindex_form, "      <Track Num="%d">n", i);
  1268.       if (IS_AUDIO(i)) {
  1269.         fprintf( cdindex_form, "         <Artist>%s</Artist>n",
  1270.   global.trackcreator[i] ? (char *) global.trackcreator[i] : "");
  1271.         fprintf( cdindex_form, "         <Name>%s</Name>n      </Track>n",
  1272.   global.tracktitle[i] ? (char *) global.tracktitle[i] : "");
  1273.       } else {
  1274.         fprintf( cdindex_form,
  1275.  "         <Artist>data track</Artist>n         <Name>data track</Name>n      </Track>n");
  1276.       }
  1277.     }
  1278.     fprintf( cdindex_form, "   </MultipleArtistCD>n");
  1279.   }
  1280.   fprintf( cdindex_form, "</CDInfo>n");
  1281.   fclose( cdindex_form );
  1282. }
  1283. #endif
  1284. static void dump_cdtext_info()
  1285. {
  1286. #ifdef CD_TEXT
  1287.   /* interpret the contents of CD Text information based on an early draft
  1288.      of SCSI-3 mmc version 2 from jan 2, 1998
  1289.      CD Text information consists of a text group containing up to
  1290.      8 language blocks containing up to
  1291.      255 Pack data chunks of
  1292.      18 bytes each.
  1293.      So we have at most 36720 bytes to cope with.
  1294.    */
  1295.   {
  1296.     short int datalength;
  1297.     unsigned char *p = bufferTOC;
  1298.     unsigned char lastline[255*12];
  1299.     int lastitem = -1;
  1300.     int itemcount = 0;
  1301.     int inlinecount = 0;
  1302.     int outlinecount = 0;
  1303.     lastline[0] = '';
  1304.     datalength = ((p[0] << 8) + p[1]) - 2;
  1305.     datalength = min(datalength, 2048-4);
  1306.     p += 4;
  1307.     for (;datalength > 0;
  1308. datalength -= sizeof (cdtextpackdata),
  1309. p += sizeof (cdtextpackdata)) {
  1310.       /* handle one packet of CD Text Information Descriptor Pack Data */
  1311.       /* this is raw R-W subchannel data converted to 8 bit values. */
  1312.       cdtextpackdata *c = (cdtextpackdata *)p;
  1313.       int extension_flag;
  1314.       int sequence_number;
  1315.       int dbcc;
  1316.       int block_number;
  1317.       int character_position;
  1318.       int crc_error;
  1319. #ifdef DEBUG_CDTEXT
  1320.       fprintf(stderr, "datalength =%dn", datalength);
  1321. #endif
  1322.       crc_error = !cdtext_crc_ok(c);
  1323.       if (lastitem != c->headerfield[0]) {
  1324. itemcount = 0;
  1325. lastitem = c->headerfield[0];
  1326.       }
  1327.       extension_flag = ((unsigned)(c->headerfield[1] & 0x80)) >> 7;
  1328.       c->headerfield[1] &= 0x7f;
  1329.       sequence_number = c->headerfield[2];
  1330.       dbcc = ((unsigned)(c->headerfield[3] & 0x80)) >> 7; /* double byte character code */
  1331.       block_number = ((unsigned)(c->headerfield[3] & 0x30)) >> 4; /* language */
  1332.       character_position = c->headerfield[3] & 0x0f;
  1333. #if defined DEBUG_CDTEXT
  1334.       fprintf(stderr, "CDText: ext_fl=%d, trnr=%d, seq_nr=%d, dbcc=%d, block_nr=%d, char_pos=%dn",
  1335.              extension_flag, (int)c->headerfield[1], sequence_number, dbcc, block_number, character_position);
  1336. #endif
  1337.       if (dbcc == 0) {
  1338.         /* print ASCII information */
  1339. unsigned char *zeroposition;
  1340.         memcpy(lastline+inlinecount, c->textdatafield, 12);
  1341. inlinecount += 12;
  1342. zeroposition = (unsigned char *)memchr(lastline+outlinecount, '', inlinecount-outlinecount);
  1343. while (zeroposition != NULL) {
  1344.   process_header(c, dbcc, lastline+outlinecount);
  1345.   outlinecount += zeroposition - (lastline+outlinecount) + 1;
  1346. #if defined DEBUG_CDTEXT
  1347.   fprintf(stderr, "tin=%d, out=%d, items=%d, trcknum=%dn", inlinecount, outlinecount, itemcount, (int) c->headerfield[1]);
  1348. { int q; for (q= outlinecount; q < inlinecount; q++) fprintf (stderr, "%c", lastline[q] ? lastline[q] : '