toc.c

来自「刻录光盘的程序」· C语言 代码 · 共 1,530 行 · 第 1/3 页

C
1,530
字号
/* @(#)toc.c	1.3 00/01/11 Copyright 1998,1999 Heiko Eissfeldt */#ifndef lintstatic char     sccsid[] ="@(#)toc.c	1.3 00/01/11 Copyright 1998,1999 Heiko Eissfeldt";#endif/* * Copyright: GNU Public License 2 applies * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2, or (at your option) *   any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * CDDA2WAV (C) Heiko Eissfeldt heiko@colossus.escape.de * CDDB routines (C) Ti Kan and Steve Scherf */#include "config.h"#include <stdio.h>#include <standard.h>#include <stdlib.h>#include <strdefs.h>#if defined (HAVE_UNISTD_H) && (HAVE_UNISTD_H == 1)#include <sys/types.h>#include <unistd.h>		/* sleep */#endif#include <ctype.h>#include <errno.h>#include <fcntl.h>#include <sys/ioctl.h>#define CD_TEXT#define CD_EXTRA#undef DEBUG_XTRA#undef DEBUG_CDTEXT#include <scg/scsitransp.h>#include "mytype.h"#include "byteorder.h"#include "interface.h"#include "cdda2wav.h"#include "global.h"#include "sha.h"#include "base64.h"#include "toc.h"#include "ringbuff.h"int have_CD_text;int have_CD_extra;static void UpdateTrackData	__PR((int p_num));static void UpdateIndexData	__PR((int p_num));static void UpdateTimeData	__PR((int p_min, int p_sec, int p_frm));static unsigned int is_cd_extra	__PR((unsigned int no_tracks));static unsigned int get_end_of_last_audio_track	__PR((unsigned int mult_off, unsigned int no_tracks));static int cddb_sum		__PR((int n));static void emit_cddb_form	__PR((char *fname_baseval));static void emit_cdindex_form	__PR((char *fname_baseval));static void dump_extra_info	__PR((unsigned int from));static int GetIndexOfSector	__PR((unsigned int sec, unsigned track));static int linear_search	__PR((int searchInd, unsigned int Start, unsigned int End, unsigned track));static int binary_search	__PR((int searchInd, unsigned int Start, unsigned int End, unsigned track));static unsigned char g_track=0xff, g_index=0xff;	/* current track, index */static unsigned char g_minute=0xff, g_seconds=0xff;	/* curr. minute, second */static unsigned char g_frame=0xff;			/* current frame *//* print the track currently read */static void UpdateTrackData (p_num)	int	p_num;{  if (global.quiet == 0) {     fprintf (stderr, "\ntrack: %.2d, ", p_num); fflush(stderr);  }  g_track = (unsigned char) p_num;}/* print the index currently read */static void UpdateIndexData (p_num)	int p_num;{  if (global.quiet == 0) {     fprintf (stderr, "index: %.2d\n", p_num); fflush(stderr);  }  g_index = (unsigned char) p_num;}/* print the time of track currently read */static void UpdateTimeData (p_min, p_sec, p_frm)	int p_min;	int p_sec;	int p_frm;{  if (global.quiet == 0) {    fprintf (stderr, "time: %.2d:%.2d.%.2d\r", p_min, p_sec, p_frm);     fflush(stderr);  }  g_minute = (unsigned char) p_min;  g_seconds = (unsigned char) p_sec;  g_frame = (unsigned char) p_frm;}void AnalyzeQchannel ( frame )	unsigned frame;{    subq_chnl *sub_ch;    if (trackindex_disp != 0) {	sub_ch = ReadSubQ(get_scsi_p(), GET_POSITIONDATA,0);	/* analyze sub Q-channel data */	if (sub_ch->track != g_track ||	    sub_ch->index != g_index) {	    UpdateTrackData (sub_ch->track);	    UpdateIndexData (sub_ch->index);	}    }    frame += 150;    UpdateTimeData ((unsigned char) (frame / (60*75)), 		    (unsigned char) ((frame % (60*75)) / 75), 		    (unsigned char) (frame % 75));}unsigned cdtracks = 0;long GetStartSector ( p_track )	unsigned long p_track;{  unsigned long i;  for (i = 0; i < cdtracks; i++) {    if (g_toc [i].bTrack == p_track) {      unsigned long dw = g_toc [i].dwStartSector;      if ((g_toc [i].bFlags & CDROM_DATA_TRACK) != 0)	return -1;      return dw;    }  }  return -1;}long GetEndSector ( p_track )	unsigned long p_track;{  unsigned long i;  for ( i = 1; i <= cdtracks; i++ ) {    if ( g_toc [i-1].bTrack == p_track ) {      unsigned long dw = g_toc [i].dwStartSector;      return dw-1;    }  }  return -1;}long FirstTrack ( ){  return g_toc[0].bTrack;}long FirstAudioTrack ( ){  unsigned long i;    for ( i = 0; i < cdtracks; i++ ) {    if ( g_toc [i].bTrack != CDROM_LEADOUT &&	( g_toc [i].bFlags & CDROM_DATA_TRACK ) == 0 )      return g_toc [i].bTrack;  }  return 0;}long LastTrack ( ){  return g_toc[cdtracks-1].bTrack;}long LastAudioTrack ( ){  unsigned i;  long j = -1;  for ( i = 0; i < cdtracks; i++ ) {    if ( g_toc [i].bTrack != CDROM_LEADOUT &&	( g_toc [i].bFlags & CDROM_DATA_TRACK ) == 0 )      j = g_toc [i].bTrack;  }  return j;}long GetLastSectorOnCd( p_track )	unsigned long p_track;{  unsigned long i;  long LastSec = 0;  for ( i = 1; i <= cdtracks; i++ ) {    if ( g_toc [i-1].bTrack < p_track )      continue;    /* break if a nonaudio track follows */    if ( (g_toc [i-1].bFlags & CDROM_DATA_TRACK) != 0) break;    LastSec = GetEndSector ( g_toc [i-1].bTrack ) + 1;  }  return LastSec;}int GetTrack( sector )	unsigned long sector;{  unsigned long i;  for (i = 0; i < cdtracks; i++) {    if (g_toc[i  ].dwStartSector <= sector &&	g_toc[i+1].dwStartSector > sector)      return (g_toc [i].bFlags & CDROM_DATA_TRACK) != 0 ? -1 : (int)(i+1);  }  return -1;}int CheckTrackrange( from, upto )	unsigned long from;	unsigned long upto;{  unsigned long i;  for ( i = 1; i <= cdtracks; i++ ) {    if ( g_toc [i-1].bTrack < from )      continue;    if ( g_toc [i-1].bTrack == upto )      return 1;    /* break if a nonaudio track follows */    if ( (g_toc [i-1].bFlags & CDROM_DATA_TRACK) != 0)      return 0;  }  /* track not found */  return 0;}unsignedfind_an_off_sector __PR((unsigned lSector, unsigned SectorBurstVal));unsigned find_an_off_sector(lSector, SectorBurstVal)	unsigned lSector;	unsigned SectorBurstVal;{	long track_of_start = GetTrack(lSector);	long track_of_end = GetTrack(lSector + SectorBurstVal -1);	long start = GetStartSector(track_of_start);	long end = GetEndSector(track_of_end);	if (lSector - start > end - lSector + SectorBurstVal -1)		return start;	else		return end;}#ifdef CD_TEXT#include "scsi_cmds.h"#endifint   handle_cdtext __PR(( void ));int   handle_cdtext (){#ifdef CD_TEXT	if (bufferTOC[0] == 0 && bufferTOC[1] == 0) {		have_CD_text = 0;		return have_CD_text;	}	/* do a quick scan over all pack type indicators */	{		int i;		int count_fails = 0;		int len = (bufferTOC[0] << 8) | bufferTOC[1];		len = min(len, 2048);		for (i = 0; i < len-4; i += 18) {			if (bufferTOC[4+i] < 0x80 || bufferTOC[4+i] > 0x8f) {				count_fails++;			}		}		have_CD_text = count_fails < 3;	}#else	have_CD_text = 0;#endif	return have_CD_text;}#ifdef CD_TEXT/**************** CD-Text special treatment **********************************/typedef struct {	unsigned char headerfield[4];	unsigned char textdatafield[12];	unsigned char crcfield[2];} cdtextpackdata;static unsigned short crctab[1<<8] = { /* as calculated by initcrctab() */    0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,    0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,    0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,    0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,    0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,    0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,    0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,    0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,    0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,    0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,    0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,    0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,    0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,    0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,    0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,    0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,    0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,    0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,    0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,    0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,    0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,    0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,    0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,    0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,    0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,    0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,    0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,    0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,    0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,    0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,    0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,    0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0,    };#undef SLOWER_CRC#define SUBSIZE	18*8static unsigned short updcrc __PR((	    unsigned int    p_crc,            register unsigned char   *cp,            register size_t  cnt));static unsigned short updcrc(p_crc, cp, cnt)	unsigned int p_crc;        register unsigned char   *cp;        register size_t  cnt;{      register unsigned short crc = p_crc;      while( cnt-- ) {#ifdef SLOWERCRC            crc = (crc<<8) ^ crctab[(crc>>(16-8)) ^ ~(*cp++)];#else            crc = (crc<<8) ^ crctab[(crc>>(16-8)) ^ (*cp++)];#endif      }      return( crc );}static unsigned short calcCRC __PR((unsigned char *buf, unsigned bsize));static unsigned short calcCRC(buf, bsize)	unsigned char *buf;	unsigned bsize;{#ifdef SLOWERCRC      return updcrc( 0x0, (unsigned char *)buf, bsize );#else      return updcrc( 0x0, (unsigned char *)buf, bsize ) ^ 0x1d0f;#endif}unsigned char    fliptab[8] = {        0x01,        0x02,        0x04,        0x08,        0x10,        0x20,        0x40,        0x80,};static int flip_error_corr __PR((unsigned char *b, int crc));static int flip_error_corr(b, crc)	unsigned char *b;	int crc;{  if (crc != 0) {    int i;    for (i = 0; i < SUBSIZE; i++) {      char      c;      c = fliptab[i%8];      b[i / 8] ^= c;      if ((crc = calcCRC(b, SUBSIZE/8)) == 0) {        return crc;      }      b[i / 8] ^= c;    }  }  return crc & 0xffff;}static int cdtext_crc_ok __PR((cdtextpackdata *c));static int cdtext_crc_ok (c)	cdtextpackdata *c;{	int crc;	crc = calcCRC(((unsigned char *)c), 18);	return 0 == flip_error_corr((unsigned char *)c, crc);}static void dump_binary __PR((cdtextpackdata *c));static void dump_binary(c)	cdtextpackdata *c;{          fprintf(stderr, ": header fields %02x %02x %02x  ",                          c->headerfield[1], c->headerfield[2], c->headerfield[3]);          fprintf(stderr,"%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x"                        , c->textdatafield[0]                        , c->textdatafield[1]                        , c->textdatafield[2]                        , c->textdatafield[3]                        , c->textdatafield[4]                        , c->textdatafield[5]                        , c->textdatafield[6]                        , c->textdatafield[7]                        , c->textdatafield[8]                        , c->textdatafield[9]                        , c->textdatafield[10]                        , c->textdatafield[11]                 );}#define DETAILED 0static int process_header __PR((cdtextpackdata *c, int dbcc, unsigned char *line));static int process_header(c, dbcc, line)	cdtextpackdata *c;	int dbcc;	unsigned char *line;{      switch ((int)c->headerfield[0]) {        case 0x80: /* Title of album or track */          if (DETAILED) fprintf (stderr, "Title");	  if (c->headerfield[1] > 0 && c->headerfield[1] < 100	    && global.tracktitle[c->headerfield[1]-1] == NULL) {	    unsigned len;	    len = strlen((char *)line);            if (len > 0)            	global.tracktitle[c->headerfield[1]-1] = (unsigned char *) malloc(len + 1);            if (global.tracktitle[c->headerfield[1]-1] != NULL) {               memcpy(global.tracktitle[c->headerfield[1]-1], line, len);               global.tracktitle[c->headerfield[1]-1][len] = '\0';            }          } else 	  if (c->headerfield[1] == 0	    && global.disctitle == NULL) {	    unsigned len;	    len = strlen((char *)line);            if (len > 0)            	global.disctitle = (unsigned char *) malloc(len + 1);            if (global.disctitle != NULL) {               memcpy(global.disctitle, line, len);               global.disctitle[len] = '\0';            }	  }        break;        case 0x81: /* Name(s) of the performer(s) */          if (DETAILED) fprintf(stderr, "Performer(s)");	  if (c->headerfield[1] > 0 && c->headerfield[1] < 100	    && global.trackcreator[c->headerfield[1]-1] == NULL) {	    unsigned len;	    len = strlen((char *)line);            if (len > 0)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?