// KreateCD - CD recording software for the K desktop environment
//
// 1998 by Alexander Feigl <Alexander.Feigl@gmx.de>
//
// This file is subject to the terms and conditions of the GNU General      
// Public License.  See the file COPYING in the main directory of the       
// KreateCD distribution for more details.                                     

#include "DriveAccess.h"
#include "ProgressDialog.h"
#include "Fork.h"
#include "CDTrack.h"


int readiso(int argc,char **argv);

#include <qstring.h>

#include <kprocess.h>
#include <kapp.h>
#include <kmsgbox.h>
#include <kconfig.h>
#include <klocale.h>

#include <strings.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

#include "uidcontrol.h"

extern KLocale *locale;


void DriveAccess::scanSCSIBus(void)
 {
  int i,k;
  KProcess cdrproc;
  KConfig *config;

  config=kapp->getConfig();

  config->setGroup("Path");
  cdrproc<<config->readEntry("PathCdrecord","cdrecord")<<"-scanbus";
  linebuffer[0]='\0';
  connect(&cdrproc,SIGNAL(receivedStdout(KProcess *,char *,int)),
          this,SLOT(getScanBus(KProcess *,char *,int)));
  current_scsibus=-1;
  for (k=0;k<MAX_SCSI_HOSTS;++k)
   {
    for (i=0;i<MAX_SCSI_UNITS;++i)
     {
      scsitype[k][i]=0;
      scsimanuf[k][i][0]='-';
      scsimanuf[k][i][1]=0;
      scsiprod[k][i][0]='-';
      scsiprod[k][i][1]=0;
     }
   }
  unsetenv("CDR_DEVICE"); // workaround for cdrecord
  getRootRights();
  cdrproc.start(KProcess::Block,KProcess::Stdout);
  dropRootRights();
 }

int DriveAccess::getSCSIType(int unit,int host)
 {
  if ( (unit>=MAX_SCSI_UNITS) || (unit<0) ) return(0);
  if ( (host>=MAX_SCSI_HOSTS) || (host<0) ) return(0);
  return (scsitype[host][unit]);
 }

const char * DriveAccess::getSCSIManu(int unit,int host)
 {
  if ( (unit>=MAX_SCSI_UNITS) || (unit<0) ) return(0);
  if ( (host>=MAX_SCSI_HOSTS) || (host<0) ) return(0);
  return(scsimanuf[host][unit]);
 }

const char * DriveAccess::getSCSIProd(int unit,int host)
 {
  if ( (unit>=MAX_SCSI_UNITS) || (unit<0) ) return(0);
  if ( (host>=MAX_SCSI_HOSTS) || (host<0) ) return(0);
  return(scsiprod[host][unit]);
 }

static int copyQuotedString(char **ptr,char *dest)
 {
  while (**ptr==' ') ++(*ptr);
  if (**ptr!='\'') return(0);
  ++(*ptr);
  while ( (**ptr!=0) && (**ptr!='\'') )
   {  
    *(dest++)=**ptr;
    ++(*ptr);
   }
  *dest=0;
  if (**ptr==0) return(0);
  ++(*ptr);
 
  return(1);
 }

