summaryrefslogtreecommitdiffstats
path: root/libk3b/jobs/k3bclonetocreader.cpp
blob: 21229372d04004086fbd6d909c72bba963536ac3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
/* 
 *
 * $Id: k3bclonetocreader.cpp 619556 2007-01-03 17:38:12Z trueg $
 * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
 *
 * This file is part of the K3b project.
 * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * See the file "COPYING" for the exact licensing terms.
 */

#include <config.h>


#include "k3bclonetocreader.h"

#include <k3bdeviceglobals.h>
#include <k3bglobals.h>

#include <tqfile.h>
#include <tqtextstream.h>

#include <kdebug.h>


class K3bCloneTocReader::Private
{
public:
  Private()
    : size(0) {
  }

  K3b::Msf size;
  TQString tocFile;
};



K3bCloneTocReader::K3bCloneTocReader( const TQString& filename )
  : K3bImageFileReader()
{
  d = new Private;
  openFile( filename );
}


K3bCloneTocReader::~K3bCloneTocReader()
{
  delete d;
}


const K3b::Msf& K3bCloneTocReader::imageSize() const
{
  return d->size;
}


void K3bCloneTocReader::readFile()
{
  // first of all we check if we find the image file which contains the data for this toc
  // cdrecord always uses this strange file naming:
  //   somedata
  //   somedata.toc

  // filename should always be the toc file
  if( filename().right( 4 ) == ".toc" )
    d->tocFile = filename();
  else
    d->tocFile = filename() + ".toc";

  // now get rid of the ".toc" extension
  TQString imageFileName = d->tocFile.left( d->tocFile.length()-4 );
  if( !TQFile::exists( imageFileName ) ) {
    kdDebug() << "(K3bCloneTocReader) could not find image file " << imageFileName << endl;
    return;
  }

  setImageFilename( imageFileName );

  d->size = 0;

  TQFile f( d->tocFile );
  if( f.open( IO_ReadOnly ) ) {
    //
    // Inspired by clone.c from the cdrecord sources
    //
    char buffer[2048];
    int read = f.readBlock( buffer, 2048 );
    f.close();

    if( read == 2048 ) {
      kdDebug() << "(K3bCloneTocReader) TOC too large." << endl;
      return;
    }

    // the toc starts with a tocheader
    struct tocheader {
      unsigned char len[2];
      unsigned char first; // first session
      unsigned char last; // last session
    };

    struct tocheader* th = (struct tocheader*)buffer;
    int dataLen = K3bDevice::from2Byte( th->len ) + 2;  // the len field does not include it's own length

    if( th->first != 1 ) {
      kdDebug() << "(K3bCloneTocReader) first session != 1" << endl;
      return;
    }

    // the following bytes are multiple instances of
    struct ftrackdesc {
      unsigned char sess_number;
#ifdef WORDS_BIGENDIAN // __BYTE_ORDER == __BIG_ENDIAN
      unsigned char adr      : 4;
      unsigned char control  : 4;
#else
      unsigned char control  : 4;
      unsigned char adr      : 4;
#endif
      unsigned char track;
      unsigned char point;
      unsigned char amin;
      unsigned char asec;
      unsigned char aframe;
      unsigned char res7;
      unsigned char pmin;
      unsigned char psec;
      unsigned char pframe;
    };

    for( int i = 4; i < dataLen; i += 11) {
      struct ftrackdesc* ft = (struct ftrackdesc*)&buffer[i];
      
      if( ft->sess_number != 1 ) {
	kdDebug() << "(K3bCloneTocReader} session number != 1" << endl;
	return;
      }

      // now we check some of the values
      if( ft->point >= 0x1 && ft->point <= 0x63 ) {
	if( ft->adr == 1 ) {
	  // check track starttime
	  if( ft->psec > 60 || ft->pframe > 75 ) {
	    kdDebug() << "(K3bCloneTocReader) invalid track start: " 
		      << (int)ft->pmin << "." 
		      << (int)ft->psec << "."
		      << (int)ft->pframe << endl;
	    return;
	  }
	}
      }
      else {
	switch( ft->point ) {
	case 0xa0:
	  if( ft->adr != 1 ) {
	    kdDebug() << "(K3bCloneTocReader) adr != 1" << endl;
	    return;
	  }

	  // disk type in psec
	  if( ft->psec != 0x00 && ft->psec != 0x10 && ft->psec != 0x20 ) {
	    kdDebug() << "(K3bCloneTocReader) invalid disktype: " << ft->psec << endl;
	    return;
	  }

	  if( ft->pmin != 1 ) {
	    kdDebug() << "(K3bCloneTocReader) first track number != 1 " << endl;
	    return;
	  }

	  if( ft->pframe != 0x0 ) {
	    kdDebug() << "(K3bCloneTocReader) found data when there should be 0x0" << endl;
	    return;
	  }
	  break;

	case  0xa1:
	  if( ft->adr != 1 ) {
	    kdDebug() << "(K3bCloneTocReader) adr != 1" << endl;
	    return;
	  }

	  if( !(ft->pmin >= 1) ) {
	    kdDebug() << "(K3bCloneTocReader) last track number needs to be >= 1." << endl;
	    return;
	  }
	  if( ft->psec != 0x0 || ft->pframe != 0x0 ) {
	    kdDebug() << "(K3bCloneTocReader) found data when there should be 0x0" << endl;
	    return;
	  }
	  break;

	case 0xa2:
	  if( ft->adr != 1 ) {
	    kdDebug() << "(K3bCloneTocReader) adr != 1" << endl;
	    return;
	  }

	  // start of the leadout = size of the image
	  // substract 2 seconds since in cdrecord other than in K3b lba 0 = msf 2:00
	  // (the cdrecord way is actually more accurate but we use k3b::Msf for many
	  // things and it is simpler this way.)
	  d->size = K3b::Msf( ft->pmin, ft->psec, ft->pframe ) - K3b::Msf( 0, 2, 0 );

	  // leadout... no check so far...
	  break;

	default:
	  if( ft->adr != 5 ) {
	    kdDebug() << "(K3bCloneTocReader) adr != 5" << endl;
	    return;
	  }
	  break;
	}
      }
    }

    if( d->size.rawBytes() != K3b::filesize( imageFileName ) ) {
      kdDebug() << "(K3bCloneTocReader) image file size invalid." << endl;
      return;
    }
    
    // ok, could be a cdrecord toc file
    setValid(true);
  }
  else {
    kdDebug() << "(K3bCloneTocReader) could not open file " << d->tocFile << endl;
  }
}