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

SCSI/ASPI

开发平台:

MultiPlatform

  1. /*  cdrdao - write audio CD-Rs in disc-at-once mode
  2.  *
  3.  *  Copyright (C) 1998  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: PlextorReaderScan.cc,v $
  21.  * Revision 1.4  1999/04/05 18:49:22  mueller
  22.  * Added driver options.
  23.  * Added option to read Q sub-channel data instead of raw PW sub-channel
  24.  * data for 'read-toc'.
  25.  *
  26.  * Revision 1.3  1999/03/27 20:56:39  mueller
  27.  * Changed toc analysis interface.
  28.  * Added support for toc analysis of data disks.
  29.  *
  30.  * Revision 1.2  1998/09/27 19:20:05  mueller
  31.  * Added retrieval of control nibbles for track with 'analyzeTrack()'.
  32.  *
  33.  * Revision 1.1  1998/09/07 15:15:40  mueller
  34.  * Initial revision
  35.  *
  36.  */
  37. static char rcsid[] = "$Id: PlextorReaderScan.cc,v 1.4 1999/04/05 18:49:22 mueller Exp mueller $";
  38. #include <config.h>
  39. #include <string.h>
  40. #include <assert.h>
  41. #include "PlextorReaderScan.h"
  42. #include "PWSubChannel96.h"
  43. #include "PQSubChannel16.h"
  44. #include "Toc.h"
  45. #include "util.h"
  46. PlextorReaderScan::PlextorReaderScan(ScsiIf *scsiIf, unsigned long options)
  47.   : PlextorReader(scsiIf, options)
  48. {
  49.   int i;
  50.   driverName_ = "Plextor CD-ROM Reader (scanning) - Version 1.0";
  51.   for (i = 0; i < maxScannedSubChannels_; i++) {
  52.     if (options_ & OPT_PLEX_USE_PQ)
  53.       scannedSubChannels_[i] = new PQSubChannel16;
  54.     else 
  55.       scannedSubChannels_[i] = new PWSubChannel96;
  56.   }
  57. }
  58. PlextorReaderScan::~PlextorReaderScan()
  59. {
  60.   int i;
  61.   for (i = 0; i < maxScannedSubChannels_; i++) {
  62.     delete scannedSubChannels_[i];
  63.     scannedSubChannels_[i] = NULL;
  64.   }
  65. }
  66. // static constructor
  67. CdrDriver *PlextorReaderScan::instance(ScsiIf *scsiIf, unsigned long options)
  68. {
  69.   return new PlextorReaderScan(scsiIf, options);
  70. }
  71. Toc *PlextorReaderScan::readDisk(int session, const char *fname)
  72. {
  73.   Toc *toc = CdrDriver::readDisk(session, fname);
  74.   setBlockSize(MODE1_BLOCK_LEN);
  75.   return toc;
  76. }
  77. int PlextorReaderScan::analyzeTrack(TrackData::Mode mode, int trackNr,
  78.     long startLba,
  79.     long endLba, Msf *indexIncrements,
  80.     int *indexIncrementCnt, long *pregap,
  81.     char *isrcCode, unsigned char *ctl)
  82. {
  83.   int ret = analyzeTrackScan(mode, trackNr, startLba, endLba,
  84.      indexIncrements, indexIncrementCnt, pregap,
  85.      isrcCode, ctl);
  86.   if ((options_ & OPT_PLEX_READ_ISRC) ||
  87.       ((options_ & OPT_PLEX_USE_PQ) && !(options_ & OPT_PLEX_PQ_BCD))) {
  88.     // The ISRC code is usually not usable if the PQ channel data is
  89.     // converted to hex numbers by the drive. Read them with the
  90.     // appropriate command in this case
  91.     *isrcCode = 0;
  92.     if (mode == TrackData::AUDIO)
  93.       readIsrc(trackNr, isrcCode);
  94.   }
  95.   return ret;
  96. }
  97. int PlextorReaderScan::readSubChannels(long lba, long len, SubChannel ***chans,
  98.        Sample *audioData)
  99. {
  100.   unsigned char cmd[12];
  101.   int i;
  102.   int retries = 5;
  103.   long blockLen;
  104.   if (options_ & OPT_PLEX_USE_PQ)
  105.     blockLen = AUDIO_BLOCK_LEN + 16;
  106.   else 
  107.     blockLen = AUDIO_BLOCK_LEN + 96;
  108.   
  109.   cmd[0] = 0xd8;  // READ CDDA
  110.   cmd[1] = 0;
  111.   cmd[2] = lba >> 24;
  112.   cmd[3] = lba >> 16;
  113.   cmd[4] = lba >> 8;
  114.   cmd[5] = lba;
  115.   cmd[6] = 0;
  116.   cmd[7] = len >> 16;
  117.   cmd[8] = len >> 8;
  118.   cmd[9] = len;
  119.   
  120.   if (options_ & OPT_PLEX_USE_PQ)
  121.     cmd[10] = 0x01;
  122.   else
  123.     cmd[10] = 0x02;
  124.   
  125.   cmd[11] = 0;
  126.   while (1) {
  127.     if (sendCmd(cmd, 12, NULL, 0, transferBuffer_, len * blockLen,
  128. retries == 0 ? 1 : 0) != 0) {
  129.       if (retries == 0)
  130. return 1;
  131.     }
  132.     else {
  133.       break;
  134.     }
  135.     retries--;
  136.   }
  137. #if 0
  138.   if (lba > 5000) {
  139.     char fname[200];
  140.     sprintf(fname, "testout_%ld", lba);
  141.     FILE *fp = fopen(fname, "w");
  142.     fwrite(transferBuffer_, blockLen, len, fp);
  143.     fclose(fp);
  144.   }
  145. #endif
  146.   unsigned char *p =  transferBuffer_ + AUDIO_BLOCK_LEN;
  147.   for (i = 0; i < len; i++) {
  148.     if (options_ & OPT_PLEX_USE_PQ) {
  149.       if (!(options_ & OPT_PLEX_PQ_BCD)) {
  150. // Numbers in sub-channel data are hex instead of BCD.
  151. // We have to convert them back to BCD for the 'SubChannel' class.
  152. p[1] = SubChannel::bcd(p[1]);
  153. p[2] = SubChannel::bcd(p[2]);
  154. p[3] = SubChannel::bcd(p[3]);
  155. p[4] = SubChannel::bcd(p[4]);
  156. p[5] = SubChannel::bcd(p[5]);
  157. p[6] = SubChannel::bcd(p[6]);
  158. p[7] = SubChannel::bcd(p[7]);
  159. p[8] = SubChannel::bcd(p[8]);
  160. p[9] = SubChannel::bcd(p[9]);
  161.       }
  162.       ((PQSubChannel16*)scannedSubChannels_[i])->init(p);
  163.       if (scannedSubChannels_[i]->type() != SubChannel::QMODE_ILLEGAL) {
  164. // the CRC of the sub-channel data is usually invalid -> mark the
  165. // sub-channel object that it should not try to verify the CRC
  166. scannedSubChannels_[i]->crcInvalid();
  167.       }
  168.     }
  169.     else {
  170.       ((PWSubChannel96*)scannedSubChannels_[i])->init(p);
  171.     }
  172.     p += blockLen;
  173.   }
  174.   if (audioData != NULL) {
  175.     p = transferBuffer_;
  176.     for (i = 0; i < len; i++) {
  177.       memcpy(audioData, p, AUDIO_BLOCK_LEN);
  178.       p += blockLen;
  179.       audioData += SAMPLES_PER_BLOCK;
  180.     }
  181.   }
  182.   *chans = scannedSubChannels_;
  183.   return 0;
  184. }
  185. int PlextorReaderScan::readAudioRange(int fd, long start, long end,
  186.       int startTrack, int endTrack, 
  187.       TrackInfo *trackInfo)
  188. {
  189.   if (!onTheFly_) {
  190.     if ((options_ & OPT_PLEX_READ_ISRC) ||
  191. ((options_ & OPT_PLEX_USE_PQ) && !(options_ & OPT_PLEX_PQ_BCD))) {
  192.       int t;
  193.       message(1, "Analyzing...");
  194.       
  195.       for (t = startTrack; t <= endTrack; t++) {
  196. message(1, "Track %d...", t + 1);
  197. trackInfo[t].isrcCode[0] = 0;
  198. readIsrc(t + 1, trackInfo[t].isrcCode);
  199. if (trackInfo[t].isrcCode[0] != 0)
  200.   message(1, "Found ISRC code.");
  201.       }
  202.       message(1, "Reading...");
  203.     }
  204.   }
  205.   return CdrDriver::readAudioRangeParanoia(fd, start, end, startTrack,
  206.    endTrack, trackInfo);
  207. }