void DriveAccess::getScanBus(KProcess *,char *buffer,int bufflen)
 {
  int i;
  char *buf,*buf2;
  i=bufflen;
  buf=buffer;
  buf2=linebuffer;
  while (*buf2!=0) ++buf2;
  while (i>0)
   {
    if (*buf=='\n')
     {
      *buf2=0;
      buf2=linebuffer;
      if (strncmp("scsibus",linebuffer,7)==0)
       {
        long int sbus;
        sbus=strtol(linebuffer+7,0,10);
        if ( (sbus<0) || (sbus>(MAX_SCSI_HOSTS-1)) )
         {
          sbus=-1;
         }
        current_scsibus=sbus;
       }
       else
       {
        char *cptr,*dptr;
        long int unit;
        char dummy[40];
        cptr=linebuffer;
        while ( (*cptr==' ') || (*cptr==9) ) 
         {
          ++cptr;
         }
        unit=strtol(cptr,&dptr,10);
        if (cptr==dptr) goto ignline;
        cptr=dptr;
        unit=unit%100;
        if ( (unit<0) || (unit>(MAX_SCSI_UNITS)) ) goto ignline;
        if (*(cptr++)!=')') goto ignline; 
        if (current_scsibus==-1) goto ignline;
        if (!copyQuotedString(&cptr,scsimanuf[current_scsibus][unit])) goto ignline;
        if (!copyQuotedString(&cptr,scsiprod[current_scsibus][unit])) goto ignline;
        if (!copyQuotedString(&cptr,dummy)) goto ignline;
        while (*cptr==' ') ++cptr;
        scsitype[current_scsibus][unit]=1;
        if (strncmp("Removable CD-ROM",cptr,16)==0) scsitype[current_scsibus][unit]=2;
        ignline:
        *buf2=0;
       }
     }
     else
     {
      *(buf2++)=*buf;
      *buf2=0;
     }
    ++buf;
    --i;
   }
 }


int DriveAccess::readTOC(void)
 {
  int i,tracks=0;
  KProcess cdrproc;
  KConfig *config;
  char devline[32];
  int host,unit;

  config=kapp->getConfig();
  config->setGroup("SCSI");
  host=config->readNumEntry("SCSICdromHost",0);
  unit=config->readNumEntry("SCSICdromUnit",-1);
  if (unit==-1) return(0);
  sprintf(devline,"dev=%d,%d,0",host,unit);

  config->setGroup("Path");
  cdrproc<<config->readEntry("PathCdrecord","cdrecord")<<"-toc"<<devline;
  linebuffer[0]='\0';
  connect(&cdrproc,SIGNAL(receivedStdout(KProcess *,char *,int)),
          this,SLOT(getTOC(KProcess *,char *,int)));

  for (i=0;i<128;++i)
   {
    toc_lba[i]=-1;
   }
  getRootRights();
  cdrproc.start(KProcess::Block,KProcess::Stdout);
  dropRootRights();
  tocsum=0;

  for (i=0;i<128;++i)
   {
    if (toc_lba[i]!=-1) 
     {
      tocsum=     (tocsum*87653)%1234951 + toc_durat[i] + toc_control[i]*123211+
      toc_adr[i]*121714+toc_mode[i]*31821;
      tracks++;
     }
   }
  if (tracks==0) return(0);
  return(1);
 }

void DriveAccess::getTOC(KProcess *,char *buffer,int bufflen)
 {
  int i;
  char *buf,*buf2;
  i=bufflen;
  buf=buffer;
  buf2=linebuffer;
  while (*buf2!=0) ++buf2;
  while (i>0)
   {
    if (*buf=='\n')
     {
      char *cptr,*tptr=0,*lptr=0,*aptr=0,*ctptr=0,*mptr=0,freetoc=0;
      long int track,lba,address,control,mode;

      *buf2=0;
      buf2=linebuffer;
      if (strncmp("track:",linebuffer,6)!=0) goto ignline;
      cptr=linebuffer+6;
      while (toc_lba[freetoc]!=-1) freetoc++;
      tptr=cptr;
      while (*cptr!=0)
       {
        if (strncmp("lba:",cptr,4)==0) lptr=cptr+4;
        if (strncmp("adr:",cptr,4)==0) aptr=cptr+4;
        if (strncmp("control:",cptr,8)==0) ctptr=cptr+8;
        if (strncmp("mode:",cptr,5)==0) mptr=cptr+5;
        ++cptr;   
       }
      if ( (lptr==0) || (aptr==0) || (ctptr==0) || (mptr==0) ) goto ignline;
      track=strtol(tptr,0,10);
      lba=strtol(lptr,0,10);
      address=strtol(aptr,0,10);
      control=strtol(ctptr,0,10);
      mode=strtol(mptr,0,10);
      if (freetoc!=0)
       {
        toc_durat[freetoc-1]=lba-toc_lba[freetoc-1];
       }
      if (track!=(freetoc+1)) goto ignline;
      toc_lba[freetoc]=lba;
      toc_durat[freetoc]=0;
      toc_adr[freetoc]=address;
      toc_control[freetoc]=control;
      toc_mode[freetoc]=mode;
      ignline:
      *buf2=0;
     }
     else
     {
      *(buf2++)=*buf;
      *buf2=0;
     }
    ++buf;
    --i;
   }
 }

