CdrDriver.cc
上传用户:weiliju62
上传日期:2007-01-06
资源大小:619k
文件大小:81k
源码类别:

SCSI/ASPI

开发平台:

MultiPlatform

  1. /*  cdrdao - write audio CD-Rs in disc-at-once mode
  2.  *
  3.  *  Copyright (C) 1998, 1999 Andreas Mueller <mueller@daneb.ping.de>
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19. /*
  20.  * $Log: CdrDriver.cc,v $
  21.  * Revision 1.13  1999/04/05 18:47:11  mueller
  22.  * Added CD-TEXT support.
  23.  *
  24.  * Revision 1.12  1999/03/27 20:52:17  mueller
  25.  * Added data track support for writing and toc analysis.
  26.  *
  27.  * Revision 1.11  1999/02/06 20:41:21  mueller
  28.  * Added virtual member function 'checkToc()'.
  29.  *
  30.  * Revision 1.10  1998/10/24 14:28:59  mueller
  31.  * Changed prototype of 'readDiskToc()'. It now accepts the name of the
  32.  * audio file that should be placed into the generated toc-file.
  33.  * Added virtual function 'readDisk()' that for reading disk toc and
  34.  * ripping audio data at the same time.
  35.  *
  36.  * Revision 1.9  1998/10/03 15:10:38  mueller
  37.  * Added function 'writeZeros()'.
  38.  * Updated function 'writeData()'.
  39.  *
  40.  * Revision 1.8  1998/09/27 19:19:18  mueller
  41.  * Added retrieval of control nibbles for track with 'analyzeTrack()'.
  42.  * Added multi session mode.
  43.  *
  44.  * Revision 1.7  1998/09/22 19:15:13  mueller
  45.  * Removed memory allocations during write process.
  46.  *
  47.  * Revision 1.6  1998/09/07 15:20:20  mueller
  48.  * Reorganized read-toc related code.
  49.  *
  50.  * Revision 1.5  1998/09/06 13:34:22  mueller
  51.  * Use 'message()' for printing messages.
  52.  *
  53.  * Revision 1.4  1998/08/30 19:12:19  mueller
  54.  * Added supressing of error messages for some commands.
  55.  * Added structure 'DriveInfo'.
  56.  *
  57.  * Revision 1.3  1998/08/25 19:24:07  mueller
  58.  * Moved basic index extraction algorithm for read-toc to this class.
  59.  * Added vendor codes.
  60.  *
  61.  */
  62. static char rcsid[] = "$Id: CdrDriver.cc,v 1.13 1999/04/05 18:47:11 mueller Exp mueller $";
  63. #include <config.h>
  64. #include <sys/types.h>
  65. #include <sys/stat.h>
  66. #include <stdio.h>
  67. #include <stdlib.h>
  68. #include <string.h>
  69. #include <errno.h>
  70. #include <assert.h>
  71. #include <fcntl.h>
  72. #include <unistd.h>
  73. #include "CdrDriver.h"
  74. #include "PWSubChannel96.h"
  75. #include "Toc.h"
  76. #include "util.h"
  77. #include "CdTextItem.h"
  78. // all drivers
  79. #include "CDD2600.h"
  80. #include "PlextorReader.h"
  81. #include "PlextorReaderScan.h"
  82. #include "GenericMMC.h"
  83. #include "GenericMMCraw.h"
  84. #include "RicohMP6200.h"
  85. #include "TaiyoYuden.h"
  86. #include "YamahaCDR10x.h"
  87. #include "TeacCdr55.h"
  88. #include "SonyCDU920.h"
  89. #include "SonyCDU948.h"
  90. // Paranoia DAE related
  91. #include "cdda_interface.h"
  92. #include "../paranoia/cdda_paranoia.h"
  93. typedef CdrDriver *(*CdrDriverConstructor)(ScsiIf *, unsigned long);
  94. struct DriverSelectTable {
  95.   char *driverId;
  96.   char *vendor;
  97.   char *model;
  98.   unsigned long options;
  99. };
  100. struct DriverTable {
  101.   char *driverId;
  102.   CdrDriverConstructor constructor;
  103. };
  104. static DriverSelectTable READ_DRIVER_TABLE[] = {
  105. { "generic-mmc", "ASUS", "CD-S400", 0 },
  106. { "generic-mmc", "E-IDE", "CD-ROM 36X/AKU", 0 },
  107. { "generic-mmc", "LITEON", "CD-ROM", OPT_DRV_GET_TOC_GENERIC },
  108. { "generic-mmc", "MATSHITA", "CD-ROM CR-588", 0 },
  109. { "generic-mmc", "MEMOREX", "CD-233E", 0 },
  110. { "generic-mmc", "PIONEER", "DVD-103", OPT_MMC_USE_PQ|OPT_MMC_PQ_BCD },
  111. { "generic-mmc", "SONY", "CD-ROM CDU31A-02", 0 },
  112. { "generic-mmc", "TEAC", "CD-532E", OPT_MMC_USE_PQ|OPT_MMC_PQ_BCD },
  113. { "generic-mmc", "TOSHIBA", "CD-ROM XM-6302B", 0 },
  114. { "plextor", "HITACHI", "DVD-ROM GD-2500", 0 },
  115. { "plextor", "NAKAMICH", "MJ-5.16S", 0 },
  116. { "plextor", "PIONEER", "CD-ROM DR-U06", OPT_DRV_GET_TOC_GENERIC },
  117. { "plextor", "PIONEER", "CD-ROM DR-U12", OPT_DRV_GET_TOC_GENERIC },
  118. { "plextor", "PIONEER", "CD-ROM DR-U16", OPT_DRV_GET_TOC_GENERIC },
  119. { "plextor", "PIONEER", "DVD-303", 0 },
  120. { "plextor", "SAF", "CD-R2006PLUS", 0 },
  121. { "plextor", "SONY", "CD-ROM", 0 },
  122. { "plextor", "SONY", "CD-ROM CDU-76", 0 },
  123. { "plextor", "TOSHIBA", "CD-ROM XM-5701TA", 0 },
  124. { "plextor", "TOSHIBA", "CD-ROM XM-6201TA", 0 },
  125. { "plextor-scan", "PLEXTOR", "CD-ROM", 0 },
  126. { "plextor-scan", "TEAC", "CD-ROM CD-532S", OPT_PLEX_USE_PQ|OPT_PLEX_PQ_BCD },
  127. { NULL, NULL, NULL, 0 }};
  128. static DriverSelectTable WRITE_DRIVER_TABLE[] = {
  129. { "cdd2600", "HP", "CD-Writer 4020", 0 },
  130. { "cdd2600", "HP", "CD-Writer 6020", 0 },
  131. { "cdd2600", "IMS", "CDD2000", 0 },
  132. { "cdd2600", "PHILIPS", "CDD2000", 0 },
  133. { "cdd2600", "PHILIPS", "CDD2600", 0 },
  134. { "generic-mmc", "HP", "CD-Writer+ 7570", OPT_MMC_CD_TEXT },
  135. { "generic-mmc", "HP", "CD-Writer+ 8100", OPT_MMC_CD_TEXT },
  136. { "generic-mmc", "HP", "CD-Writer+ 8200", OPT_MMC_CD_TEXT },
  137. { "generic-mmc", "MATSHITA", "CD-R   CW-7502", 0 },
  138. { "generic-mmc", "MATSHITA", "CD-R   CW-7503", 0 },
  139. { "generic-mmc", "MATSHITA", "CD-R   CW-7582", 0 },
  140. { "generic-mmc", "MEMOREX", "CD-RW4224", 0 },
  141. { "generic-mmc", "MITSUMI", "CR-4801", 0 },
  142. { "generic-mmc", "PANASONIC", "CD-R   CW-7582", 0 },
  143. { "generic-mmc", "PHILIPS", "PCA460RW", 0 },
  144. { "generic-mmc", "PLEXTOR", "CD-R   PX-R412", OPT_MMC_USE_PQ|OPT_MMC_READ_ISRC },
  145. { "generic-mmc", "PLEXTOR", "CD-R   PX-R820", 0 },
  146. { "generic-mmc", "PLEXTOR", "CD-R   PX-W4220", OPT_MMC_CD_TEXT },
  147. { "generic-mmc", "SONY", "CRX100", OPT_MMC_CD_TEXT },
  148. { "generic-mmc", "TEAC", "CD-R56", OPT_MMC_USE_PQ|OPT_MMC_CD_TEXT },
  149. { "generic-mmc", "TRAXDATA", "CDRW4260", 0 },
  150. { "generic-mmc", "WAITEC", "WT624", 0 },
  151. { "generic-mmc", "YAMAHA", "CDR200", 0 },
  152. { "generic-mmc", "YAMAHA", "CDR400", 0 },
  153. { "generic-mmc", "YAMAHA", "CRW2260", 0 },
  154. { "generic-mmc", "YAMAHA", "CRW4260", 0 },
  155. { "generic-mmc", "YAMAHA", "CRW4416", 0 },
  156. { "generic-mmc", "YAMAHA", "CRW6416", 0 },
  157. { "generic-mmc-raw", "ATAPI", "CD-R/RW CRW6206A", 0 },
  158. { "generic-mmc-raw", "BTC", "BCE621E", 0 },
  159. { "generic-mmc-raw", "HP", "CD-Writer+ 7100", 0 },
  160. { "generic-mmc-raw", "HP", "CD-Writer+ 7200", 0 },
  161. { "generic-mmc-raw", "IDE-CD", "R/RW 2x2x24", 0 },
  162. { "generic-mmc-raw", "MEMOREX", "CDRW-2216", 0 },
  163. { "generic-mmc-raw", "MEMOREX", "CR-622", 0 },
  164. { "generic-mmc-raw", "MEMOREX", "CRW-1662", 0 },
  165. { "generic-mmc-raw", "MITSUMI", "CR-4802", 0 },
  166. { "generic-mmc-raw", "PHILIPS", "CDD3600", 0 },
  167. { "generic-mmc-raw", "PHILIPS", "CDD3610", 0 },
  168. { "generic-mmc-raw", "TRAXDATA", "CDRW2260+", 0 },
  169. { "generic-mmc-raw", "TRAXDATA", "CRW2260 PRO", 0 },
  170. { "generic-mmc-raw", "WAITEC", "WT4424", 0 },
  171. { "ricoh-mp6200", "PHILIPS", "OMNIWRITER26", 0 },
  172. { "ricoh-mp6200", "RICOH", "MP6200", 0 },
  173. { "ricoh-mp6200", "RICOH", "MP6201", 0 },
  174. { "sony-cdu920", "SONY", "CD-R   CDU920", 0 },
  175. { "sony-cdu920", "SONY", "CD-R   CDU924", 0 },
  176. { "sony-cdu948", "SONY", "CD-R   CDU948", 0 },
  177. { "taiyo-yuden", "T.YUDEN", "CD-WO EW-50", 0 },
  178. { "teac-cdr55", "SAF", "CD-R2006PLUS", 0 },
  179. { "teac-cdr55", "SAF", "CD-R4012", 0 },
  180. { "teac-cdr55", "SAF", "CD-RW 226", 0 },
  181. { "teac-cdr55", "TEAC", "CD-R50", 0 },
  182. { "teac-cdr55", "TEAC", "CD-R55", 0 },
  183. { "teac-cdr55", "TRAXDATA", "CDR4120", 0 },
  184. { "yamaha-cdr10x", "YAMAHA", "CDR100", 0 },
  185. { "yamaha-cdr10x", "YAMAHA", "CDR102", 0 },
  186. { NULL, NULL, NULL, 0 }};
  187. static DriverTable DRIVERS[] = {
  188. { "cdd2600", &CDD2600::instance },
  189. { "generic-mmc", &GenericMMC::instance },
  190. { "generic-mmc-raw", &GenericMMCraw::instance },
  191. { "plextor", &PlextorReader::instance },
  192. { "plextor-scan", &PlextorReaderScan::instance },
  193. { "ricoh-mp6200", &RicohMP6200::instance },
  194. { "sony-cdu920", &SonyCDU920::instance },
  195. { "sony-cdu948", &SonyCDU948::instance },
  196. { "taiyo-yuden", &TaiyoYuden::instance },
  197. { "teac-cdr55", &TeacCdr55::instance },
  198. { "yamaha-cdr10x", &YamahaCDR10x::instance },
  199. { NULL, NULL }};
  200. struct CDRVendorTable {
  201.   char m1, s1, f1; // 1st vendor code
  202.   char m2, s2, f2; // 2nd vendor code
  203.   const char *id;  // vendor ID
  204. };
  205. static CDRVendorTable VENDOR_TABLE[] = {
  206.   // permanent codes
  207.   { 97,28,30,  97,46,50, "Auvistar Industry Co.,Ltd." },
  208.   { 97,26,60,  97,46,60, "CMC Magnetics Corporation" },
  209.   { 97,23,10,  0,0,0,    "Doremi Media Co., Ltd." },
  210.   { 97,26,00,  97,45,00, "FORNET INTERNATIONAL PTE LTD." },
  211.   { 97,46,40,  97,46,40, "FUJI Photo Film Co., Ltd." },
  212.   { 97,26,40,  0,0,0,    "FUJI Photo Film Co., Ltd." },
  213.   { 97,28,10,  97,49,10, "GIGASTORAGE CORPORATION" },
  214.   { 97,25,20,  97,47,10, "Hitachi Maxell, Ltd." },
  215.   { 97,27,40,  97,48,10, "Kodak Japan Limited" },
  216.   { 97,26,50,  97,48,60, "Lead Data Inc." },
  217.   { 97,27,50,  97,48,50, "Mitsui Chemicals, Inc." },
  218.   { 97,34,20,  97,50,20, "Mitsubishi Chemical Corporation" },
  219.   { 97,28,20,  97,46,20, "Multi Media Masters & Machinary SA" },
  220.   { 97,21,40,  0,0,0,    "Optical Disc Manufacturing Equipment" },
  221.   { 97,27,30,  97,48,30, "Pioneer Video Corporation" },
  222.   { 97,27,10,  97,48,20, "Plasmon Data systems Ltd." },
  223.   { 97,26,10,  97,47,40, "POSTECH Corporation" },
  224.   { 97,27,20,  97,47,20, "Princo Corporation" },
  225.   { 97,32,10,  0,0,0,    "Prodisc Technology Inc." },
  226.   { 97,27,60,  97,48,00, "Ricoh Company Limited" },
  227.   { 97,31,00,  97,47,50, "Ritek Co." },
  228.   { 97,26,20,  0,0,0,    "SKC Co., Ltd." },
  229.   { 97,24,10,  0,0,0,    "SONY Corporation" },
  230.   { 97,24,00,  97,46,00, "Taiyo Yuden Company Limited" },
  231.   { 97,32,00,  97,49,00, "TDK Corporation" },
  232.   { 97,25,60,  97,45,60, "Xcitek Inc." },
  233.   // tentative codes
  234.   { 97,22,60,  97,45,20, "Acer Media Technology, Inc" },
  235.   { 97,25,50,  0,0,0,    "AMS Technology Inc." },
  236.   { 97,23,30,  0,0,0,    "AUDIO DISTRIBUTORS CO., LTD." },
  237.   { 97,30,10,  97,50,30, "CDA Datentraeger Albrechts GmbH" },
  238.   { 97,22,40,  97,45,40, "CIS Technology Inc." },
  239.   { 97,24,20,  97,46,30, "Computer Support Italy s.r.l." },
  240.   { 97,23,60,  0,0,0,    "Customer Pressing Oosterhout" },
  241.   { 97,27,00,  97,48,40, "DIGITAL STORAGE TECHNOLOGY CO.,LTD" },
  242.   { 97,31,30,  97,51,10, "Grand Advance Technology Ltd." },
  243.   { 97,24,50,  97,45,50, "Guann Yinn Co.,Ltd." },
  244.   { 97,25,30,  97,51,20, "INFODISC Technology Co., Ltd." },
  245.   { 97,28,40,  97,49,20, "King Pro Mediatek Inc." },
  246.   { 97,23,00,  97,49,60, "Matsushita Electric Industrial Co., Ltd." },
  247.   { 97,15,20,  0,0,0,    "Mitsubishi Chemical Corporation" },
  248.   { 97,23,20,  0,0,0,    "Nacar Media sr" },
  249.   { 97,26,30,  0,0,0,    "OPTICAL DISC CORPRATION" },
  250.   { 97,28,00,  97,49,30, "Opti.Me.S. S.p.A." },
  251.   { 97,23,50,  0,0,0,    "OPTROM.INC." },
  252.   { 97,47,60,  0,0,0,    "Prodisc Technology Inc." },
  253.   { 97,15,10,  0,0,0,    "Ritek Co." },
  254.   { 97,29,00,  0,0,0,    "Taeil Media Co.,Ltd." },
  255.   { 97,15,00,  0,0,0,    "TDK Corporation." },
  256.   { 97,24,30,  97,45,10, "UNITECH JAPAN INC." },
  257.   { 97,29,10,  97,50,10, "Vanguard Disc Inc." },
  258.   { 97,22,00,  0,0,0,    "Woongjin Media corp." },
  259.   { 0, 0, 0,  0, 0, 0,  NULL}
  260. };
  261. unsigned char CdrDriver::syncPattern[12] = {
  262.   0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0
  263. };
  264. const char *CdrDriver::selectDriver(int readWrite, const char *vendor,
  265.     const char *model, unsigned long *options)
  266. {
  267.   DriverSelectTable *run;
  268.   DriverSelectTable *match = NULL;
  269.   unsigned int matchLen = 0;
  270.   run = (readWrite == 0) ? READ_DRIVER_TABLE : WRITE_DRIVER_TABLE;
  271.   while (run->driverId != NULL) {
  272.     if (strcmp(run->vendor, vendor) == 0 && 
  273. strstr(model, run->model) != NULL) {
  274.       if (match == NULL || strlen(run->model) > matchLen) {
  275. match = run;
  276. matchLen = strlen(run->model);
  277.       }
  278.     }
  279.     run++;
  280.   }
  281.   if (match != NULL) {
  282.     *options = match->options;
  283.     return match->driverId;
  284.   }
  285.   return NULL;
  286. }
  287. CdrDriver *CdrDriver::createDriver(const char *driverId, unsigned long options,
  288.    ScsiIf *scsiIf)
  289. {
  290.   DriverTable *run = DRIVERS;
  291.   while (run->driverId != NULL) {
  292.     if (strcmp(run->driverId, driverId) == 0) 
  293.       return run->constructor(scsiIf, options);
  294.     run++;
  295.   }
  296.   return NULL;
  297. }
  298. void CdrDriver::printDriverIds()
  299. {
  300.   DriverTable *run = DRIVERS;
  301.   while (run->driverId != NULL) {
  302.     message(0, "%s", run->driverId);
  303.     run++;
  304.   }
  305. }
  306. CdrDriver::CdrDriver(ScsiIf *scsiIf, unsigned long options) 
  307. {
  308.   size16 byteOrderTest = 1;
  309.   char *byteOrderTestP = (char*)&byteOrderTest;
  310.   options_ = options;
  311.   scsiIf_ = scsiIf;
  312.   toc_ = NULL;
  313.   if (*byteOrderTestP == 1)
  314.     hostByteOrder_ = 0; // little endian
  315.   else
  316.     hostByteOrder_ = 1; // big endian
  317.   audioDataByteOrder_ = 0; // default to little endian
  318.   fastTocReading_ = 0;
  319.   rawDataReading_ = 0;
  320.   padFirstPregap_ = 1;
  321.   onTheFly_ = 0;
  322.   onTheFlyFd_ = -1;
  323.   multiSession_ = 0;
  324.   encodingMode_ = 0;
  325.   blockLength_ = 0;
  326.   blocksPerWrite_ = 0;
  327.   zeroBuffer_ = NULL;
  328.   transferBuffer_ = new (unsigned char)[scsiIf_->maxDataLen()];
  329.   maxScannedSubChannels_ = scsiIf_->maxDataLen() / (AUDIO_BLOCK_LEN + 96);
  330.   scannedSubChannels_ = new (SubChannel*)[maxScannedSubChannels_];
  331.   paranoia_ = NULL;
  332.   paranoiaDrive_ = NULL;
  333.   paranoiaMode(3); // full paranoia but allow skip
  334. }
  335. CdrDriver::~CdrDriver()
  336. {
  337.   toc_ = NULL;
  338.   delete[] zeroBuffer_;
  339.   zeroBuffer_ = NULL;
  340.   delete[] transferBuffer_;
  341.   transferBuffer_ = NULL;
  342.   delete [] scannedSubChannels_;
  343.   scannedSubChannels_ = NULL;
  344. }
  345. // Sets multi session mode. 0: close session, 1: open next session
  346. // Return: 0: OK
  347. //         1: multi session not supported by driver
  348. int CdrDriver::multiSession(int m)
  349. {
  350.   multiSession_ = m != 0 ? 1 : 0;
  351.   return 0;
  352. }
  353. void CdrDriver::onTheFly(int fd)
  354. {
  355.   if (fd >= 0) {
  356.     onTheFly_ = 1;
  357.     onTheFlyFd_ = fd;
  358.   }
  359.   else {
  360.     onTheFly_ = 0;
  361.     onTheFlyFd_ = -1;
  362.   }
  363. }
  364. int CdrDriver::cdrVendor(Msf &code, const char **vendorId, 
  365.  const char **mediumType)
  366. {
  367.   CDRVendorTable *run = VENDOR_TABLE;
  368.   *vendorId = NULL;
  369.   char m = code.min();
  370.   char s = code.sec();
  371.   char f = code.frac();
  372.   char type = f % 10;
  373.   f -= type;
  374.   while (run->id != NULL) {
  375.     if ((run->m1 == m && run->s1 == s && run->f1 == f) ||
  376. (run->m2 == m && run->s2 == s && run->f2 == f)) {
  377.       *vendorId = run->id;
  378.       break;
  379.     }
  380.     run++;
  381.   }
  382.   if (*vendorId != NULL) {
  383.     if (type < 5) {
  384.       *mediumType = "Long Strategy Type, e.g. Cyanine";
  385.     }
  386.     else {
  387.       *mediumType = "Short Strategy Type, e.g. Phthalocyanine";
  388.     }
  389.     return 1;
  390.   }
  391.   return 0;
  392. }
  393. // Sends SCSI command via 'scsiIf_'.
  394. // return: see 'ScsiIf::sendCmd()'
  395. int CdrDriver::sendCmd(const unsigned char *cmd, int cmdLen,
  396.        const unsigned char *dataOut, int dataOutLen,
  397.        unsigned char *dataIn, int dataInLen,
  398.        int showErrorMsg) const
  399. {
  400.   return scsiIf_->sendCmd(cmd, cmdLen, dataOut, dataOutLen, dataIn,
  401.   dataInLen, showErrorMsg);
  402. }
  403. // checks if unit is ready
  404. // return: 0: OK
  405. //         1: scsi command failed
  406. //         2: not ready
  407. //         3: not ready, no disk in drive
  408. //         4: not ready, tray out
  409. int CdrDriver::testUnitReady(int ignoreUnitAttention) const
  410. {
  411.   unsigned char cmd[6];
  412.   const unsigned char *sense;
  413.   int senseLen;
  414.   memset(cmd, 0, 6);
  415.   switch (scsiIf_->sendCmd(cmd, 6, NULL, 0, NULL, 0, 0)) {
  416.   case 1:
  417.     return 1;
  418.   case 2:
  419.     sense = scsiIf_->getSense(senseLen);
  420.     
  421.     int code = sense[2] & 0x0f;
  422.     if (code == 0x02) {
  423.       // not ready
  424.       return 2;
  425.     }
  426.     else if (code != 0x06) {
  427.       scsiIf_->printError();
  428.       return 1;
  429.     }
  430.     else {
  431.       return 0;
  432.     }
  433.   }
  434.   return 0;
  435. }
  436. int CdrDriver::speed2Mult(int speed)
  437. {
  438.   return speed / 176;
  439. }
  440. int CdrDriver::mult2Speed(int mult)
  441. {
  442.   return mult * 177;
  443. }
  444. // start unit ('startStop' == 1) or stop unit ('startStop' == 0)
  445. // return: 0: OK
  446. //         1: scsi command failed
  447. int CdrDriver::startStopUnit(int startStop) const
  448. {
  449.   unsigned char cmd[6];
  450.   memset(cmd, 0, 6);
  451.   cmd[0] = 0x1b;
  452.   
  453.   if (startStop != 0) {
  454.     cmd[4] |= 0x01;
  455.   }
  456.   if (sendCmd(cmd, 6, NULL, 0, NULL, 0) != 0) {
  457.     message(-2, "Cannot start/stop unit.");
  458.     return 1;
  459.   }
  460.   return 0;
  461. }
  462. // blocks or unblocks tray
  463. // return: 0: OK
  464. //         1: scsi command failed
  465. int CdrDriver::preventMediumRemoval(int block) const
  466. {
  467.   unsigned char cmd[6];
  468.   memset(cmd, 0, 6);
  469.   cmd[0] = 0x1e;
  470.   
  471.   if (block != 0) {
  472.     cmd[4] |= 0x01;
  473.   }
  474.   if (sendCmd(cmd, 6, NULL, 0, NULL, 0) != 0) {
  475.     message(-2, "Cannot prevent/allow medium removal.");
  476.     return 1;
  477.   }
  478.   return 0;
  479. }
  480. // reset device to initial state
  481. // return: 0: OK
  482. //         1: scsi command failed
  483. int CdrDriver::rezeroUnit(int showMessage) const
  484. {
  485.   unsigned char cmd[6];
  486.   memset(cmd, 0, 6);
  487.   cmd[0] = 0x01;
  488.   
  489.   if (sendCmd(cmd, 6, NULL, 0, NULL, 0, showMessage) != 0) {
  490.     if (showMessage)
  491.       message(-2, "Cannot rezero unit.");
  492.     return 1;
  493.   }
  494.   return 0;
  495. }
  496. // Flushs cache of drive which inidcates end of write action. Errors resulting
  497. // from this command are ignored because everything is already done and
  498. // at most the last part of the lead-out track may be affected.
  499. // return: 0: OK
  500. int CdrDriver::flushCache() const
  501. {
  502.   unsigned char cmd[10];
  503.   memset(cmd, 0, 10);
  504.   cmd[0] = 0x35; // FLUSH CACHE
  505.   
  506.   // Print no message if the flush cache command fails because some drives
  507.   // report errors even if all went OK.
  508.   sendCmd(cmd, 10, NULL, 0, NULL, 0, 0);
  509.   return 0;
  510. }
  511. // Reads the cd-rom capacity and stores the total number of available blocks
  512. // in 'length'.
  513. // return: 0: OK
  514. //         1: SCSI command failed
  515. int CdrDriver::readCapacity(long *length, int showMessage)
  516. {
  517.   unsigned char cmd[10];
  518.   unsigned char data[8];
  519.   memset(cmd, 0, 10);
  520.   memset(data, 0, 8);
  521.   cmd[0] = 0x25; // READ CD-ROM CAPACITY
  522.   if (sendCmd(cmd, 10, NULL, 0, data, 8, showMessage) != 0) {
  523.     if (showMessage)
  524.       message(-2, "Cannot read capacity.");
  525.     return 1;
  526.   }
  527.   
  528.   *length = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
  529.   // *length += 1;
  530.   return 0;
  531. }
  532. int CdrDriver::blankDisk()
  533. {
  534.   message(-2, "Blanking is not supported by this driver.");
  535.   return 1;
  536. }
  537. // Writes data to target, the block length depends on the actual writing mode
  538. // 'mode'. 'len' is number of blocks to write.
  539. // 'lba' specifies the next logical block address for writing and is updated
  540. // by this function.
  541. // return: 0: OK
  542. //         1: scsi command failed
  543. int CdrDriver::writeData(TrackData::Mode mode, long &lba, const char *buf,
  544.  long len)
  545. {
  546.   assert(blocksPerWrite_ > 0);
  547.   int writeLen = 0;
  548.   unsigned char cmd[10];
  549.   long blockLength = blockSize(mode);
  550.   
  551. #if 0
  552.   long sum, i;
  553.   sum = 0;
  554.   for (i = 0; i < len * blockLength; i++) {
  555.     sum += buf[i];
  556.   }
  557.   message(0, "W: %ld: %ld, %ld, %ld", lba, blockLength, len, sum);
  558. #endif
  559.   memset(cmd, 0, 10);
  560.   cmd[0] = 0x2a; // WRITE1
  561.   
  562.   while (len > 0) {
  563.     writeLen = (len > blocksPerWrite_ ? blocksPerWrite_ : len);
  564.     cmd[2] = lba >> 24;
  565.     cmd[3] = lba >> 16;
  566.     cmd[4] = lba >> 8;
  567.     cmd[5] = lba;
  568.     cmd[7] = writeLen >> 8;
  569.     cmd[8] = writeLen & 0xff;
  570.     if (sendCmd(cmd, 10, (unsigned char *)buf, writeLen * blockLength,
  571. NULL, 0) != 0) {
  572.       message(-2, "Write data failed.");
  573.       return 1;
  574.     }
  575.     buf += writeLen * blockLength;
  576.     lba += writeLen;
  577.     len -= writeLen;
  578.   }
  579.       
  580.   return 0;
  581. }
  582. // Writes 'count' blocks with zero data with 'writeData'.
  583. // m: mode for encoding zero data
  584. // lba: logical block address for the write command, will be updated
  585. // encLba: logical block address used by the LE-C encoder for the
  586. //         sector headers
  587. // count: number of zero blocks to write
  588. // Return: 0: OK
  589. //         1: SCSI error occured
  590. int CdrDriver::writeZeros(TrackData::Mode m, long &lba, long encLba,
  591.   long count)
  592. {
  593.   assert(blocksPerWrite_ > 0);
  594.   assert(zeroBuffer_ != NULL);
  595.   int n, i;
  596.   long cnt = 0;
  597.   long total = count * AUDIO_BLOCK_LEN;
  598.   long cntMb;
  599.   long lastMb = 0;
  600.   long blockLen;
  601.   if (encodingMode_ == 0)
  602.     blockLen = AUDIO_BLOCK_LEN;
  603.   else 
  604.     blockLen = blockSize(m);
  605.   //FILE *fp = fopen("zeros.out", "w");
  606.   while (count > 0) {
  607.     n = (count > blocksPerWrite_ ? blocksPerWrite_ : count);
  608.     for (i = 0; i < n; i++) {
  609.       Track::encodeZeroData(encodingMode_, m, encLba++,
  610.     zeroBuffer_ + i * blockLen);
  611.     }
  612.     if (encodingMode_ == 0 && bigEndianSamples() == 0) {
  613.       // swap encoded data blocks
  614.       swapSamples((Sample *)zeroBuffer_, n * SAMPLES_PER_BLOCK);
  615.     }
  616.     //fwrite(zeroBuffer_, blockLen, n, fp);
  617.     if (writeData(encodingMode_ == 0 ? TrackData::AUDIO : m, lba, zeroBuffer_,
  618.   n) != 0) {
  619.       return 1;
  620.     }
  621.     
  622.     cnt += n * AUDIO_BLOCK_LEN;
  623.     cntMb = cnt >> 20;
  624.     if (cntMb > lastMb) {
  625.       message(1, "Wrote %ld of %ld MB.r", cntMb, total >> 20);
  626.       fflush(stdout);
  627.       lastMb = cntMb;
  628.     }
  629.     count -= n;
  630.   }
  631.   //fclose(fp);
  632.   return 0;
  633. }
  634. // Requests mode page 'pageCode' from device and places it into given
  635. // buffer of maximum length 'bufLen'.
  636. // modePageHeader: if != NULL filled with mode page header (8 bytes)
  637. // blockDesc     : if != NULL filled with block descriptor (8 bytes),
  638. //                 buffer is zeroed if no block descriptor is received
  639. // return: 0: OK
  640. //         1: scsi command failed
  641. //         2: buffer too small for requested mode page
  642. int CdrDriver::getModePage(int pageCode, unsigned char *buf, long bufLen,
  643.    unsigned char *modePageHeader,
  644.    unsigned char *blockDesc,
  645.    int showErrorMsg)
  646. {
  647.   unsigned char cmd[10];
  648.   long dataLen = bufLen + 8/*mode parameter header*/ + 
  649.                           100/*spare for block descriptors*/;
  650.   unsigned char *data = new (unsigned char)[dataLen];
  651.   memset(cmd, 0, 10);
  652.   memset(data, 0, dataLen);
  653.   memset(buf, 0, bufLen);
  654.   cmd[0] = 0x5a; // MODE SENSE
  655.   cmd[2] = pageCode & 0x3f;
  656.   cmd[7] = dataLen >> 8;
  657.   cmd[8] = dataLen;
  658.   if (sendCmd(cmd, 10, NULL, 0, data, dataLen,  showErrorMsg) != 0) {
  659.     delete[] data;
  660.     return 1;
  661.   }
  662.   long modeDataLen = (data[0] << 8) | data[1];
  663.   long blockDescLen = (data[6] << 8) | data[7];
  664.   if (modePageHeader != NULL)
  665.     memcpy(modePageHeader, data, 8);
  666.   if (blockDesc != NULL) {
  667.     if (blockDescLen >= 8)
  668.       memcpy(blockDesc, data + 8, 8);
  669.     else 
  670.       memset(blockDesc, 0, 8);
  671.   }
  672.   if (modeDataLen > blockDescLen + 6) {
  673.     unsigned char *modePage = data + blockDescLen + 8;
  674.     long modePageLen = modePage[1] + 2;
  675.     if (modePageLen > bufLen) {
  676.       message(-2, "Requested mode page exceeds provided buffer size.");
  677.       delete[] data;
  678.       return 2;
  679.     }
  680.     else {
  681.       memcpy(buf, modePage, modePageLen);
  682.       delete[] data;
  683.       return 0;
  684.     }
  685.   }
  686.   else {
  687.     message(-2, "No mode page data received.");
  688.     delete[] data;
  689.     return 1;
  690.   }
  691. }
  692. // Sets mode page in device specified in buffer 'modePage'
  693. // modePageHeader: if != NULL used as mode page header (8 bytes)
  694. // blockDesc     : if != NULL used as block descriptor (8 bytes),
  695. // Return: 0: OK
  696. //         1: SCSI command failed
  697. int CdrDriver::setModePage(const unsigned char *modePage,
  698.    const unsigned char *modePageHeader,
  699.    const unsigned char *blockDesc,
  700.    int showErrorMsg)
  701. {
  702.   long pageLen = modePage[1] + 2;
  703.   unsigned char cmd[10];
  704.   long dataLen = pageLen + 8/*mode parameter header*/;
  705.   if (blockDesc != NULL)
  706.     dataLen += 8;
  707.   unsigned char *data = new (unsigned char)[dataLen];
  708.   memset(cmd, 0, 10);
  709.   memset(data, 0, dataLen);
  710.   if (modePageHeader != NULL)
  711.     memcpy(data, modePageHeader, 8);
  712.   data[0] = 0;
  713.   data[1] = 0;
  714.   data[4] = 0;
  715.   data[5] = 0;
  716.   if (blockDesc != NULL) {
  717.     memcpy(data + 8, blockDesc, 8);
  718.     memcpy(data + 16, modePage, pageLen);
  719.     data[6] = 0;
  720.     data[7] = 8;
  721.   }
  722.   else {
  723.     memcpy(data + 8, modePage, pageLen);
  724.     data[6] = 0;
  725.     data[7] = 0;
  726.   }
  727.   cmd[0] = 0x55; // MODE SELECT
  728.   cmd[1] = 1 << 4;
  729.   cmd[7] = dataLen >> 8;
  730.   cmd[8] = dataLen;
  731.   if (sendCmd(cmd, 10, data, dataLen, NULL, 0, showErrorMsg) != 0) {
  732.     delete[] data;
  733.     return 1;
  734.   }
  735.   delete[] data;
  736.   return 0;
  737. }
  738. // As above, but implemented with six byte mode commands
  739. // Requests mode page 'pageCode' from device and places it into given
  740. // buffer of maximum length 'bufLen'.
  741. // modePageHeader: if != NULL filled with mode page header (4 bytes)
  742. // blockDesc     : if != NULL filled with block descriptor (8 bytes),
  743. //                 buffer is zeroed if no block descriptor is received
  744. // return: 0: OK
  745. //         1: scsi command failed
  746. //         2: buffer too small for requested mode page
  747. int CdrDriver::getModePage6(int pageCode, unsigned char *buf, long bufLen,
  748.     unsigned char *modePageHeader,
  749.     unsigned char *blockDesc,
  750.     int showErrorMsg)
  751. {
  752.   unsigned char cmd[6];
  753.   long dataLen = bufLen + 4/*mode parameter header*/ + 
  754.                           100/*spare for block descriptors*/;
  755.   unsigned char *data = new (unsigned char)[dataLen];
  756.   memset(cmd, 0, 6);
  757.   memset(data, 0, dataLen);
  758.   memset(buf, 0, bufLen);
  759.   cmd[0] = 0x1a; // MODE SENSE(6)
  760.   cmd[2] = pageCode & 0x3f;
  761.   cmd[4] = (dataLen > 255) ? 0 : dataLen;
  762.   if (sendCmd(cmd, 6, NULL, 0, data, dataLen,  showErrorMsg) != 0) {
  763.     delete[] data;
  764.     return 1;
  765.   }
  766.   long modeDataLen = data[0];
  767.   long blockDescLen = data[3];
  768.   if (modePageHeader != NULL)
  769.     memcpy(modePageHeader, data, 4);
  770.   if (blockDesc != NULL) {
  771.     if (blockDescLen >= 8)
  772.       memcpy(blockDesc, data + 4, 8);
  773.     else 
  774.       memset(blockDesc, 0, 8);
  775.   }
  776.   if (modeDataLen > blockDescLen + 4) {
  777.     unsigned char *modePage = data + blockDescLen + 4;
  778.     long modePageLen = modePage[1] + 2;
  779.     if (modePageLen > bufLen) {
  780.       message(-2, "Requested mode page exceeds provided buffer size.");
  781.       delete[] data;
  782.       return 2;
  783.     }
  784.     else {
  785.       memcpy(buf, modePage, modePageLen);
  786.       delete[] data;
  787.       return 0;
  788.     }
  789.   }
  790.   else {
  791.     message(-2, "No mode page data received.");
  792.     delete[] data;
  793.     return 1;
  794.   }
  795. }
  796.  
  797. // Sets mode page in device specified in buffer 'modePage'
  798. // modePageHeader: if != NULL used as mode page header (4 bytes)
  799. // blockDesc     : if != NULL used as block descriptor (8 bytes),
  800. // Return: 0: OK
  801. //         1: SCSI command failed
  802. int CdrDriver::setModePage6(const unsigned char *modePage,
  803.     const unsigned char *modePageHeader,
  804.     const unsigned char *blockDesc,
  805.     int showErrorMsg)
  806. {
  807.   long pageLen = modePage[1] + 2;
  808.   unsigned char cmd[6];
  809.   long dataLen = pageLen + 4/*mode parameter header*/;
  810.   if (blockDesc != NULL)
  811.     dataLen += 8;
  812.   unsigned char *data = new (unsigned char)[dataLen];
  813.   memset(cmd, 0, 6);
  814.   memset(data, 0, dataLen);
  815.   if (modePageHeader != NULL)
  816.     memcpy(data, modePageHeader, 4);
  817.   data[0] = 0;
  818.   if (blockDesc != NULL) {
  819.     memcpy(data + 4, blockDesc, 8);
  820.     memcpy(data + 12, modePage, pageLen);
  821.     data[3] = 8;
  822.   }
  823.   else {
  824.     memcpy(data + 4, modePage, pageLen);
  825.     data[3] = 0;
  826.   }
  827.   cmd[0] = 0x15; // MODE SELECT(6)
  828.   cmd[1] = 1 << 4;
  829.   cmd[4] = dataLen;
  830.   if (sendCmd(cmd, 6, data, dataLen, NULL, 0, showErrorMsg) != 0) {
  831.     delete[] data;
  832.     return 1;
  833.   }
  834.   delete[] data;
  835.   return 0;
  836. }
  837. // Retrieves TOC data of inserted CD. It won't distinguish between different
  838. // sessions.
  839. // The track information is returend either for all sessions or for the
  840. // first session depending on the drive. 'cdTocLen' is filled with number
  841. // of entries including the lead-out track.
  842. // Return: 'NULL' on error, else array of 'CdToc' structures with '*cdTocLen'
  843. // entries 
  844. CdToc *CdrDriver::getTocGeneric(int *cdTocLen)
  845. {
  846.   unsigned char cmd[10];
  847.   unsigned short dataLen;
  848.   unsigned char *data = NULL;;
  849.   unsigned char reqData[4]; // buffer for requestion the actual length
  850.   unsigned char *p = NULL;
  851.   int i;
  852.   CdToc *toc;
  853.   int nTracks;
  854.   // read disk toc length
  855.   memset(cmd, 0, 10);
  856.   cmd[0] = 0x43; // READ TOC
  857.   cmd[6] = 0; // return info for all tracks
  858.   cmd[8] = 4;
  859.   
  860.   if (sendCmd(cmd, 10, NULL, 0, reqData, 4) != 0) {
  861.     message(-2, "Cannot read disk toc.");
  862.     return NULL;
  863.   }
  864.   dataLen = (reqData[0] << 8) | reqData[1];
  865.   dataLen += 2;
  866.   message(3, "getTocGeneric: data len %d", dataLen);
  867.   if (dataLen < 12) {
  868.     dataLen = (100 * 8) + 4;
  869.   }
  870.   data = new (unsigned char)[dataLen];
  871.   memset(data, 0, dataLen);
  872.   // read disk toc
  873.   cmd[7] = dataLen >> 8;
  874.   cmd[8] = dataLen;
  875.   
  876.   if (sendCmd(cmd, 10, NULL, 0, data, dataLen) != 0) {
  877.     message(-2, "Cannot read disk toc.");
  878.     delete[] data;
  879.     return NULL;
  880.   }
  881.   nTracks = data[3] - data[2] + 1;
  882.   if (nTracks > 99) {
  883.     message(-2, "Got illegal toc data.");
  884.     delete[] data;
  885.     return NULL;
  886.   }
  887.   toc = new CdToc[nTracks + 1];
  888.   
  889.   for (i = 0, p = data + 4; i <= nTracks; i++, p += 8) {
  890.     toc[i].track = p[2];
  891.     toc[i].adrCtl = p[1];
  892.     toc[i].start = (p[4] << 24) | (p[5] << 16) | (p[6] << 8) | p[7];
  893.   }
  894.   *cdTocLen = nTracks + 1;
  895.   delete[] data;
  896.   return toc;
  897. }
  898. // Retrieves TOC data of inserted CD. The track information is returend for
  899. // specified session number only. The lead-out start is taken from the
  900. // correct session so that it can be used to calculate the length of the
  901. // last track.
  902. // 'cdTocLen' is filled with number of entries including the lead-out track.
  903. // Return: 'NULL' on error, else array of 'CdToc' structures with '*cdTocLen'
  904. // entries 
  905. #define IS_BCD(v) (((v) & 0xf0) <= 0x90 && ((v) & 0x0f) <= 0x09)
  906. CdToc *CdrDriver::getToc(int sessionNr, int *cdTocLen)
  907. {
  908.   int rawTocLen;
  909.   int completeTocLen;
  910.   CdToc *completeToc; // toc retrieved with generic method to verify with raw
  911.                       // toc data
  912.   CdToc *cdToc;
  913.   CdRawToc *rawToc;
  914.   int i, j, tocEnt;
  915.   int nTracks = 0;
  916.   int trackNr;
  917.   long trackStart;
  918.   int isBcd = -1;
  919.   int lastTrack;
  920.   int min, sec, frame;
  921.   if ((completeToc = getTocGeneric(&completeTocLen)) == NULL)
  922.     return NULL;
  923.   if (options_ & OPT_DRV_GET_TOC_GENERIC) {
  924.     *cdTocLen = completeTocLen;
  925.     return completeToc;
  926.   }
  927.   if ((rawToc = getRawToc(1, &rawTocLen)) == NULL) {
  928.     *cdTocLen = completeTocLen;
  929.     return completeToc;
  930.   }
  931.   // Try to determine if raw toc data contains BCD or HEX numbers.
  932.   for (i = 0; i < rawTocLen; i++) {
  933.     if ((rawToc[i].adrCtl & 0xf0) == 0x10) { // only process QMODE1 entries
  934.       if (rawToc[i].point < 0xa0 && !IS_BCD(rawToc[i].point)) {
  935. isBcd = 0;
  936.       }
  937.       if (rawToc[i].point < 0xa0 || rawToc[i].point == 0xa2) {
  938. if (!IS_BCD(rawToc[i].pmin) || !IS_BCD(rawToc[i].psec) ||
  939.     !IS_BCD(rawToc[i].pframe)) {
  940.   isBcd = 0;
  941.   break;
  942. }
  943.       }
  944.     }
  945.   }
  946.   if (isBcd == -1) {
  947.     // We still don't know if the values are BCD or HEX but we've ensured
  948.     // so far that all values are valid BCD numbers.
  949.     // Assume that we have BCD numbers and compare with the generic toc data.
  950.     isBcd = 1;
  951.     for (i = 0; i < rawTocLen && isBcd == 1; i++) {
  952.       if ((rawToc[i].adrCtl & 0xf0) == 0x10 && // only process QMODE1 entries
  953.   rawToc[i].point < 0xa0) { 
  954. trackNr = SubChannel::bcd2int(rawToc[i].point);
  955. for (j = 0; j < completeTocLen; j++) {
  956.   if (completeToc[j].track == trackNr) {
  957.     break;
  958.   }
  959. }
  960. if (j < completeTocLen) {
  961.   min = SubChannel::bcd2int(rawToc[i].pmin);
  962.   sec = SubChannel::bcd2int(rawToc[i].psec);
  963.   frame = SubChannel::bcd2int(rawToc[i].pframe);
  964.   if (min <= 99 && sec < 60 && frame < 75) {
  965.     trackStart = Msf(min, sec, frame).lba() - 150;
  966.     if (completeToc[j].start != trackStart) {
  967.       // start does not match -> values are not BCD
  968.       isBcd = 0;
  969.     }
  970.   }
  971.   else {
  972.     // bogus time code -> values are not BCD
  973.     isBcd = 0;
  974.   }
  975. }
  976. else {
  977.   // track not found -> values are not BCD
  978.   isBcd = 0;
  979. }
  980.       }
  981.     }
  982.     if (isBcd == 1) {
  983.       // verify last lead-out pointer
  984.       trackStart = 0; // start of lead-out
  985.       for (i = rawTocLen - 1; i >= 0; i--) {
  986. if ((rawToc[i].adrCtl & 0xf0) == 0x10 && // QMODE1 entry
  987.     rawToc[i].point == 0xa2) {
  988.   min = SubChannel::bcd2int(rawToc[i].pmin);
  989.   sec = SubChannel::bcd2int(rawToc[i].psec);
  990.   frame = SubChannel::bcd2int(rawToc[i].pframe);
  991.   if (min <= 99 && sec < 60 && frame < 75)
  992.     trackStart = Msf(min, sec, frame).lba() - 150;
  993.   break;
  994. }
  995.       }
  996.       if (i < 0) {
  997. message(-3, "Found bogus toc data (no lead-out entry in raw data). Please report!");
  998. delete[] rawToc;
  999. delete[] completeToc;
  1000. return NULL;
  1001.       }
  1002.       for (j = 0; j < completeTocLen; j++) {
  1003. if (completeToc[j].track == 0xaa) {
  1004.   break;
  1005. }
  1006.       }
  1007.       
  1008.       if (j < completeTocLen) {
  1009. if (trackStart != completeToc[j].start) {
  1010.   // lead-out start does not match -> values are not BCD
  1011.     isBcd = 0;
  1012. }
  1013.       }
  1014.       else {
  1015. message(-3,
  1016. "Found bogus toc data (no lead-out entry). Please report!");
  1017. delete[] rawToc;
  1018. delete[] completeToc;
  1019. return NULL;
  1020.       }
  1021.     }
  1022.   }
  1023.   if (isBcd == 0) {
  1024.     // verify that the decision is really correct.
  1025.     for (i = 0; i < rawTocLen && isBcd == 0; i++) {
  1026.       if ((rawToc[i].adrCtl & 0xf0) == 0x10 && // only process QMODE1 entries
  1027.   rawToc[i].point < 0xa0) {
  1028. trackNr = rawToc[i].point;
  1029. for (j = 0; j < completeTocLen; j++) {
  1030.   if (completeToc[j].track == trackNr) {
  1031.     break;
  1032.   }
  1033. }
  1034. if (j < completeTocLen) {
  1035.   min = rawToc[i].pmin;
  1036.   sec = rawToc[i].psec;
  1037.   frame = rawToc[i].pframe;
  1038.   if (min <= 99 && sec < 60 && frame < 75) {
  1039.     trackStart = Msf(min, sec, frame).lba() - 150;
  1040.     if (completeToc[j].start != trackStart) {
  1041.       // start does not match -> values are not HEX
  1042.       isBcd = -1;
  1043.     }
  1044.   }
  1045.   else {
  1046.     // bogus time code -> values are not HEX
  1047.     isBcd = -1;
  1048.   }
  1049. }
  1050. else {
  1051.   // track not found -> values are not BCD
  1052.   isBcd = -1;
  1053. }
  1054.       }
  1055.     }
  1056.     // verify last lead-out pointer
  1057.     trackStart = 0; // start of lead-out
  1058.     for (i = rawTocLen - 1; i >= 0; i--) {
  1059.       if ((rawToc[i].adrCtl & 0xf0) == 0x10 && // QMODE1 entry
  1060.   rawToc[i].point == 0xa2) {
  1061. min = rawToc[i].pmin;
  1062. sec = rawToc[i].psec;
  1063. frame = rawToc[i].pframe;
  1064. if (min <= 99 && sec < 60 && frame < 75)
  1065.   trackStart = Msf(min, sec, frame).lba() - 150;
  1066. break;
  1067.       }
  1068.     }
  1069.     if (i < 0) {
  1070.       message(-3, "Found bogus toc data (no lead-out entry in raw data). Please report!");
  1071.       delete[] rawToc;
  1072.       delete[] completeToc;
  1073.       return NULL;
  1074.     }
  1075.     
  1076.     for (j = 0; j < completeTocLen; j++) {
  1077.       if (completeToc[j].track == 0xaa) {
  1078. break;
  1079.       }
  1080.     }
  1081.     
  1082.     if (j < completeTocLen) {
  1083.       if (trackStart != completeToc[j].start) {
  1084. // lead-out start does not match -> values are not BCD
  1085. isBcd = -1;
  1086.       }
  1087.     }
  1088.     else {
  1089.       message(-3,
  1090.       "Found bogus toc data (no lead-out entry). Please report!");
  1091.       delete[] rawToc;
  1092.       delete[] completeToc;
  1093.       return NULL;
  1094.     }
  1095.   }
  1096.   
  1097.   if (isBcd == -1) {
  1098.     message(-1, "Could not determine if raw toc data is BCD or HEX. Please report!");
  1099.     message(-1, "Using TOC data retrieved with generic method (no multi session support).");
  1100.     delete[] rawToc;
  1101.     *cdTocLen = completeTocLen;
  1102.     return completeToc;
  1103.   }
  1104.   message(3, "Raw toc contains %s values.", isBcd == 0 ? "HEX" : "BCD");
  1105.   for (i = 0; i < rawTocLen; i++) {
  1106.     if (rawToc[i].sessionNr == sessionNr &&
  1107. (rawToc[i].adrCtl & 0xf0) == 0x10 && /* QMODE1 entry */
  1108. rawToc[i].point < 0xa0) {
  1109.       nTracks++;
  1110.     }
  1111.   }
  1112.   if (nTracks == 0 || nTracks > 99) {
  1113.     message(-3, "Found bogus toc data (0 or > 99 tracks). Please report!");
  1114.     delete[] rawToc;
  1115.     delete[] completeToc;
  1116.     return NULL;
  1117.   }
  1118.   cdToc = new CdToc[nTracks + 1];
  1119.   tocEnt = 0;
  1120.   lastTrack = -1;
  1121.   for (i = 0; i < rawTocLen; i++) {
  1122.     if (rawToc[i].sessionNr == sessionNr &&
  1123. (rawToc[i].adrCtl & 0xf0) == 0x10 &&  // QMODE1 entry
  1124. rawToc[i].point < 0xa0) {
  1125.       if (isBcd) {
  1126. trackNr = SubChannel::bcd2int(rawToc[i].point);
  1127. trackStart = Msf(SubChannel::bcd2int(rawToc[i].pmin),
  1128.  SubChannel::bcd2int(rawToc[i].psec),
  1129.  SubChannel::bcd2int(rawToc[i].pframe)).lba();
  1130.       }
  1131.       else {
  1132. trackNr = rawToc[i].point;
  1133. trackStart =
  1134.   Msf(rawToc[i].pmin, rawToc[i].psec, rawToc[i].pframe).lba();
  1135.       }
  1136.       if (lastTrack != -1 && trackNr != lastTrack + 1) {
  1137. message(-3, "Found bogus toc data (track number sequence). Please report!");
  1138. delete[] rawToc;
  1139. delete[] completeToc;
  1140. delete[] cdToc;
  1141. return NULL;
  1142.       }
  1143.       lastTrack = trackNr;
  1144.       cdToc[tocEnt].adrCtl = rawToc[i].adrCtl;
  1145.       cdToc[tocEnt].track = trackNr;
  1146.       cdToc[tocEnt].start = trackStart - 150;
  1147.       tocEnt++;
  1148.     }
  1149.   }
  1150.   // find lead-out pointer
  1151.   for (i = 0; i < rawTocLen; i++) {
  1152.     if (rawToc[i].sessionNr == sessionNr &&
  1153. (rawToc[i].adrCtl & 0xf0) == 0x10 &&  // QMODE1 entry
  1154. rawToc[i].point == 0xa2 /* Lead-out pointer */) {
  1155.       if (isBcd) {
  1156. trackStart = Msf(SubChannel::bcd2int(rawToc[i].pmin),
  1157.  SubChannel::bcd2int(rawToc[i].psec),
  1158.  SubChannel::bcd2int(rawToc[i].pframe)).lba();
  1159.       }
  1160.       else {
  1161. trackStart =
  1162.   Msf(rawToc[i].pmin, rawToc[i].psec, rawToc[i].pframe).lba();
  1163.       }
  1164.       
  1165.       cdToc[tocEnt].adrCtl = rawToc[i].adrCtl;
  1166.       cdToc[tocEnt].track = 0xaa;
  1167.       cdToc[tocEnt].start = trackStart - 150;
  1168.       tocEnt++;
  1169.       break;
  1170.     }
  1171.   }
  1172.   
  1173.   if (tocEnt != nTracks + 1) {
  1174.     message(-3, "Found bogus toc data (no lead-out pointer for session). Please report!");
  1175.     delete[] rawToc;
  1176.     delete[] completeToc;
  1177.     delete[] cdToc;
  1178.     return NULL;
  1179.   }
  1180.   
  1181.   delete[] rawToc;
  1182.   delete[] completeToc;
  1183.   *cdTocLen = nTracks + 1;
  1184.   return cdToc;
  1185. }
  1186. #if 0
  1187. static void adjustPreGaps(TrackInfo *trackInfos, long nofTrackInfos)
  1188. {
  1189.   long i;
  1190.   for (i = 0; i < nofTrackInfos - 1; i++) {
  1191.     if (i == 0) {
  1192.       trackInfos[i].pregap = trackInfos[i].start;
  1193.     }
  1194.     else {
  1195.       long prevTrackLen = trackInfos[i].start - trackInfos[i - 1].start;
  1196.       if (prevTrackLen >= 6 * 75) {
  1197. if (trackInfos[i].mode == TrackData::AUDIO ||
  1198.     trackInfos[i].mode != trackInfos[i - 1].mode) {
  1199.   trackInfos[i].pregap = 2 * 75;
  1200. }
  1201.       }
  1202.     }
  1203.   }
  1204. }
  1205. #endif
  1206. static char *buildDataFileName(int trackNr, CdToc *toc, int nofTracks, 
  1207.        const char *basename, const char *extension)
  1208. {
  1209.   char buf[30];
  1210.   int start, end;
  1211.   int run;
  1212.   int onlyOneAudioRange = 1;
  1213.   // don't modify the STDIN filename
  1214.   if (strcmp(basename, "-") == 0)
  1215.     return strdupCC(basename);
  1216.   if ((toc[trackNr].adrCtl & 0x04) != 0) {
  1217.     // data track
  1218.     sprintf(buf, "_%d", trackNr + 1);
  1219.     return strdup3CC(basename, buf, NULL);
  1220.   }
  1221.   // audio track, find continues range of audio tracks
  1222.   start = trackNr;
  1223.   while (start > 0 && (toc[start - 1].adrCtl & 0x04) == 0)
  1224.     start--;
  1225.   if (start > 0) {
  1226.     run = start - 1;
  1227.     while (run >= 0) {
  1228.       if ((toc[run].adrCtl & 0x04) == 0) {
  1229. onlyOneAudioRange = 0;
  1230. break;
  1231.       }
  1232.       run--;
  1233.     }
  1234.   }
  1235.   end = trackNr;
  1236.   while (end < nofTracks - 1 && (toc[end + 1].adrCtl & 0x04) == 0)
  1237.     end++;
  1238.   if (onlyOneAudioRange && end < nofTracks - 1) {
  1239.     run = end + 1;
  1240.     while (run < nofTracks) {
  1241.       if ((toc[run].adrCtl & 0x04) == 0) {
  1242. onlyOneAudioRange = 0;
  1243. break;
  1244.       }
  1245.       run++;
  1246.     }
  1247.   }
  1248.   if (onlyOneAudioRange) {
  1249.     return strdup3CC(basename, extension, NULL);
  1250.   }
  1251.   else {
  1252.     sprintf(buf, "_%d-%d", start + 1, end + 1);
  1253.     return strdup3CC(basename, buf, extension);
  1254.   }
  1255. }
  1256. // Creates 'Toc' object for inserted CD.
  1257. // session: session that should be analyzed
  1258. // audioFilename: name of audio file that is placed into TOC
  1259. // Return: newly allocated 'Toc' object or 'NULL' on error
  1260. Toc *CdrDriver::readDiskToc(int session, const char *dataFilename)
  1261. {
  1262.   int nofTracks = 0;
  1263.   int i, j;
  1264.   CdToc *cdToc = getToc(session, &nofTracks);
  1265.   Msf indexIncrements[98];
  1266.   int indexIncrementCnt = 0;
  1267.   char isrcCode[13];
  1268.   unsigned char trackCtl; // control nibbles of track
  1269.   int ctlCheckOk;
  1270.   char *fname;
  1271.   char *extension = NULL;
  1272.   char *p;
  1273.   TrackInfo *trackInfos;
  1274.   if (cdToc == NULL) {
  1275.     return NULL;
  1276.   }
  1277.   if (nofTracks <= 1) {
  1278.     message(-1, "No tracks on disk.");
  1279.     delete[] cdToc;
  1280.     return NULL;
  1281.   }
  1282.   message(1, "");
  1283.   printCdToc(cdToc, nofTracks);
  1284.   message(1, "");
  1285.   //return NULL;
  1286.   nofTracks -= 1; // do not count lead-out
  1287.   fname = strdupCC(dataFilename);
  1288.   if ((p = strrchr(fname, '.')) != NULL) {
  1289.     extension = strdupCC(p);
  1290.     *p = 0;
  1291.   }
  1292.   trackInfos = new TrackInfo[nofTracks + 1];
  1293.   memset(trackInfos, 0, (nofTracks + 1) * sizeof(TrackInfo));
  1294.   for (i = 0; i < nofTracks; i++) {
  1295.     TrackData::Mode trackMode;
  1296.     if ((cdToc[i].adrCtl & 0x04) != 0) {
  1297.       if ((trackMode = getTrackMode(i + 1, cdToc[i].start)) ==
  1298.   TrackData::MODE0) {
  1299. message(-1, "Cannot determine mode of data track %d - asuming MODE1.",
  1300. i + 1);
  1301. trackMode = TrackData::MODE1;
  1302.       }
  1303.       if (rawDataReading_) {
  1304. if (trackMode == TrackData::MODE1) {
  1305.   trackMode = TrackData::MODE1_RAW;
  1306. }
  1307. else if (trackMode == TrackData::MODE2) {
  1308.   trackMode = TrackData::MODE2_RAW;
  1309. }
  1310. else if (trackMode == TrackData::MODE2_FORM1 ||
  1311.  trackMode == TrackData::MODE2_FORM2 ||
  1312.  trackMode == TrackData::MODE2_FORM_MIX) {
  1313.   trackMode = TrackData::MODE2_RAW;
  1314. }
  1315.       }
  1316.       else {
  1317. if (trackMode == TrackData::MODE2_FORM1 ||
  1318.     trackMode == TrackData::MODE2_FORM2) {
  1319.   trackMode = TrackData::MODE2_FORM_MIX;
  1320. }
  1321.       }
  1322.     }
  1323.     else {
  1324.       trackMode = TrackData::AUDIO;
  1325.     }
  1326.     trackInfos[i].trackNr = cdToc[i].track;
  1327.     trackInfos[i].ctl = cdToc[i].adrCtl & 0x0f;
  1328.     trackInfos[i].mode = trackMode;
  1329.     trackInfos[i].start = cdToc[i].start;
  1330.     trackInfos[i].pregap = 0;
  1331.     trackInfos[i].fill = 0;
  1332.     trackInfos[i].indexCnt = 0;
  1333.     trackInfos[i].isrcCode[0] = 0;
  1334.     trackInfos[i].filename = buildDataFileName(i, cdToc, nofTracks, fname,
  1335.        extension);
  1336.     trackInfos[i].bytesWritten = 0;
  1337.   }
  1338.   // lead-out entry
  1339.   trackInfos[nofTracks].trackNr = 0xaa;
  1340.   trackInfos[nofTracks].ctl = 0;
  1341.   trackInfos[nofTracks].mode = trackInfos[nofTracks - 1].mode;
  1342.   trackInfos[nofTracks].start = cdToc[nofTracks].start;
  1343.   trackInfos[nofTracks].pregap = 0;
  1344.   trackInfos[nofTracks].fill = 0;
  1345.   trackInfos[nofTracks].indexCnt = 0;
  1346.   trackInfos[nofTracks].isrcCode[0] = 0;
  1347.   trackInfos[nofTracks].filename = NULL;
  1348.   trackInfos[nofTracks].bytesWritten = 0;
  1349.   
  1350.   long pregap = 0;
  1351.   long slba, elba;
  1352.   if (session == 1) {
  1353.     pregap = cdToc[0].start; // pre-gap of first track
  1354.   }
  1355.   for (i = 0; i < nofTracks; i++) {
  1356.     trackInfos[i].pregap = pregap;
  1357.     slba = trackInfos[i].start;
  1358.     elba = trackInfos[i + 1].start;
  1359.     if (trackInfos[i].mode != trackInfos[i + 1].mode)
  1360.       elba -= 150;
  1361.     Msf trackLength(elba - slba);
  1362.     message(1, "Analyzing track %d (%s): start %s, ", i + 1, 
  1363.     TrackData::mode2String(trackInfos[i].mode),
  1364.     Msf(cdToc[i].start).str());
  1365.     message(1, "length %s...", trackLength.str());
  1366.     if (pregap > 0) {
  1367.       message(1, "Found pre-gap: %s", Msf(pregap).str());
  1368.     }
  1369.     isrcCode[0] = 0;
  1370.     indexIncrementCnt = 0;
  1371.     pregap = 0;
  1372.     trackCtl = 0;
  1373.     if (!fastTocReading_) {
  1374.       // Find index increments and pre-gap of next track
  1375.       if (trackInfos[i].mode == TrackData::AUDIO) {
  1376. analyzeTrack(TrackData::AUDIO, i + 1, slba, elba,
  1377.      indexIncrements, &indexIncrementCnt, 
  1378.      i < nofTracks - 1 ? &pregap : 0, isrcCode, &trackCtl);
  1379. if (trackInfos[i].mode != trackInfos[i + 1].mode)
  1380.   pregap = 150;
  1381.       }
  1382.       else {
  1383. if (trackInfos[i].mode != trackInfos[i + 1].mode)
  1384.   pregap = 150;
  1385.       }
  1386.     }
  1387.     else {
  1388.       if (trackInfos[i].mode == TrackData::AUDIO) {
  1389. if (readIsrc(i + 1, isrcCode) != 0) {
  1390.   isrcCode[0] = 0;
  1391. }
  1392. if (trackInfos[i].mode != trackInfos[i + 1].mode)
  1393.   pregap = 150;
  1394.       }
  1395.       else {
  1396. if (trackInfos[i].mode != trackInfos[i + 1].mode)
  1397.   pregap = 150;
  1398.       }
  1399.     }
  1400.     if (isrcCode[0] != 0) {
  1401.       message(1, "Found ISRC code.");
  1402.       memcpy(trackInfos[i].isrcCode, isrcCode, 13);
  1403.     }
  1404.     for (j = 0; j < indexIncrementCnt; j++)
  1405.       trackInfos[i].index[j] = indexIncrements[j].lba();
  1406.     
  1407.     trackInfos[i].indexCnt = indexIncrementCnt;
  1408.     
  1409.     if ((trackCtl & 0x80) != 0) {
  1410.       // Check track against TOC control nibbles
  1411.       ctlCheckOk = 1;
  1412.       if ((trackCtl & 0x01) !=  (cdToc[i].adrCtl & 0x01)) {
  1413. message(-1, "Pre-emphasis flag of track differs from TOC - toc file contains TOC setting.");
  1414. ctlCheckOk = 0;
  1415.       }
  1416.       if ((trackCtl & 0x08) != (cdToc[i].adrCtl & 0x08)) {
  1417. message(-1, "2-/4-channel-audio  flag of track differs from TOC - toc file contains TOC setting.");
  1418. ctlCheckOk = 0;
  1419.       }
  1420.       if (ctlCheckOk) {
  1421. message(1, "Control nibbles of track match CD-TOC settings.");
  1422.       }
  1423.     }
  1424.   }
  1425.   /*
  1426.   if (pregap != 0)
  1427.     trackInfos[nofTracks - 1].fill += pregap;
  1428.   if (fastTocReading_) {
  1429.     adjustPreGaps(trackInfos, nofTracks + 1);
  1430.   }
  1431.   */
  1432.   int padFirstPregap;
  1433.   if (onTheFly_) {
  1434.     if (session == 1 && (options_ & OPT_DRV_NO_PREGAP_READ) == 0)
  1435.       padFirstPregap = 0;
  1436.     else
  1437.       padFirstPregap = 1;
  1438.   }
  1439.   else {
  1440.     padFirstPregap = (session != 1) || padFirstPregap_;
  1441.   }
  1442.   Toc *toc = buildToc(trackInfos, nofTracks + 1, padFirstPregap);
  1443.   if (toc != NULL) {
  1444.     readCdTextData(toc);
  1445.     if (readCatalog(toc, trackInfos[0].start, trackInfos[nofTracks].start)) {
  1446.       message(1, "Found disk catalogue number.");
  1447.     }
  1448.   }
  1449.   delete[] cdToc;
  1450.   delete[] trackInfos;
  1451.   delete[] fname;
  1452.   if (extension != NULL)
  1453.     delete[] extension;
  1454.   return toc;
  1455. }
  1456. // Implementation is based on binary search over all sectors of actual
  1457. // track. ISRC codes are not extracted here.
  1458. int CdrDriver::analyzeTrackSearch(TrackData::Mode, int trackNr, long startLba,
  1459.   long endLba, Msf *index, int *indexCnt,
  1460.   long *pregap, char *isrcCode,
  1461.   unsigned char *ctl)
  1462. {
  1463.   isrcCode[0] = 0;
  1464.   *ctl = 0;
  1465.   if (pregap != NULL) {
  1466.     *pregap = findIndex(trackNr + 1, 0, startLba, endLba - 1);
  1467.     if (*pregap >= endLba) {
  1468. *pregap = 0;
  1469.     }
  1470.     else if (*pregap > 0) {
  1471.       *pregap = endLba - *pregap;
  1472.     }
  1473.   }
  1474.   // check for index increments
  1475.   int ind = 2;
  1476.   long indexLba = startLba;
  1477.   *indexCnt = 0;
  1478.   do {
  1479.     if ((indexLba = findIndex(trackNr, ind, indexLba, endLba - 1)) > 0) {
  1480.       message(1, "Found index %d at %s", ind, Msf(indexLba).str());
  1481.       if (*indexCnt < 98 && indexLba > startLba) {
  1482. index[*indexCnt] =  Msf(indexLba - startLba);
  1483. *indexCnt += 1;
  1484.       }
  1485.       ind++;
  1486.     }
  1487.   } while (indexLba > 0 && indexLba < endLba);
  1488.   // Retrieve control nibbles of track, add 75 to track start so we 
  1489.   // surely get a block of current track.
  1490.   int dummy, track;
  1491.   if (getTrackIndex(startLba + 75, &track, &dummy, ctl) == 0 &&
  1492.       track == trackNr) {
  1493.     *ctl |= 0x80;
  1494.   }
  1495.   return 0;
  1496. }
  1497. int CdrDriver::getTrackIndex(long lba, int *trackNr, int *indexNr, 
  1498.      unsigned char *ctl)
  1499. {
  1500.   return 1;
  1501. }
  1502. // Scan from lba 'trackStart' to 'trackEnd' for the position at which the
  1503. // index switchs to 'index' of track number 'track'.
  1504. // return: lba of index start postion or 0 if index was not found
  1505. long CdrDriver::findIndex(int track, int index, long trackStart,
  1506.   long trackEnd)
  1507. {
  1508.   int actTrack;
  1509.   int actIndex;
  1510.   long start = trackStart;
  1511.   long end = trackEnd;
  1512.   long mid;
  1513.   //message(0, "findIndex: %ld - %ld", trackStart, trackEnd);
  1514.   while (start < end) {
  1515.     mid = start + ((end - start) / 2);
  1516.     
  1517.     //message(0, "Checking block %ld...", mid);
  1518.     if (getTrackIndex(mid, &actTrack, &actIndex, NULL) != 0) {
  1519.       return 0;
  1520.     }
  1521.     //message(0, "Found track %d, index %d", actTrack, actIndex);
  1522.     if ((actTrack < track || actIndex < index) && mid + 1 < trackEnd) {
  1523.       //message(0, "  Checking block %ld...", mid + 1);
  1524.       if (getTrackIndex(mid + 1, &actTrack, &actIndex, NULL) != 0) {
  1525. return 0;
  1526.       }
  1527.       //message(0, "  Found track %d, index %d", actTrack, actIndex);
  1528.       if (actTrack == track && actIndex == index) {
  1529. //message(0, "Found pregap at %ld", mid + 1);
  1530. return mid;
  1531.       }
  1532.       else {
  1533. start = mid + 1;
  1534.       }
  1535.       
  1536.     }
  1537.     else {
  1538.       end = mid;
  1539.     }
  1540.   }
  1541.   return 0;
  1542. }
  1543. int CdrDriver::analyzeTrackScan(TrackData::Mode, int trackNr, long startLba,
  1544. long endLba,
  1545. Msf *index, int *indexCnt, long *pregap,
  1546. char *isrcCode, unsigned char *ctl)
  1547. {
  1548.   SubChannel **subChannels;
  1549.   int n, i;
  1550.   int actIndex = 1;
  1551.   long length;
  1552.   long crcErrCnt = 0;
  1553.   long timeCnt = 0;
  1554.   int ctlSet = 0;
  1555.   int isrcCodeFound = 0;
  1556.   long trackStartLba = startLba;
  1557.   *isrcCode = 0;
  1558.   if (pregap != NULL)
  1559.     *pregap = 0;
  1560.   *indexCnt = 0;
  1561.   *ctl = 0;
  1562.   //startLba -= 75;
  1563.   if (startLba < 0) {
  1564.     startLba = 0;
  1565.   }
  1566.   length = endLba - startLba;
  1567.   while (length > 0) {
  1568.     n = (length > maxScannedSubChannels_) ? maxScannedSubChannels_ : length;
  1569.     if (readSubChannels(startLba, n, &subChannels, NULL) != 0 ||
  1570. subChannels == NULL) {
  1571.       return 1;
  1572.     }
  1573.     for (i = 0; i < n; i++) {
  1574.       SubChannel *chan = subChannels[i];
  1575.       //chan->print();
  1576.       if (chan->checkCrc() && chan->checkConsistency()) {
  1577. if (chan->type() == SubChannel::QMODE1DATA) {
  1578.   int t = chan->trackNr();
  1579.   Msf time(chan->min(), chan->sec(), chan->frame()); // track rel time
  1580.   if (timeCnt > 74) {
  1581.     message(1, "%sr", time.str());
  1582.     timeCnt = 0;
  1583.   }
  1584.   if (t == trackNr && !ctlSet) {
  1585.     *ctl = chan->ctl();
  1586.     *ctl |= 0x80;
  1587.     ctlSet = 1;
  1588.   }
  1589.   if (t == trackNr && chan->indexNr() == actIndex + 1) {
  1590.     actIndex = chan->indexNr();
  1591.     message(1, "Found index %d at: %s", actIndex, time.str());
  1592.     if ((*indexCnt) < 98) {
  1593.       index[*indexCnt] = time;
  1594.       *indexCnt += 1;
  1595.     }
  1596.   }
  1597.   else if (t == trackNr + 1) {
  1598.     if (chan->indexNr() == 0) {
  1599.       if (pregap != NULL)
  1600. *pregap = time.lba();
  1601.       if (crcErrCnt != 0)
  1602. message(1, "Found %ld Q sub-channels with CRC errors.",
  1603. crcErrCnt);
  1604.     
  1605.       return 0;
  1606.     }
  1607.   }
  1608. }
  1609. else if (chan->type() == SubChannel::QMODE3) {
  1610.   if (!isrcCodeFound && startLba > trackStartLba) {
  1611.     strcpy(isrcCode, chan->isrc());
  1612.     isrcCodeFound = 1;
  1613.   }
  1614. }
  1615.       }
  1616.       else {
  1617. crcErrCnt++;
  1618. #if 0
  1619. if (chan->type() == SubChannel::QMODE1DATA) {
  1620.   message(1, "Q sub-channel data at %02d:%02d:%02d failed CRC check - ignored",
  1621.  chan->min(), chan->sec(), chan->frame());
  1622. }
  1623. else {
  1624.   message(1, "Q sub-channel data failed CRC check - ignored.");
  1625. }
  1626. chan->print();
  1627. #endif
  1628.       }
  1629.       timeCnt++;
  1630.     }
  1631.     length -= n;
  1632.     startLba += n;
  1633.   }
  1634.   if (crcErrCnt != 0)
  1635.     message(1, "Found %ld Q sub-channels with CRC errors.", crcErrCnt);
  1636.   return 0;
  1637. }
  1638. int CdrDriver::readSubChannels(long, long, SubChannel ***, Sample *)
  1639. {
  1640.   return 1;
  1641. }
  1642. // Checks if toc is suitable for writing. Usually all tocs are OK so
  1643. // return just 0 here.
  1644. // Return: 0: OK
  1645. //         1: toc may not be  suitable
  1646. //         2: toc is not suitable
  1647. int CdrDriver::checkToc(const Toc *toc)
  1648. {
  1649.   if (multiSession_ && toc->tocType() != Toc::CD_ROM_XA) {
  1650.     message(-1, "The toc type should be set to CD_ROM_XA if a multi session");
  1651.     message(-1, "CD is recorded.");
  1652.     return 1;
  1653.   }
  1654.   return 0;
  1655. }
  1656. // Returns block size for given mode and actual 'encodingMode_' that must
  1657. // be used to send data to the recorder.
  1658. long CdrDriver::blockSize(TrackData::Mode m) const
  1659. {
  1660.   long bsize = 0;
  1661.   if (encodingMode_ == 0) {
  1662.     // only audio blocks are written
  1663.     bsize = AUDIO_BLOCK_LEN;
  1664.   }
  1665.   else if (encodingMode_ == 1) {
  1666.     // encoding for SCSI-3/mmc drives in session-at-once mode
  1667.     switch (m) {
  1668.     case TrackData::AUDIO:
  1669.       bsize = AUDIO_BLOCK_LEN;
  1670.       break;
  1671.     case TrackData::MODE1:
  1672.     case TrackData::MODE1_RAW:
  1673.       bsize = MODE1_BLOCK_LEN;
  1674.       break;
  1675.     case TrackData::MODE2:
  1676.     case TrackData::MODE2_RAW:
  1677.     case TrackData::MODE2_FORM1:
  1678.     case TrackData::MODE2_FORM2:
  1679.     case TrackData::MODE2_FORM_MIX:
  1680.       bsize = MODE2_BLOCK_LEN;
  1681.       break;
  1682.     case TrackData::MODE0:
  1683.       message(-3, "Illegal mode in 'CdrDriver::blockSize()'.");
  1684.       break;
  1685.     }
  1686.   }
  1687.   else {
  1688.     message(-3, "Illegal encoding mode in 'CdrDriver::blockSize()'.");
  1689.   }
  1690.   return bsize;
  1691. }
  1692. void CdrDriver::printCdToc(CdToc *toc, int tocLen)
  1693. {
  1694.   int t;
  1695.   long len;
  1696.   message(1, "Track   Mode    Flags  Start                Length");
  1697.   message(1, "------------------------------------------------------------");
  1698.   for (t = 0; t < tocLen; t++) {
  1699.     if (t == tocLen - 1) {
  1700.       message(1, "Leadout %s   %x      %s(%6ld)",
  1701.       (toc[t].adrCtl & 0x04) != 0 ? "DATA " : "AUDIO",
  1702.       toc[t].adrCtl & 0x0f,
  1703.       Msf(toc[t].start).str(), toc[t].start);
  1704.     }
  1705.     else {
  1706.       len = toc[t + 1].start - toc[t].start;
  1707.       message(1, "%2d      %s   %x      %s(%6ld) ", toc[t].track,
  1708.       (toc[t].adrCtl & 0x04) != 0 ? "DATA " : "AUDIO",
  1709.       toc[t].adrCtl & 0x0f,
  1710.       Msf(toc[t].start).str(), toc[t].start);
  1711.       message(1, "    %s(%6ld)", Msf(len).str(), len);
  1712.     }
  1713.   }
  1714. }
  1715. TrackData::Mode CdrDriver::getTrackMode(int, long trackStartLba)
  1716. {
  1717.   unsigned char cmd[10];
  1718.   unsigned char data[2340];
  1719.   int blockLength = 2340;
  1720.   TrackData::Mode mode;
  1721.   if (setBlockSize(blockLength) != 0) {
  1722.     return TrackData::MODE0;
  1723.   }
  1724.   memset(cmd, 0, 10);
  1725.   cmd[0] = 0x28; // READ10
  1726.   cmd[2] = trackStartLba >> 24;
  1727.   cmd[3] = trackStartLba >> 16;
  1728.   cmd[4] = trackStartLba >> 8;
  1729.   cmd[5] = trackStartLba;
  1730.   cmd[8] = 1;
  1731.   if (sendCmd(cmd, 10, NULL, 0, data, blockLength) != 0) {
  1732.     setBlockSize(MODE1_BLOCK_LEN);
  1733.     return TrackData::MODE0;
  1734.   }
  1735.   
  1736.   setBlockSize(MODE1_BLOCK_LEN);
  1737.   mode = determineSectorMode(data);
  1738.   if (mode == TrackData::MODE0) {
  1739.     message(-2, "Found illegal mode in sector %ld.", trackStartLba);
  1740.   }
  1741.   return mode;
  1742. }
  1743. TrackData::Mode CdrDriver::determineSectorMode(unsigned char *buf)
  1744. {
  1745.   switch (buf[3]) {
  1746.   case 1:
  1747.     return TrackData::MODE1;
  1748.     break;
  1749.   case 2:
  1750.     return analyzeSubHeader(buf + 4);
  1751.     break;
  1752.   }
  1753.   // illegal mode found
  1754.   return TrackData::MODE0;
  1755. }
  1756. // Analyzes given 8 byte sub head and tries to determine if it belongs
  1757. // to a form 1, form 2 or a plain mode 2 sector.
  1758. TrackData::Mode CdrDriver::analyzeSubHeader(unsigned char *sh)
  1759. {
  1760.   if (sh[0] == sh[4] && sh[1] == sh[5] && sh[2] == sh[6] && sh[3] == sh[7]) {
  1761.     // check first copy
  1762.     //if (sh[0] < 8 && sh[1] < 8 && sh[2] != 0) {
  1763.     if (sh[2] & 0x20 != 0)
  1764.       return TrackData::MODE2_FORM2;
  1765.     else
  1766.       return TrackData::MODE2_FORM1;
  1767.     //}
  1768. #if 0
  1769.     // check second copy
  1770.     if (sh[4] < 8 && sh[5] < 8 && sh[6] != 0) {
  1771.       if (sh[6] & 0x20 != 0)
  1772. return TrackData::MODE2_FORM2;
  1773.       else
  1774. return TrackData::MODE2_FORM1;
  1775.     }
  1776. #endif
  1777.   }
  1778.   else {
  1779.     // no valid sub-header data, sector is a plain MODE2 sector
  1780.     return TrackData::MODE2;
  1781.   }
  1782. }
  1783. // Sets block size for read/write operation to given value.
  1784. // Return: 0: OK
  1785. //         1: SCSI command failed
  1786. int CdrDriver::setBlockSize(long blocksize)
  1787. {
  1788.   unsigned char cmd[10];
  1789.   unsigned char ms[16];
  1790.   if (blockLength_ == blocksize)
  1791.     return 0;
  1792.   memset(ms, 0, 16);
  1793.   ms[3] = 8;
  1794.   ms[10] = blocksize >> 8;
  1795.   ms[11] = blocksize;
  1796.   memset(cmd, 0, 10);
  1797.   cmd[0] = 0x15; // MODE SELECT6
  1798.   cmd[4] = 12;
  1799.   if (sendCmd(cmd, 6, ms, 12, NULL, 0) != 0) {
  1800.     message(-2, "Cannot set block size.");
  1801.     return 1;
  1802.   }
  1803.   blockLength_ = blocksize;
  1804.   return 0;
  1805. }
  1806. // Returns control flags for given track.   
  1807. unsigned char CdrDriver::trackCtl(const Track *track)
  1808. {
  1809.   unsigned char ctl = 0;
  1810.   if (track->copyPermitted()) {
  1811.     ctl |= 0x20;
  1812.   }
  1813.   if (track->type() == TrackData::AUDIO) {
  1814.     // audio track
  1815.     if (track->preEmphasis()) {
  1816.       ctl |= 0x10;
  1817.     }
  1818.     if (track->audioType() == 1) {
  1819.       ctl |= 0x80;
  1820.     }
  1821.   }
  1822.   else {
  1823.     // data track
  1824.     ctl |= 0x40;
  1825.   }
  1826.   
  1827.   return ctl;
  1828. }
  1829. // Returns session format for point A0 toc entry depending on Toc type.
  1830. unsigned char CdrDriver::sessionFormat()
  1831. {
  1832.   unsigned char ret = 0;
  1833.   switch (toc_->tocType()) {
  1834.   case Toc::CD_DA:
  1835.   case Toc::CD_ROM:
  1836.     ret = 0x00;
  1837.     break;
  1838.   case Toc::CD_I:
  1839.     ret = 0x10;
  1840.     break;
  1841.   case Toc::CD_ROM_XA:
  1842.     ret = 0x20;
  1843.     break;
  1844.   }
  1845.   message(2, "Session format: %x", ret);
  1846.   return ret;
  1847. }
  1848. // Generic method to read CD-TEXT packs according to the MMC-2 specification.
  1849. // nofPacks: filled with number of found CD-TEXT packs
  1850. // return: array of CD-TEXT packs or 'NULL' if no packs where retrieved
  1851. CdTextPack *CdrDriver::readCdTextPacks(long *nofPacks)
  1852. {
  1853.   unsigned char cmd[10];
  1854.   unsigned char *data;
  1855.   unsigned char reqData[4];
  1856.   memset(cmd, 0, 10);
  1857.   cmd[0] = 0x43; // READ TOC/PMA/ATIP
  1858.   cmd[2] = 5;    // CD-TEXT
  1859.   cmd[8] = 4;
  1860.   if (sendCmd(cmd, 10, NULL, 0, reqData, 4, 0) != 0) {
  1861.     message(1, "Cannot read CD-TEXT data - maybe not supported by drive.");
  1862.     return NULL;
  1863.   }
  1864.   long len = ((reqData[0] << 8 ) | reqData[1]) + 2;
  1865.   message(3, "CD-TEXT data len: %ld", len);
  1866.   if (len <= 4)
  1867.     return NULL;
  1868.   if (len > scsiIf_->maxDataLen()) {
  1869.     message(-2, "CD-TEXT data too big for maximum SCSI transfer length.");
  1870.     return NULL;
  1871.   }
  1872.   data = new (unsigned char)[len];
  1873.   cmd[7] = len >> 8;
  1874.   cmd[8] = len;
  1875.   if (sendCmd(cmd, 10, NULL, 0, data, len, 1) != 0) {
  1876.     message(-2, "Reading of CD-TEXT data failed.");
  1877.     delete[] data;
  1878.     return NULL;
  1879.   }
  1880.   
  1881.   *nofPacks = (len - 4) / sizeof(CdTextPack);
  1882.   CdTextPack *packs = new CdTextPack[*nofPacks];
  1883.   memcpy(packs, data + 4, *nofPacks * sizeof(CdTextPack));
  1884.   delete[] data;
  1885.   return packs;
  1886. }
  1887. // Analyzes CD-TEXT packs and stores read data in given 'Toc' object.
  1888. // Return: 0: OK
  1889. //         1: error occured
  1890. int CdrDriver::readCdTextData(Toc *toc)
  1891. {
  1892.   long i, j;
  1893.   long nofPacks;
  1894.   CdTextPack *packs = readCdTextPacks(&nofPacks);
  1895.   unsigned char buf[256 * 12];
  1896.   unsigned char lastType;
  1897.   int lastBlockNumber;
  1898.   int blockNumber;
  1899.   int pos;
  1900.   int actTrack;
  1901.   CdTextItem::PackType packType;
  1902.   CdTextItem *sizeInfoItem = NULL;
  1903.   CdTextItem *item;
  1904.   if (packs == NULL)
  1905.     return 1;
  1906.   message(1, "Found CD-TEXT data.");
  1907.   pos = 0;
  1908.   lastType = packs[0].packType;
  1909.   lastBlockNumber = (packs[0].blockCharacter >> 4) & 0x07;
  1910.   actTrack = 0;
  1911.   for (i = 0; i < nofPacks; i++) {
  1912.     CdTextPack &p = packs[i];
  1913. #if 1
  1914.     message(3, "%02x %02x %02x %02x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x  CRC: %02x %02x", p.packType, p.trackNumber,
  1915.     p.sequenceNumber, p.blockCharacter, p.data[0], p.data[1], 
  1916.     p.data[2], p.data[3], p.data[4], p.data[5], p.data[6], p.data[7], 
  1917.     p.data[8], p.data[9], p.data[10], p.data[11],
  1918.     p.crc0, p.crc1);
  1919. #endif
  1920.     blockNumber = (p.blockCharacter >> 4) & 0x07;
  1921.     if (lastType != p.packType || lastBlockNumber != blockNumber) {
  1922.       if (lastType >= 0x80 && lastType <= 0x8f) {
  1923. packType = CdTextItem::int2PackType(lastType);
  1924. if (CdTextItem::isBinaryPack(packType)) {
  1925.   // finish binary data
  1926.   if (packType == CdTextItem::CDTEXT_GENRE) {
  1927.     // The two genre codes may be followed by a string. Adjust 'pos'
  1928.     // so that all extra 0 bytes at the end of the data are stripped
  1929.     // off.
  1930.     for (j = 2; j < pos && buf[j] != 0; j++) ;
  1931.     if (j < pos)
  1932.       pos = j + 1;
  1933.   }
  1934.   item = new CdTextItem(packType, lastBlockNumber, buf, pos);
  1935.   if (packType == CdTextItem::CDTEXT_SIZE_INFO)
  1936.     sizeInfoItem = item;
  1937.   toc->addCdTextItem(0, item);
  1938. }
  1939.       }
  1940.       else {
  1941. message(-2, "CD-TEXT: Found invalid pack type: %02x", lastType);
  1942. delete[] packs;
  1943. return 1;
  1944.       }
  1945.       lastType = p.packType;
  1946.       lastBlockNumber = blockNumber;
  1947.       pos = 0;
  1948.       actTrack = 0;
  1949.     }
  1950.     if (p.packType >= 0x80 && p.packType <= 0x8f) {
  1951.       packType = CdTextItem::int2PackType(p.packType);
  1952.       if (CdTextItem::isBinaryPack(packType)) {
  1953. memcpy(buf + pos, p.data, 12);
  1954. pos += 12;
  1955.       }
  1956.       else {
  1957. // pack contains text -> read all string from it
  1958. j = 0;
  1959. while (j < 12) {
  1960.   for (; j < 12 && p.data[j] != 0; j++)
  1961.     buf[pos++] = p.data[j];
  1962.   if (j < 12) {
  1963.     // string is finished
  1964.     buf[pos] = 0;
  1965. #if 0
  1966.     message(0, "%02x %02x: %s", p.packType, p.trackNumber, buf);
  1967. #endif
  1968.     toc->addCdTextItem(actTrack,
  1969.        new CdTextItem(packType, blockNumber,
  1970.       (char*)buf));
  1971.     actTrack++;
  1972.     pos = 0;
  1973.     // skip zero data
  1974.     while (j < 12 && p.data[j] == 0)
  1975.       j++;
  1976.   }
  1977. }
  1978.       }
  1979.     }
  1980.     else {
  1981.       message(-2, "CD-TEXT: Found invalid pack type: %02x", p.packType);
  1982.       delete[] packs;
  1983.       return 1;
  1984.     }
  1985.   }
  1986.   if (pos != 0 && lastType >= 0x80 && lastType <= 0x8f) {
  1987.     packType = CdTextItem::int2PackType(lastType);
  1988.     if (CdTextItem::isBinaryPack(packType)) {
  1989.       // finish binary data
  1990.       if (packType == CdTextItem::CDTEXT_GENRE) {
  1991. // The two genre codes may be followed by a string. Adjust 'pos'
  1992. // so that all extra 0 bytes at the end of the data are stripped
  1993. // off.
  1994. for (j = 2; j < pos && buf[j] != 0; j++) ;
  1995. if (j < pos)
  1996.   pos = j + 1;
  1997.       }
  1998.       item = new CdTextItem(packType, lastBlockNumber, buf, pos);
  1999.       toc->addCdTextItem(0, item);
  2000.       if (packType == CdTextItem::CDTEXT_SIZE_INFO)
  2001. sizeInfoItem = item;
  2002.     }
  2003.   }
  2004.   delete[] packs;
  2005.   // update language mapping from SIZE INFO pack data
  2006.   if (sizeInfoItem != NULL && sizeInfoItem->dataLen() >= 36) {
  2007.     const unsigned char *data = sizeInfoItem->data();
  2008.     for (i = 0; i < 8; i++) {
  2009.       if (data[28 + i] > 0)
  2010. toc->cdTextLanguage(i, data[28 + i]);
  2011.       else
  2012. toc->cdTextLanguage(i, -1);
  2013.     }
  2014.   }
  2015.   else {
  2016.     message(-1, "Cannot determine language mapping from CD-TEXT data.");
  2017.     message(-1, "Using default mapping.");
  2018.   }
  2019.   return 0;
  2020. }
  2021. long CdrDriver::readTrackData(TrackData::Mode mode, long lba, long len,
  2022.       unsigned char *buf)
  2023. {
  2024.   return -1;
  2025. }
  2026. int CdrDriver::analyzeDataTrack(TrackData::Mode mode, int trackNr,
  2027. long startLba, long endLba, long *pregap)
  2028. {
  2029.   long maxLen = scsiIf_->maxDataLen() / AUDIO_BLOCK_LEN;
  2030.   long lba = startLba;
  2031.   long len = endLba - startLba;
  2032.   long actLen, n;
  2033.   *pregap = 0;
  2034.   while (len > 0) {
  2035.     n = len > maxLen ? maxLen : len;
  2036.     if ((actLen = readTrackData(mode, lba, n, transferBuffer_)) < 0) {
  2037.       message(-2, "Analyzing of track %d failed.", trackNr);
  2038.       return 1;
  2039.     }
  2040.     message(1, "%sr", Msf(lba).str());
  2041.     if (actLen != n) {
  2042.       //message(0, "Data track pre-gap: %ld", len - actLen);
  2043.       *pregap = len - actLen;
  2044.       if (*pregap > 300) {
  2045. message(-1,
  2046. "The pre-gap of the following track appears to have length %s.",
  2047. Msf(*pregap).str());
  2048. message(-1, "This value is probably bogus and may be caused by unexpected");
  2049. message(-1, "behavior of the drive. Try to verify with other tools how");
  2050. message(-1, "much data can be read from the current track and compare it");
  2051. message(-1, "to the value stored in the toc-file. Usually, the pre-gap");
  2052. message(-1, "should have length 00:02:00.");
  2053.       }
  2054.       return 0;
  2055.     }
  2056.     len -= n;
  2057.     lba += n;
  2058.   }
  2059.   return 0;
  2060. }
  2061. // Reads toc and audio data from CD. Must be overloaded by derived class.
  2062. Toc *CdrDriver::readDisk(int session, const char *dataFilename)
  2063. {
  2064.   int padFirstPregap = 1;
  2065.   int nofTracks = 0;
  2066.   int i;
  2067.   CdToc *cdToc = getToc(session, &nofTracks);
  2068.   //unsigned char trackCtl; // control nibbles of track
  2069.   //int ctlCheckOk;
  2070.   TrackInfo *trackInfos;
  2071.   TrackData::Mode trackMode;
  2072.   int fp;
  2073.   char *fname = strdupCC(dataFilename);
  2074.   Toc *toc = NULL;
  2075.   if (cdToc == NULL) {
  2076.     return NULL;
  2077.   }
  2078.   if (nofTracks <= 1) {
  2079.     message(-1, "No tracks on disk.");
  2080.     delete[] cdToc;
  2081.     return NULL;
  2082.   }
  2083.   message(1, "");
  2084.   printCdToc(cdToc, nofTracks);
  2085.   message(1, "");
  2086.   //return NULL;
  2087.   if (onTheFly_) {
  2088.     fp = onTheFlyFd_;
  2089.   }
  2090.   else {
  2091. #ifdef _WIN32
  2092.     if ((fp = open(dataFilename, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,
  2093.    0666)) < 0)
  2094. #else
  2095.     if ((fp = open(dataFilename, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
  2096. #endif
  2097.     {
  2098.       message(-2, "Cannot open "%s" for writing: %s", dataFilename,
  2099.       strerror(errno));
  2100.       delete[] cdToc;
  2101.       return NULL;
  2102.     }
  2103.   }
  2104.   nofTracks -= 1; // do not count lead-out
  2105.   trackInfos = new TrackInfo[nofTracks + 1];
  2106.   
  2107.   for (i = 0; i < nofTracks; i++) {
  2108.     if ((cdToc[i].adrCtl & 0x04) != 0) {
  2109.       if ((trackMode = getTrackMode(i + 1, cdToc[i].start)) ==
  2110.   TrackData::MODE0) {
  2111. message(-1, "Cannot determine mode of data track %d - asuming MODE1.",
  2112. i + 1);
  2113. trackMode = TrackData::MODE1;
  2114.       }
  2115.       if (rawDataReading_) {
  2116. if (trackMode == TrackData::MODE1) {
  2117.   trackMode = TrackData::MODE1_RAW;
  2118. }
  2119. else if (trackMode == TrackData::MODE2_FORM1 ||
  2120.  trackMode == TrackData::MODE2_FORM2 ||
  2121.  trackMode == TrackData::MODE2_FORM_MIX) {
  2122.   trackMode = TrackData::MODE2_RAW;
  2123. }
  2124.       }
  2125.       else {
  2126. if (trackMode == TrackData::MODE2_FORM1 ||
  2127.     trackMode == TrackData::MODE2_FORM2 ||
  2128.     trackMode == TrackData::MODE2_FORM_MIX) {
  2129.   trackMode = TrackData::MODE2_FORM_MIX;
  2130. }
  2131.       }
  2132.     }
  2133.     else {
  2134.       trackMode = TrackData::AUDIO;
  2135.     }
  2136.     trackInfos[i].trackNr = cdToc[i].track;
  2137.     trackInfos[i].ctl = cdToc[i].adrCtl & 0x0f;
  2138.     trackInfos[i].mode = trackMode;
  2139.     trackInfos[i].start = cdToc[i].start;
  2140.     trackInfos[i].pregap = 0;
  2141.     trackInfos[i].fill = 0;
  2142.     trackInfos[i].indexCnt = 0;
  2143.     trackInfos[i].isrcCode[0] = 0;
  2144.     trackInfos[i].filename = fname;
  2145.     trackInfos[i].bytesWritten = 0;
  2146.   }
  2147.   // lead-out entry
  2148.   trackInfos[nofTracks].trackNr = 0xaa;
  2149.   trackInfos[nofTracks].ctl = 0;
  2150.   trackInfos[nofTracks].mode = trackInfos[nofTracks - 1].mode;
  2151.   trackInfos[nofTracks].start = cdToc[nofTracks].start;
  2152.   trackInfos[nofTracks].pregap = 0;
  2153.   trackInfos[nofTracks].indexCnt = 0;
  2154.   trackInfos[nofTracks].isrcCode[0] = 0;
  2155.   trackInfos[nofTracks].filename = NULL;
  2156.   trackInfos[nofTracks].bytesWritten = 0;
  2157.   int trs = 0;
  2158.   int tre = 0;
  2159.   long slba, elba;
  2160.   while (trs < nofTracks) {
  2161.     if (trackInfos[trs].mode != TrackData::AUDIO) {
  2162.       if (trs == 0) {
  2163. if (session == 1)
  2164.   trackInfos[trs].pregap = trackInfos[trs].start;
  2165.       }
  2166.       else {
  2167. if (trackInfos[trs].mode != trackInfos[trs - 1].mode)
  2168.   trackInfos[trs].pregap = 150;
  2169.       }
  2170.       slba = trackInfos[trs].start;
  2171.       elba = trackInfos[trs + 1].start;
  2172.       if (trackInfos[trs].mode != trackInfos[trs + 1].mode) {
  2173. elba -= 150;
  2174.       }
  2175.       message(1, "Copying data track %d (%s): start %s, ", trs + 1, 
  2176.       TrackData::mode2String(trackInfos[trs].mode),
  2177.       Msf(cdToc[trs].start).str());
  2178.       message(1, "length %s to "%s"...", Msf(elba - slba).str(),
  2179.       trackInfos[trs].filename);
  2180.       
  2181.       if (readDataTrack(fp, slba, elba, &trackInfos[trs]) != 0)
  2182. goto fail;
  2183.       trs++;
  2184.     }
  2185.     else {
  2186.       // find continuous range of audio tracks
  2187.       tre = trs;
  2188.       while (tre < nofTracks && trackInfos[tre].mode == TrackData::AUDIO)
  2189. tre++;
  2190.       if (trs == 0) {
  2191. if (session == 1)
  2192.   trackInfos[trs].pregap = trackInfos[trs].start;
  2193.       }
  2194.       else {
  2195. if (trackInfos[trs].mode != trackInfos[trs - 1].mode)
  2196.   trackInfos[trs].pregap = 150;
  2197.       }
  2198.       slba = cdToc[trs].start;
  2199.       elba = cdToc[tre].start;
  2200.       // If we have the first track of the first session we can start ripping
  2201.       // from lba 0 to extract the pre-gap data.
  2202.       // But only if the drive supports it as indicated by 'options_'.
  2203.       if (session == 1 && trs == 0 &&
  2204.   (options_ & OPT_DRV_NO_PREGAP_READ) == 0) {
  2205. slba = 0;
  2206.       }
  2207.       // Assume that the pre-gap length conforms to the standard if the track
  2208.       // mode changes. 
  2209.       if (trackInfos[tre - 1].mode != trackInfos[tre].mode) {
  2210. elba -= 150;
  2211.       }
  2212.       message(1, "Copying audio tracks %d-%d: start %s, ", trs + 1, tre,
  2213.       Msf(slba).str());
  2214.       message(1, "length %s to "%s"...", Msf(elba - slba).str(),
  2215.       trackInfos[trs].filename);
  2216.       if (readAudioRange(fp, slba, elba, trs, tre - 1, trackInfos) != 0)
  2217. goto fail;
  2218.       trs = tre;
  2219.     }
  2220.   }
  2221.   // if the drive allows to read audio data from the first track's
  2222.   // pre-gap the data will be written to the output file and 
  2223.   // 'buildToc()' must not create zero data for the pre-gap
  2224.   padFirstPregap = 1;
  2225.   if (session == 1 && (options_ & OPT_DRV_NO_PREGAP_READ) == 0)
  2226.     padFirstPregap = 0;
  2227.   toc = buildToc(trackInfos, nofTracks + 1, padFirstPregap);
  2228.   if (!onTheFly_ && toc != NULL) {
  2229.     readCdTextData(toc);
  2230.     if (readCatalog(toc, trackInfos[0].start, trackInfos[nofTracks].start)) {
  2231.       message(1, "Found disk catalogue number.");
  2232.     }
  2233.   }
  2234. fail:
  2235.   delete[] cdToc;
  2236.   delete[] trackInfos;
  2237.   delete[] fname;
  2238.   if (!onTheFly_) {
  2239.     if (close(fp) != 0) {
  2240.       message(-2, "Writing to "%s" failed: %s", dataFilename,
  2241.       strerror(errno));
  2242.       delete toc;
  2243.       return NULL;
  2244.     }
  2245.   }
  2246.   return toc;
  2247. }
  2248. Toc *CdrDriver::buildToc(TrackInfo *trackInfos, long nofTrackInfos,
  2249.  int padFirstPregap)
  2250. {
  2251.   long i, j;
  2252.   long nofTracks = nofTrackInfos - 1;
  2253.   int foundDataTrack = 0;
  2254.   int foundAudioTrack = 0;
  2255.   int foundXATrack = 0;
  2256.   long modeStartLba = 0; // start LBA for current mode
  2257.   unsigned long dataLen;
  2258.   TrackData::Mode trackMode;
  2259.   TrackData::Mode lastMode = TrackData::MODE0; // illegal in this context
  2260.   int newMode;
  2261.   long byteOffset = 0;
  2262.   if (nofTrackInfos < 2)
  2263.     return NULL;
  2264.   Toc *toc = new Toc;
  2265.   // build the Toc
  2266.   for (i = 0; i < nofTracks; i++) {
  2267.     TrackInfo &ati = trackInfos[i]; // actual track info
  2268.     TrackInfo &nti = trackInfos[i + 1]; // next track info
  2269.     newMode = 0;
  2270.     trackMode = ati.mode;
  2271.     switch (trackMode) {
  2272.     case TrackData::AUDIO:
  2273.       foundAudioTrack = 1;
  2274.       break;
  2275.     case TrackData::MODE1:
  2276.     case TrackData::MODE1_RAW:
  2277.     case TrackData::MODE2:
  2278.       foundDataTrack = 1;
  2279.       break;
  2280.     case TrackData::MODE2_RAW:
  2281.     case TrackData::MODE2_FORM1:
  2282.     case TrackData::MODE2_FORM2:
  2283.     case TrackData::MODE2_FORM_MIX:
  2284.       foundXATrack = 1;
  2285.       break;
  2286.     case TrackData::MODE0:
  2287.       // should not happen
  2288.       break;
  2289.     }
  2290.     if (trackMode != lastMode) {
  2291.       newMode = 1;
  2292.       if (i == 0 && !padFirstPregap)
  2293. modeStartLba = 0;
  2294.       else
  2295. modeStartLba = ati.start;
  2296.       lastMode = trackMode;
  2297.     }
  2298.     
  2299.     Track t(trackMode);
  2300.     t.preEmphasis(ati.ctl & 0x01);
  2301.     t.copyPermitted(ati.ctl & 0x02);
  2302.     t.audioType(ati.ctl & 0x08);
  2303.     if (ati.isrcCode[0] != 0)
  2304.       t.isrc(ati.isrcCode);
  2305.     if (trackMode == TrackData::AUDIO) {
  2306.       if (newMode && (i > 0 || padFirstPregap)) {
  2307. Msf trackLength(nti.start - ati.start - nti.pregap);
  2308. if (ati.pregap > 0) {
  2309.   t.append(SubTrack(SubTrack::DATA,
  2310.     TrackData(trackMode, Msf(ati.pregap).samples())));
  2311. }
  2312. t.append(SubTrack(SubTrack::DATA,
  2313.   TrackData(ati.filename, byteOffset,
  2314.     0, trackLength.samples())));
  2315.       }
  2316.       else {
  2317. Msf trackLength(nti.start - ati.start - nti.pregap + ati.pregap);
  2318. t.append(SubTrack(SubTrack::DATA,
  2319.   TrackData(ati.filename, byteOffset,
  2320.     Msf(ati.start - modeStartLba
  2321. - ati.pregap).samples(), 
  2322.     trackLength.samples())));
  2323.       }
  2324.       t.start(Msf(ati.pregap));
  2325.     }
  2326.     else {
  2327.       long trackLength = nti.start - ati.start - nti.pregap - ati.fill;
  2328.       if (ati.pregap != 0) {
  2329. // add zero data for pre-gap
  2330. dataLen = ati.pregap * TrackData::dataBlockSize(trackMode);
  2331. t.append(SubTrack(SubTrack::DATA, TrackData(trackMode, dataLen)));
  2332.       }
  2333.       
  2334.       dataLen = trackLength * TrackData::dataBlockSize(trackMode);
  2335.       t.append(SubTrack(SubTrack::DATA,
  2336. TrackData(trackMode, ati.filename, byteOffset,
  2337.   dataLen)));
  2338.       if (ati.fill > 0) {
  2339. dataLen =  ati.fill * TrackData::dataBlockSize(trackMode);
  2340. t.append(SubTrack(SubTrack::DATA, TrackData(trackMode, dataLen)));
  2341.       }
  2342.       t.start(Msf(ati.pregap));
  2343.     }
  2344.     for (j = 0; j < ati.indexCnt; j++)
  2345.       t.appendIndex(Msf(ati.index[j]));
  2346.     toc->append(&t);
  2347.     byteOffset += ati.bytesWritten;
  2348.   }
  2349.   if (foundXATrack)
  2350.     toc->tocType(Toc::CD_ROM_XA);
  2351.   else if (foundDataTrack)
  2352.     toc->tocType(Toc::CD_ROM);
  2353.   else
  2354.     toc->tocType(Toc::CD_DA);
  2355.   return toc;
  2356. }
  2357. // Reads a complete data track.
  2358. // start: start of data track from TOC
  2359. // end: start of next track from TOC
  2360. // trackInfo: info about current track, updated by this function
  2361. // Return: 0: OK
  2362. //         1: error occured
  2363. int CdrDriver::readDataTrack(int fd, long start, long end,
  2364.      TrackInfo *trackInfo)
  2365. {
  2366.   long len = end - start;
  2367.   long lba;
  2368.   long lastLba;
  2369.   long blockLen;
  2370.   long blocking;
  2371.   long burst;
  2372.   long iterationsWithoutError = 0;
  2373.   long n, ret;
  2374.   long act;
  2375.   int foundLECError;
  2376.   unsigned char *buf;
  2377.   TrackData::Mode mode;
  2378.   switch (trackInfo->mode) {
  2379.   case TrackData::MODE1:
  2380.     mode = TrackData::MODE1;
  2381.     blockLen = MODE1_BLOCK_LEN;
  2382.     break;
  2383.   case TrackData::MODE1_RAW:
  2384.     mode = TrackData::MODE1_RAW;
  2385.     blockLen = AUDIO_BLOCK_LEN;
  2386.     break;
  2387.   case TrackData::MODE2:
  2388.     mode = TrackData::MODE2;
  2389.     blockLen = MODE2_BLOCK_LEN;
  2390.     break;
  2391.   case TrackData::MODE2_RAW:
  2392.     mode = TrackData::MODE2_RAW;
  2393.     blockLen = AUDIO_BLOCK_LEN;
  2394.     break;
  2395.   case TrackData::MODE2_FORM1:
  2396.   case TrackData::MODE2_FORM2:
  2397.   case TrackData::MODE2_FORM_MIX:
  2398.     mode = TrackData::MODE2_FORM_MIX;
  2399.     blockLen = MODE2_BLOCK_LEN;
  2400.     break;
  2401.   case TrackData::MODE0:
  2402.   case TrackData::AUDIO:
  2403.     message(-3, "CdrDriver::readDataTrack: Illegal mode.");
  2404.     return 1;
  2405.     break;
  2406.   }
  2407.   // adjust mode in 'trackInfo'
  2408.   trackInfo->mode = mode;
  2409.   trackInfo->bytesWritten = 0;
  2410.   blocking = scsiIf_->maxDataLen() / AUDIO_BLOCK_LEN;;
  2411.   assert(blocking > 0);
  2412.   buf = new (unsigned char)[blocking * blockLen];
  2413.   lba = lastLba = start;
  2414.   burst = blocking;
  2415.   while (len > 0) {
  2416.     if (burst != blocking && iterationsWithoutError > 2 * blocking)
  2417.       burst = blocking;
  2418.     n = (len > burst) ? burst : len;
  2419.     foundLECError = 0;
  2420.     if ((act = readTrackData(mode, lba, n, buf)) == -1) {
  2421.       message(-2, "Read error while copying data from track.");
  2422.       delete[] buf;
  2423.       return 1;
  2424.     }
  2425.     if (act == -2) {
  2426.       // L-EC error encountered
  2427.       if (trackInfo->mode == TrackData::MODE1_RAW ||
  2428.   trackInfo->mode == TrackData::MODE2_RAW) {
  2429. if (n > 1) {
  2430.   // switch to single step mode
  2431.   iterationsWithoutError = 0;
  2432.   burst = 1;
  2433.   continue;
  2434. }
  2435. else {
  2436.   foundLECError = 1;
  2437.   act = n = 0;
  2438. }
  2439.       }
  2440.       else {
  2441. message(-2, "L-EC error around sector %ld while copying data from track.", lba);
  2442. message(-2, "Use option '--read-raw' to ignore L-EC errors.");
  2443. delete[] buf;
  2444. return 1;
  2445.       }
  2446.     }
  2447.     if (foundLECError) {
  2448.       iterationsWithoutError = 0;
  2449.       message(-1, "Found L-EC error at sector %ld - ignored.", lba);
  2450.       // create a dummy sector for the sector with L-EC errors
  2451.       Msf m(lba + 150);
  2452.       memcpy(buf, syncPattern, 12);
  2453.       buf[12] = SubChannel::bcd(m.min());
  2454.       buf[13] = SubChannel::bcd(m.sec());
  2455.       buf[14] = SubChannel::bcd(m.frac());
  2456.       if (trackInfo->mode == TrackData::MODE1_RAW)
  2457. buf[15] = 1;
  2458.       else
  2459. buf[15] = 2;
  2460.       memset(buf + 16, 0, AUDIO_BLOCK_LEN - 16);
  2461.       if ((ret = fullWrite(fd, buf, AUDIO_BLOCK_LEN)) != AUDIO_BLOCK_LEN) {
  2462. if (ret < 0)
  2463.   message(-2, "Writing of data failed: %s", strerror(errno));
  2464. else
  2465.   message(-2, "Writing of data failed: Disk full");
  2466.   
  2467. delete[] buf;
  2468. return 1;
  2469.       }
  2470.       trackInfo->bytesWritten += AUDIO_BLOCK_LEN;
  2471.       lba += 1;
  2472.       len -= 1;
  2473.     }
  2474.     else {
  2475.       iterationsWithoutError++;
  2476.       if (act > 0) {
  2477. if ((ret = fullWrite(fd, buf, blockLen * act)) != blockLen * act) {
  2478.   if (ret < 0)
  2479.     message(-2, "Writing of data failed: %s", strerror(errno));
  2480.   else
  2481.     message(-2, "Writing of data failed: Disk full");
  2482.   
  2483.   delete[] buf;
  2484.   return 1;
  2485. }
  2486.       }
  2487.       trackInfo->bytesWritten += blockLen * act;
  2488.       if (lba > lastLba + 75) {
  2489. Msf lbatime(lba);
  2490. message(1, "%02d:%02d:00r", lbatime.min(), lbatime.sec());
  2491. lastLba = lba;
  2492.       }
  2493.       lba += act;
  2494.       len -= act;
  2495.       if (act != n)
  2496. break;
  2497.     }
  2498.   }
  2499.   // pad remaining blocks with zero data, e.g. for disks written in TAO mode
  2500.   if (len > 0) {
  2501.     message(-1, "Padding with %ld zero sectors.", len);
  2502.     if (mode == TrackData::MODE1_RAW || mode == TrackData::MODE2_RAW) {
  2503.       memcpy(buf, syncPattern, 12);
  2504.       if (mode == TrackData::MODE1_RAW)
  2505. buf[15] = 1;
  2506.       else
  2507. buf[15] = 2;
  2508.       memset(buf + 16, 0, AUDIO_BLOCK_LEN - 16);
  2509.     }
  2510.     else {
  2511.       memset(buf, 0, blockLen);
  2512.     }
  2513.     
  2514.     while (len > 0) {
  2515.       if (mode == TrackData::MODE1_RAW || mode == TrackData::MODE2_RAW) {
  2516. Msf m(lba + 150);
  2517. buf[12] = SubChannel::bcd(m.min());
  2518. buf[13] = SubChannel::bcd(m.sec());
  2519. buf[14] = SubChannel::bcd(m.frac());
  2520.       }
  2521.       if ((ret = fullWrite(fd, buf, blockLen)) != blockLen) {
  2522. if (ret < 0)
  2523.   message(-2, "Writing of data failed: %s", strerror(errno));
  2524. else
  2525.   message(-2, "Writing of data failed: Disk full");
  2526.   
  2527. delete[] buf;
  2528. return 1;
  2529.       }
  2530.       trackInfo->bytesWritten += blockLen;
  2531.       
  2532.       len--;
  2533.       lba++;
  2534.     }
  2535.   }
  2536.   delete[] buf;
  2537.   
  2538.   return 0;
  2539. }
  2540. // Tries to read the catalog number from the sub-channels starting at LBA 0.
  2541. // If a catalog number is found it will be placed into the provided 14 byte
  2542. // buffer 'mcnCode'. Otherwise 'mcnCode[0]' is set to 0.
  2543. // Return: 0: OK
  2544. //         1: SCSI error occured
  2545. #define N_ELEM 11
  2546. #define MCN_LEN 13
  2547. #define MAX_MCN_SCAN_LENGTH 5000
  2548. static int cmpMcn(const void *p1, const void *p2)
  2549. {
  2550.   const char *s1 = (const char *)p1;
  2551.   const char *s2 = (const char *)p2;
  2552.   
  2553.   return strcmp(s1, s2);
  2554. }
  2555. int CdrDriver::readCatalogScan(char *mcnCode, long startLba, long endLba)
  2556. {
  2557.   SubChannel **subChannels;
  2558.   int n, i;
  2559.   long length;
  2560.   int mcnCodeFound = 0;
  2561.   char mcn[N_ELEM][MCN_LEN+1];
  2562.   *mcnCode = 0;
  2563.   length = endLba - startLba;
  2564.   if (length > MAX_MCN_SCAN_LENGTH)
  2565.     length = MAX_MCN_SCAN_LENGTH;
  2566.   while ((length > 0) && (mcnCodeFound < N_ELEM)) {
  2567.     n = (length > maxScannedSubChannels_ ? maxScannedSubChannels_ : length);
  2568.     if (readSubChannels(startLba, n, &subChannels, NULL) != 0 ||
  2569. subChannels == NULL) {
  2570.       return 1;
  2571.     }
  2572.     for (i = 0; i < n; i++) {
  2573.       SubChannel *chan = subChannels[i];
  2574.       //chan->print();
  2575.       if (chan->checkCrc() && chan->checkConsistency()) {
  2576.         if (chan->type() == SubChannel::QMODE2) {
  2577.           if (mcnCodeFound < N_ELEM) {
  2578.             strcpy(mcn[mcnCodeFound++], chan->catalog());
  2579.           }
  2580.         }
  2581.       }
  2582.     }
  2583.     length -= n;
  2584.     startLba += n;
  2585.   }
  2586.   if(mcnCodeFound > 0) {
  2587.     qsort(mcn, mcnCodeFound, MCN_LEN + 1, cmpMcn);
  2588.     strcpy(mcnCode, mcn[(mcnCodeFound >> 1)]);
  2589.   }
  2590.   return 0;
  2591. }
  2592. #undef N_ELEM
  2593. #undef MCN_LEN
  2594. #undef MAX_MCN_SCAN_LENGTH
  2595. // read cdda paranoia related:
  2596. void CdrDriver::paranoiaMode(int mode)
  2597. {
  2598.   paranoiaMode_ = PARANOIA_MODE_FULL^PARANOIA_MODE_NEVERSKIP;
  2599.   switch (mode) {
  2600.   case 0:
  2601.     paranoiaMode_ = PARANOIA_MODE_DISABLE;
  2602.     break;
  2603.   case 1:
  2604.     paranoiaMode_ &= ~PARANOIA_MODE_VERIFY;
  2605.     break;
  2606.   case 2:
  2607.     paranoiaMode_ &= ~(PARANOIA_MODE_SCRATCH|PARANOIA_MODE_REPAIR);
  2608.     break;
  2609.   }
  2610. }
  2611. int CdrDriver::readAudioRangeParanoia(int fd, long start, long end,
  2612.       int startTrack, int endTrack, 
  2613.       TrackInfo *trackInfo)
  2614. {
  2615.   long startLba = start;
  2616.   long endLba = end - 1;
  2617.   long len, ret;
  2618.   size16 *buf;
  2619.   if (paranoia_ == NULL) {
  2620.     // first time -> allocate paranoia structure 
  2621.     paranoiaDrive_ = new cdrom_drive;
  2622.     paranoiaDrive_->cdr = this;
  2623.     paranoiaDrive_->nsectors = maxScannedSubChannels_;
  2624.     paranoia_ = paranoia_init(paranoiaDrive_);
  2625.   }
  2626.   paranoia_set_range(paranoia_, startLba, endLba);
  2627.   paranoia_modeset(paranoia_, paranoiaMode_);
  2628.   paranoiaTrackInfo_ = trackInfo;
  2629.   paranoiaStartTrack_ = startTrack;
  2630.   paranoiaEndTrack_ = endTrack;
  2631.   paranoiaActLba_ = startLba + 149;
  2632.   paranoiaActTrack_ = startTrack;
  2633.   paranoiaActIndex_ = 1;
  2634.   paranoiaCrcCount_ = 0;
  2635.   paranoiaError_ = 0;
  2636.   paranoiaProgress_ = 0;
  2637.   len = endLba - startLba + 1;
  2638.   message(1, "Track %d...", startTrack + 1);
  2639.   trackInfo[endTrack].bytesWritten = 0;
  2640.   while (len > 0) {
  2641.     buf = paranoia_read(paranoia_, &CdrDriver::paranoiaCallback);
  2642.     // The returned samples are always in host byte order. We want to
  2643.     // output in big endian byte order so swap if we are a little
  2644.     // endian host.
  2645.     if (hostByteOrder_ == 0)
  2646.       swapSamples((Sample*)buf, SAMPLES_PER_BLOCK);
  2647.     if ((ret = fullWrite(fd, buf, AUDIO_BLOCK_LEN)) != AUDIO_BLOCK_LEN) {
  2648.       if (ret < 0)
  2649. message(-2, "Writing of data failed: %s", strerror(errno));
  2650.       else
  2651. message(-2, "Writing of data failed: Disk full");
  2652.       return 1;
  2653.     }
  2654.     trackInfo[endTrack].bytesWritten += AUDIO_BLOCK_LEN;
  2655.     len--;
  2656.   }
  2657.   if (paranoiaCrcCount_ != 0)
  2658.     message(1, "Found %ld Q sub-channels with CRC errors.", paranoiaCrcCount_);
  2659.   return 0;
  2660. }
  2661. long CdrDriver::paranoiaRead(Sample *buffer, long startLba, long len)
  2662. {
  2663.   SubChannel **chans;
  2664.   int i;
  2665.   int swap;
  2666.   if (readSubChannels(startLba, len, &chans, buffer) != 0) {
  2667.     memset(buffer, 0, len * AUDIO_BLOCK_LEN);
  2668.     paranoiaError_ = 1;
  2669.     return len;
  2670.   }
  2671.   swap = (audioDataByteOrder_ == hostByteOrder_) ? 0 : 1;
  2672.   if (options_ & OPT_DRV_SWAP_READ_SAMPLES)
  2673.     swap = !swap;
  2674.   if (swap)
  2675.     swapSamples(buffer, len * SAMPLES_PER_BLOCK);
  2676.   if (chans == NULL) {
  2677.     // drive does not provide sub channel data so that's all we could do here:
  2678.     if (startLba > paranoiaTrackInfo_[paranoiaActTrack_ + 1].start) {
  2679.       paranoiaActTrack_++;
  2680.       message(1, "Track %d...", paranoiaActTrack_ + 1);
  2681.     }
  2682.     if (startLba - paranoiaProgress_ > 75) {
  2683.       paranoiaProgress_ = startLba;
  2684.       Msf m(paranoiaProgress_);
  2685.       message(1, "%02d:%02d:00r", m.min(), m.sec());
  2686.     }
  2687.     
  2688.     return len;      
  2689.   }
  2690.   // analyze sub-channels to find pre-gaps, index marks and ISRC codes
  2691.   for (i = 0; i < len; i++) {
  2692.     SubChannel *chan = chans[i];
  2693.     //chan->print();
  2694.     
  2695.     if (chan->checkCrc() && chan->checkConsistency()) {
  2696.       if (chan->type() == SubChannel::QMODE1DATA) {
  2697. int t = chan->trackNr() - 1;
  2698. Msf atime = Msf(chan->amin(), chan->asec(), chan->aframe());
  2699. //message(0, "LastLba: %ld, ActLba: %ld", paranoiaActLba_, atime.lba());
  2700. if (t >= paranoiaStartTrack_ && t <= paranoiaEndTrack_ &&
  2701.     atime.lba() > paranoiaActLba_ && 
  2702.     atime.lba() - 150 < paranoiaTrackInfo_[t + 1].start) {
  2703.   Msf time(chan->min(), chan->sec(), chan->frame()); // track rel time
  2704.   paranoiaActLba_ = atime.lba();
  2705.   if (paranoiaActLba_ - paranoiaProgress_ > 75) {
  2706.     paranoiaProgress_ = paranoiaActLba_;
  2707.     Msf m(paranoiaProgress_ - 150);
  2708.     message(1, "%02d:%02d:00r", m.min(), m.sec());
  2709.   }
  2710.   if (t == paranoiaActTrack_ &&
  2711.       chan->indexNr() == paranoiaActIndex_ + 1) {
  2712.   
  2713.     if (chan->indexNr() > 1) {
  2714.       message(1, "Found index %d at: %s", chan->indexNr(),
  2715.       time.str());
  2716.   
  2717.       if (paranoiaTrackInfo_[t].indexCnt < 98) {
  2718. paranoiaTrackInfo_[t].index[paranoiaTrackInfo_[t].indexCnt] = time.lba();
  2719. paranoiaTrackInfo_[t].indexCnt += 1;
  2720.       }
  2721.     }
  2722.   }
  2723.   else if (t == paranoiaActTrack_ + 1) {
  2724.     message(1, "Track %d...", t + 1);
  2725.     //chan->print();
  2726.     if (chan->indexNr() == 0) {
  2727.       paranoiaTrackInfo_[t].pregap = time.lba();
  2728.       message(1, "Found pre-gap: %s", time.str());
  2729.     }
  2730.   }
  2731.   paranoiaActIndex_ = chan->indexNr();
  2732.   paranoiaActTrack_ = t;
  2733. }
  2734.       }
  2735.       else if (chan->type() == SubChannel::QMODE3) {
  2736. if (paranoiaTrackInfo_[paranoiaActTrack_].isrcCode[0] == 0) {
  2737.   message(1, "Found ISRC code.");
  2738.   strcpy(paranoiaTrackInfo_[paranoiaActTrack_].isrcCode,
  2739.  chan->isrc());
  2740. }
  2741.       }
  2742.     }
  2743.     else {
  2744.       paranoiaCrcCount_++;
  2745.     }
  2746.   }
  2747.   return len;
  2748. }
  2749. long cdda_read(cdrom_drive *d, void *buffer, long beginsector, long sectors)
  2750. {
  2751.   CdrDriver *cdr = (CdrDriver*)d->cdr;
  2752.   return cdr->paranoiaRead((Sample*)buffer, beginsector, sectors);
  2753. }
  2754. void CdrDriver::paranoiaCallback(long, int)
  2755. {
  2756. }