~ubuntustudio-dev/+junk/gcdmaster-gtk3

« back to all changes in this revision

Viewing changes to dao/PlextorReaderScan.cc

  • Committer: Janne (astraljava) Jokitalo
  • Date: 2012-01-19 15:26:14 UTC
  • Revision ID: astraljava@kapsi.fi-20120119152614-nss8fhm03n10wu07
Initial commit, registering branch

Show diffs side-by-side

added added

removed removed

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