long int DriveAccess::getTOCLBA(int track)
 {
  if ( (track<1) || (track>99)) return(-1);
  if ( toc_lba[track-1]==-1) return(-1);
  return(toc_lba[track-1]);
 }
    
long int DriveAccess::getTOCDuration(int track)
 {
  if ( (track<1) || (track>99)) return(-1);
  if ( toc_lba[track-1]==-1) return(-1);
  return(toc_durat[track-1]);
 }

int DriveAccess::getTOCMode(int track)
 {
  if ( (track<1) || (track>99)) return(-1);
  if ( toc_lba[track-1]==-1) return(-1);
  return(toc_mode[track-1]);
 }
   
int DriveAccess::getTOCType(int track)
 {
  if ( (track<1) || (track>99)) return(-1);
  if ( toc_lba[track-1]==-1) return(-1);
  return(toc_control[track-1]);
 }

long int DriveAccess::getTOCSum(void)
 {
  return(tocsum);
 }


int DriveAccess::paranoiaTrack(int track,char *filename)
 {
  int retval;
  KProcess *cdrproc;
  KConfig *config;
  
  char devline[32],trackline[32],progressline[64];
  QString cddev;

  cdrproc=new KProcess();
  config=kapp->getConfig();
  config->setGroup("SCSI");
  cddev=config->readEntry("SCSICdromDevice","");
  if (cddev[0]==0) return(0);

  sprintf(devline,"-d%s",cddev.data());
  sprintf(trackline,"%d",track);
  config->setGroup("Path");
  *cdrproc<<config->readEntry("PathCdparanoia","cdparanoia")<<"-R"<<"-e"<<devline<<trackline<<filename;
  linebuffer[0]='\0';
  connect(cdrproc,SIGNAL(receivedStderr(KProcess *,char *,int)),
          this,SLOT(getParanoia(KProcess *,char *,int)));
  connect(cdrproc,SIGNAL(processExited(KProcess *)),
          this,SLOT(leaveParanoia(KProcess *)));

  sprintf(progressline,locale->translate("Extracting audio track %d from CD..."),track);
  paranoiaprogress=new ProgressDialog(0,0,progressline);
  connect(paranoiaprogress,SIGNAL(canceled()),paranoiaprogress,SLOT(abortCancel()));

  ripflag=0;
  paranoiafrom=0;
  paranoiato=999999;

  getRootRights();
  cdrproc->start(KProcess::NotifyOnExit,KProcess::Stderr);
  dropRootRights();

  retval=paranoiaprogress->exec();  // 1=ripping was OK  -1=abort -2=ripping error  0=window hard closed
  if (retval!=1) remove(filename);
  if (retval==-2)
   {
#if QT_VERSION >= 200
    KMsgBox::message(0,QString::null,locale->translate("Unable to read audio track!"),KMsgBox::EXCLAMATION);
#else
    KMsgBox::message(0,0,locale->translate("Unable to read audio track!"),KMsgBox::EXCLAMATION);
#endif
   }
  
  delete (cdrproc);
  delete (paranoiaprogress);
   
  if (retval!=1) return(0);
 
  return(1);
 }

void DriveAccess::leaveParanoia(KProcess *)
 {
  paranoiaprogress->abortDialog(ripflag?1:-2);
 }

