|
|
|
/*
|
|
|
|
*
|
|
|
|
* $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 <textstream.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;
|
|
|
|
}
|
|
|
|
}
|