/* * * $Id: k3bclonetocreader.cpp 619556 2007-01-03 17:38:12Z trueg $ * Copyright (C) 2003 Sebastian Trueg * * This file is part of the K3b project. * Copyright (C) 1998-2007 Sebastian Trueg * * 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 #include "k3bclonetocreader.h" #include #include #include #include #include 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; } }