void DriveAccess::getParanoia(KProcess *,char *buffer,int bufflen)
 {
  int i;
  char *buf,*buf2;

  i=bufflen;
  buf=buffer;
  buf2=linebuffer;
  while (*buf2!=0) ++buf2;
  while (i>0)
   {  
    if ( (*buf=='\n') || (*buf=='\r') )
     {
      *buf2=0;
      buf2=linebuffer;
      if (strncmp("Ripping from sector",linebuffer,19)==0)
       {
        char *xptr;
        long int val;
        xptr=linebuffer+19;
        if (*xptr=='\0') goto ignLine;
        while ( *xptr==' ') ++xptr;
        val=strtol(xptr,0,10);
        paranoiafrom=val;
       }
      if (strncmp("\t  to sector",linebuffer,12)==0)
       {
        char *xptr;
        long int val;
        xptr=linebuffer+12;
        if (*xptr=='\0') goto ignLine;
        while ( *xptr==' ') ++xptr;
        val=strtol(xptr,0,10);
        paranoiato=val;
       }
      if (strncmp("##: ",linebuffer,4)==0)
       {
        char *xptr;
        long int val,pval;
        xptr=linebuffer+4;
        if (*xptr=='\0') goto ignLine;
        while ( *xptr==' ') ++xptr;
        val=strtol(xptr,0,10);
        if (val!=-2) goto ignLine;
        while ( (*xptr!='@') && (*xptr!='\0') ) ++xptr;
        if (*xptr=='\0') goto ignLine;
        ++xptr;
        while ( *xptr==' ') ++xptr;
        pval=strtol(xptr,0,10);
        pval/=1176;
        if ( (pval>=paranoiafrom) && (pval<=paranoiato) )
         {
          paranoiaprogress->setProtectedProgress(pval-paranoiafrom,
          (long) paranoiato-paranoiafrom+1 );
         }
       }
      if (strncmp("Done.",linebuffer,5)==0) ripflag=1;

      ignLine:
      *buf2=0;
     }
     else
     {
      *(buf2++)=*buf;
      *buf2=0;
     }
    ++buf;
    --i;
   }
 }

int DriveAccess::readDataTrack(int track,char *filename,long int lba_start,long int size_hint)
 {
  int retval;
  KConfig *config;
  
  char lbaline[32],lenline[32],progressline[64];
  QString cddev;

  IsoFork=new Fork(readiso);
  config=kapp->getConfig();
  config->setGroup("SCSI");
  cddev=config->readEntry("SCSICdromDevice","");
  if (cddev[0]==0) return(0);
  sprintf(lbaline,"%ld",lba_start);
  sprintf(lenline,"%ld",size_hint);

  config->setGroup("Path");
  *IsoFork<<"readiso"<<cddev.data()<<lbaline<<filename<<lenline;
 
  linebuffer[0]='\0';
  connect(IsoFork,SIGNAL(receivedStderr(KProcess *,char *,int)),
          this,SLOT(getISO(KProcess *,char *,int)));
  connect(IsoFork,SIGNAL(processExited(KProcess *)),
          this,SLOT(leaveISO(KProcess *)));

  sprintf(progressline,locale->translate("Extracting data track %d from CD..."),track);
  isoprogress=new ProgressDialog(0,0,progressline);
  connect(isoprogress,SIGNAL(canceled()),isoprogress,SLOT(abortCancel()));

  ripflag=-2;

  getRootRights();
  IsoFork->start(KProcess::NotifyOnExit,KProcess::All);
  dropRootRights();

  retval=isoprogress->exec();  // 1=ripping was OK  -1=abort 0=winclose
                               // -2=unexpected process term -3= DevError
                               // -4=Memory -5=Read -6=Write
  if (retval!=1) remove(filename);
  switch (retval)
   {
#if QT_VERSION >= 200
    case -2:
      KMsgBox::message(0,QString::null,locale->translate("Reading process died!"),KMsgBox::EXCLAMATION);
      break;
    case -3:
      KMsgBox::message(0,QString::null,locale->translate("Cannot access the drive! (no disc?)"),KMsgBox::EXCLAMATION);
      break;
    case -4:
      KMsgBox::message(0,QString::null,locale->translate("Cannot get buffer memory!"),KMsgBox::EXCLAMATION);
      break;
    case -5:
      KMsgBox::message(0,QString::null,locale->translate("CDROM read error occured!"),KMsgBox::EXCLAMATION);
      break;
    case -6:
      KMsgBox::message(0,QString::null,locale->translate("Image file write error! (harddisk full?)"),KMsgBox::EXCLAMATION);
      break;
#else
    case -2:
      KMsgBox::message(0,0,locale->translate("Reading process died!"),KMsgBox::EXCLAMATION);
      break;
    case -3:
      KMsgBox::message(0,0,locale->translate("Cannot access the drive! (no disc?)"),KMsgBox::EXCLAMATION);
      break;
    case -4:
      KMsgBox::message(0,0,locale->translate("Cannot get buffer memory!"),KMsgBox::EXCLAMATION);
      break;
    case -5:
      KMsgBox::message(0,0,locale->translate("CDROM read error occured!"),KMsgBox::EXCLAMATION);
      break;
    case -6:
      KMsgBox::message(0,0,locale->translate("Image file write error! (harddisk full?)"),KMsgBox::EXCLAMATION);
      break;
#endif
   }
  
  delete (IsoFork);
  delete (isoprogress);
   
  if (retval!=1) return(0);
 
  return(1);
 }

void DriveAccess::leaveISO(KProcess *)
 {
  isoprogress->abortDialog(ripflag);
 }

void DriveAccess::getISO(KProcess *,char *buffer,int bufflen)
 {
  int i;
  char *buf,*buf2;

  i=bufflen;
  buf=buffer;
  buf2=linebuffer;
  while (*buf2!=0) ++buf2;
  while (i>0)
   {  
    if ( (*buf=='\n') || (*buf=='\r') )
     {
      *buf2=0;
      buf2=linebuffer;
      if (strncmp("#PROGRESS#",linebuffer,10)==0)
       {
        char *xptr;
        long int val,maxval;
        xptr=linebuffer+10;
        while ( (*xptr!=' ') && (*xptr!='\0') ) ++xptr;
        if (*xptr=='\0') goto ignLine;
        while ( *xptr==' ') ++xptr;
        val=strtol(xptr,0,10);
        while ( (*xptr!=' ') && (*xptr!='\0') ) ++xptr;
        if (*xptr=='\0') goto ignLine;
        while ( *xptr==' ') ++xptr;
        maxval=strtol(xptr,0,10);
        if (maxval>=val) isoprogress->setProtectedProgress(val,maxval);
       }
      if (strcmp("#OK#",linebuffer)==0)
       {
        ripflag=1;
       }

      if (strncmp("#READ#",linebuffer,6)==0)
       {
        char *xptr;
        long int lba;
        int retval;
        char rerrmsg[128];
        char rchar;
        KMsgBox *request;
        xptr=linebuffer+6;
        while ( (*xptr==' ') && (*xptr!='\0') ) ++xptr;
        if (*xptr=='\0') goto ignLine;
        lba=strtol(xptr,0,10);
        sprintf(rerrmsg,locale->translate("CD read error at block %ld!\n"),lba);
#if QT_VERSION >= 200
        request=new KMsgBox(0,QString::null,rerrmsg,KMsgBox::QUESTION,
             locale->translate("Retry"),
             locale->translate("Ignore"),
             locale->translate("Pad with 0"),
             locale->translate("Cancel"));
#else
        request=new KMsgBox(0,0,rerrmsg,KMsgBox::QUESTION,
             locale->translate("Retry"),
             locale->translate("Ignore"),
             locale->translate("Pad with 0"),
             locale->translate("Cancel"));
#endif
        retval=request->exec();
        delete request;
        switch (retval)
         {
          case 1:
            rchar='R';
            break;
          case 2:
            rchar='I';
            break;
          case 3:
            rchar='P';
            break;
          default:
            rchar='C';
            break;
         }
        IsoFork->writeStdin(&rchar,1);
       }
      if (strcmp("#ERROR# Device",linebuffer)==0)
       {
        ripflag=-3;
       }
      if (strcmp("#ERROR# Memory",linebuffer)==0)
       {
        ripflag=-4;
       }
      if (strcmp("#ERROR# Read",linebuffer)==0)
       {
        ripflag=-5;
       }
      if (strcmp("#ERROR# Write",linebuffer)==0)
       {
        ripflag=-6;
       }

      ignLine:
      *buf2=0;
     }
     else
     {
      *(buf2++)=*buf;
      *buf2=0;
     }
    ++buf;
    --i;
   }
 }



int DriveAccess::burnCD(int ntrack,CDTrack **track,int simmode,int speed,Fixating fix,int eject)
 {
  return(callRecord(ntrack,track,simmode,speed,fix,eject,false));
 }

long int DriveAccess::getCDFree(int ntrack,CDTrack **track,Fixating fix)
 {
  int rc;
  rc=callRecord(ntrack,track,1,1,fix,0,true);
  if (rc!=1) return(-1);
  if (ntrack==0)
   {
    return(blocksFree);
   }
   else
   {
    return(blocksRemain);
   }
 }

int DriveAccess::callRecord(int ntrack,CDTrack **track,int simmode,int speed,Fixating fix,int eject,bool capread)
 {
  int retval,i;
  CDTrack *xtrack;
  KConfig *config;
  enum CDTrack::TrackType cmode,xmode;

  char devline[32],speedline[32];
  int unit,host;


  getCapacity=capread;
  cdrproc=new KProcess();
  config=kapp->getConfig();
  config->setGroup("SCSI");
  host=config->readNumEntry("SCSIWriterHost",0);
  unit=config->readNumEntry("SCSIWriterUnit",-1);
  if (unit==-1) return(0);

  sprintf(devline,"dev=%d,%d,0",host,unit);
  sprintf(speedline,"speed=%d",speed);
  config->setGroup("Path");
  *cdrproc<<config->readEntry("PathCdrecord","cdrecord")<<"-v"<<devline<<speedline;
  if (simmode) *cdrproc<<"-dummy";
  switch (fix)
   {
    case Fix_None:
      *cdrproc<<"-nofix";
      break;
    case Fix_Session:
      *cdrproc<<"-multi";
      break;
    case Fix_CD:
      break;
   }

  if (eject) *cdrproc<<"-eject";



  cmode=CDTrack::Track_DataMode1;

  for (i=0;i<ntrack;++i)
   {
    char imagefile[1024];
    xtrack=track[i];

    if (!xtrack->getBurnFile(imagefile))
     {
      delete (cdrproc);
#if QT_VERSION >= 200
      KMsgBox::message(0,QString::null,locale->translate("Image file not found!"),KMsgBox::EXCLAMATION);
#else
      KMsgBox::message(0,0,locale->translate("Image file not found!"),KMsgBox::EXCLAMATION);
#endif
      return(0);
     }
    xmode=xtrack->getTrackType();
    if ( (xmode!=cmode) || (i==0) )
     {
      if (cmode==CDTrack::Track_AudioPreEmph) *cdrproc<<"-nopreemp";
      cmode=xmode;
      switch(xmode)
       {
        case CDTrack::Track_Audio:
          *cdrproc<<"-audio";
          break;
        case CDTrack::Track_AudioPreEmph:
          *cdrproc<<"-audio"<<"-preemp";
          break;
        case CDTrack::Track_DataMode1:
          *cdrproc<<"-data";
          break;
        case CDTrack::Track_DataMode2:
          *cdrproc<<"-mode2";
          break;
        case CDTrack::Track_XA1:
          *cdrproc<<"-xa1";
          break;
        case CDTrack::Track_XA2:
          *cdrproc<<"-xa2";
          break;
        case CDTrack::Track_CDI:
          *cdrproc<<"-cdi";
          break;
       }
     }
    *cdrproc<<imagefile;
   }

  if (ntrack==0)
   {
    if (!getCapacity)
     {
      delete(cdrproc);
      return(0);
     }
     else
     {
      FILE *duf;
      char dumpath[512];
      KConfig *mconfig;
      mconfig=kapp->getConfig();
      mconfig->setGroup("Path");
      strcpy(dumpath,mconfig->readEntry("Temporary","/tmp"));
      strcat(dumpath,"/dummyfile");
      *cdrproc<<dumpath;
      duf=fopen(dumpath,"wb");
      fclose (duf);
     }
   }

  linebuffer[0]='\0';
  connect(cdrproc,SIGNAL(receivedStdout(KProcess *,char *,int)),
          this,SLOT(getCdrecord(KProcess *,char *,int)));
  connect(cdrproc,SIGNAL(receivedStderr(KProcess *,char *,int)),
          this,SLOT(getCdrecord(KProcess *,char *,int)));
  connect(cdrproc,SIGNAL(processExited(KProcess *)),
          this,SLOT(leaveCdrecord(KProcess *)));

  cdrecordprogress=new ProgressDialog(0,0,
  getCapacity?locale->translate("Reading capacity ..."):locale->translate("Preparing burning ..."));
  connect(cdrecordprogress,SIGNAL(canceled()),cdrecordprogress,SLOT(abortCancel()));
  if (!getCapacity) cdrecordprogress->addStatusView();

  burnstate=0;
  burntrack=0;
  burnsize=100;


  getRootRights();
  cdrproc->start(KProcess::NotifyOnExit,KProcess::AllOutput);
  dropRootRights();

  retval=cdrecordprogress->exec();  // 1=ripping was OK  -1=abort -2=ripping error  0=window hard closed
  delete (cdrproc);
  delete (cdrecordprogress);

  if (retval==-2)
   {
    switch (burnstate)
     {
#if QT_VERSION >= 200
      case 10000:
        KMsgBox::message(0,QString::null,locale->translate("Cannot access the drive! (no disc?)"),KMsgBox::EXCLAMATION);
        break;
      case 10001:
        KMsgBox::message(0,QString::null,locale->translate("Cannot open a new session!"),KMsgBox::EXCLAMATION);
        break;
      default:
        KMsgBox::message(0,QString::null,locale->translate("Unrecognized error while writing CD-R!!!"),KMsgBox::EXCLAMATION);
        break;
#else
      case 10000:
        KMsgBox::message(0,0,locale->translate("Cannot access the drive! (no disc?)"),KMsgBox::EXCLAMATION);
        break;
      case 10001:
        KMsgBox::message(0,0,locale->translate("Cannot open a new session!"),KMsgBox::EXCLAMATION);
        break;
      default:
        KMsgBox::message(0,0,locale->translate("Unrecognized error while writing CD-R!!!"),KMsgBox::EXCLAMATION);
        break;
#endif
     }
   }

  if (ntrack==0)
   {
    if (getCapacity)
     {
      char dumpath[512];
      KConfig *mconfig;
      mconfig=kapp->getConfig();
      mconfig->setGroup("Path");
      strcpy(dumpath,mconfig->readEntry("Temporary","/tmp"));
      strcat(dumpath,"/dummyfile");
      remove(dumpath);
     }
   }

  if ( (retval!=1) || (getCapacity))
   {
    FILE *xfile;
    QString qs;
    config->setGroup("SCSI");
    qs=config->readEntry("SCSIWriterDevice","/dev/null");
    getRootRights();
    xfile=fopen(qs.data(),"rb");
    if (xfile!=0) fclose(xfile);
    dropRootRights();
   }

  if (retval!=1) return(0);

  return(1);
 }

void DriveAccess::leaveCdrecord(KProcess *)
 {
  cdrecordprogress->abortDialog((burnstate==99999)?1:-2);
 }

void DriveAccess::getCdrecord(KProcess *,char *buffer,int bufflen)
 {
  int i;
  char *buf,*buf2;

  i=bufflen;
  buf=buffer;
  buf2=linebuffer;
  while (*buf2!=0) ++buf2;
  while (i>0)
   {
    if ( (*buf=='\n') || (*buf=='\r') )
     {
      *buf2=0;
      buf2=linebuffer;

      if (strncmp("Blocks total:",linebuffer,13)==0)
       {
        char *xptr,*yptr;
        xptr=linebuffer+13;
        while (*xptr==' ') ++xptr;
        if (*xptr==0) goto ignLine;
        blocksTotal=strtoul(xptr,&yptr,10);
        if (strncmp(" Blocks current:",yptr,16)!=0) goto ignLine;
        xptr=yptr+16;
        while (*xptr==' ') ++xptr;
        if (*xptr==0) goto ignLine;
        blocksFree=strtoul(xptr,&yptr,10);
        if (strncmp(" Blocks remaining:",yptr,18)!=0) goto ignLine;
        xptr=yptr+18;
        while (*xptr==' ') ++xptr;
        if (*xptr==0) goto ignLine;
        blocksRemain=strtoul(xptr,&yptr,10);
        if (xptr==yptr) goto ignLine;
        if (getCapacity)
         {
          burnstate=99999;
          cdrproc->kill(SIGHUP);
         }
        goto doneLine;
       }
      if (strncmp("Starting new track at sector:",linebuffer,29)==0)
       {
        burntrack=0;
        cdrecordprogress->setProgress(0,100);
        goto doneLine;
       }

      if (strncmp("Track ",linebuffer,6)==0)
       {
        char *xptr,*yptr;
        long cur,max,track,fifo;
        xptr=linebuffer+6;
        while (*xptr==' ') ++xptr;
        if (*xptr==0) goto ignLine;
        track=strtol(xptr,&yptr,10);
        if (*yptr!=':') goto ignLine;
        xptr=yptr+1;
        while (*xptr==' ') ++xptr;
        if ( (*xptr=='0') && (*(xptr+1)==' ') )
         {
          cur=0;
          yptr=xptr+1;
         }
         else
         {
          cur=strtol(xptr,&yptr,10);
         }
        if (strncmp(" of ",yptr,4)!=0) goto ignLine;
        xptr=yptr+4;
        while (*xptr==' ') ++xptr;
        if (*xptr==0) goto ignLine;
        max=strtol(xptr,&yptr,10);
        fifo=100;
        if (strncmp(" MB written",yptr,11)==0) goto noFifo;
        if (strncmp(" MB written (fifo ",yptr,18)!=0) goto ignLine;
        xptr=yptr+18;
        while (*xptr==' ') ++xptr;
        if (*xptr==0) goto ignLine;
        fifo=strtoul(xptr,&yptr,10);
        noFifo:
        if (max==0) max=1;
        cdrecordprogress->setProgress(cur,max);
        if (burntrack==0)
         {
          char xwork[128];
          sprintf(xwork,locale->translate("Writing track %ld"),track);
          cdrecordprogress->setWorkText(xwork);
         }
        goto surpressLine;
       }
      if (strncmp("Fixating...",linebuffer,11)==0)
       {
        cdrecordprogress->setWorkText(locale->translate("Fixating..."));
        goto doneLine;
       }
       {
        char *xptr;
        xptr=linebuffer;
        while ( (*xptr!=0) && (*xptr!=':') ) ++xptr;
        if (*xptr!=0)
         {
          xptr++;
          while (*xptr==' ') ++xptr;
          if (strncmp("fifo had ",xptr,9)==0)
           {
            if (burnstate<10000) burnstate=99999;
            goto doneLine;
           }
          if (strncmp("No disk",xptr,7)==0)
           {
            burnstate=10000;
            goto doneLine;
           }
          if (strncmp("Cannot open new session",xptr,23)==0)
           {
            burnstate=10001;
           }
         }
       }



      ignLine:
      doneLine:
        cdrecordprogress->printStatusLine(QString(linebuffer));
      surpressLine:
      *buf2=0;
     }
     else
     {
      *(buf2++)=*buf;
      *buf2=0;
     }
    ++buf;
    --i;
   }
 }

