Logo Search packages:      
Sourcecode: qpxtool version File versions  Download package

QPxTool.cpp

/*
 * This file is part of the QPxTool project.
 * Copyright (C) 2005-2006 Gennady "ShultZ" Kozlov <qpxtool@mail.ru>
 *
 * 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 <stdlib.h>
#include <math.h>
#include <common_functions.h>

#include <qlabel.h>
#include <qlineedit.h>
// #include <qbitmap.h>
#include <qimage.h>
#include <qcanvas.h>
#include <qcolor.h>
//#include <qpoint.h>

#include <qcombobox.h>
#include <qcheckbox.h>
#include <qgroupbox.h>
#include <qbuttongroup.h>
#include <qlistview.h>
//#include <qpainter.h>
#include <qprogressbar.h>
#include <qpushbutton.h>
#include <qtextbrowser.h>
#include <qslider.h>
#include <qradiobutton.h>
#include <qmessagebox.h>

//#include <qobject.h>
#include <qthread.h>

#include <transport.h>
#include <qpx_mmc.h>
#include <plextor_features.h>

#include <ASDB.h>
#include <MQChk.h>
#include <SaveHTML.h>
#include <plextor_ext_cx.h>

#include <qmenubar.h>
#include <qpopupmenu.h>
#include <qstatusbar.h>

#include "QPxTool.h"
#define __DEBUG

//#include <QPTMainWin.h>

#include "img/q.xpm"
#include "img/ok.xpm"
#include "img/no.xpm"
#include "img/unknown.xpm"
#include "img/logo.xpm"

#include "version.h"

const int   speeds_sc_cd[]={4,8,24,32,40};
const int   speeds_sc_dvd[]={2,5,8,12};
//const     int   speeds_rd_cd[]={4,8,16,24,32,40,48};
//const     int   speeds_rd_dvd[]={2,5,8,12,16};

      char  drvtbl[_devcnt][32];
      int   drvcnt=0;
      int   drvidx=0;
      int   speedidx;
      int   devtype;
      int   grecn=0;

      int   c1pie_total=0;
      int   c1pie_max=0;
      float c1pie_avg=0.0;
      int   c2pif_total=0;
      int   c2pif_max=0;
      float c2pif_avg=0.0;
      int   cu_total=0;
      int   cu_max=0;
      float cu_avg=0.0;
      float j_min=0;
      float j_max=0;
      float j_avg=0.0;
      float b_min=0;
      float b_max=0;
      float b_avg=0.0;  
      int   TA_cur=0;
      int   TA_new=0;
      int   TA_layer=0;
      int   TA_zone=0;

//QPxToolWidget::QPxToolWidget(QWidget* parent, const char* name, WFlags fl)
QPxToolWidget::QPxToolWidget(QWidget *parent, const char *name)
        : QPxTool_mainwin_UI(parent,name)
{
      pix_logo.convertFromImage(QImage(q_xpm),0);
      setIcon(pix_logo);

      printf(tr("** static init...\n"));
      int   i,j;
      push_abort->setEnabled(false);
      push_skip->setEnabled(false);

//    progress_test->setCenterIndicator(true);
//    progress_test->setPercentageVisible(true);
//    progress_test->setProgress(0);
//    current_test->setText("idle...");
//    map_r0 = new QBitmap(400,200,true);
//    map_r0->setSize(400,200);
//    paint_r1.begin(pix_r1,true);
//    paint_r1.setPen(QPen(green, 1, SolidLine));

      printf(tr("** dinamic objects init...\n"));
      device=(char*)malloc(0xFF);
      logo = new QImage(logo_xpm);

      printf(tr("** Initializing menu bar...\n"));
// -----------------
//    menubar = new QMenuBar (this);
//    Menu Bar init
// -----------------
      menu_file = new QPopupMenu (this);
//    menu_file->setCheckable(true);
      menu_save = new QPopupMenu (this);
      menu_save->insertItem(tr("Transfer rate"),this,SLOT(file_save_rd()));
      menu_save->insertItem(tr("Cx/Pi"),this,SLOT(file_save_cx()));
      menu_save->insertItem(tr("Jitter/Beta"),this,SLOT(file_save_jb()));
      menu_save->insertItem(tr("FE/TE"),this,SLOT(file_save_ft()));
      menu_save->insertItem(tr("Time analyser"),this,SLOT(file_save_ta()));
      menu_file->insertItem(tr("Save results..."),menu_save);

      menu_file->insertItem(tr("Save all as html"),this,SLOT(file_save()));
      menu_file->insertSeparator();
      menu_file->insertItem(tr("Quit"),this,SLOT(quit()));
//    menubar->insertItem("File",menu_file);
      MenuBarEditor->insertItem(tr("File"),menu_file);
      menu_view = new QPopupMenu (this);
      menu_view->insertItem(tr("Clear Log"),this,SLOT(clear_debug()));
      menu_view->insertItem(tr("Clear Transfer rate Results"),this,SLOT(zero_rd()));
      menu_view->insertItem(tr("Clear Cx/Pi Results"),this,SLOT(zero_cx()));
      menu_view->insertItem(tr("Clear Jitter/Beta Results"),this,SLOT(zero_jb()));
      menu_view->insertItem(tr("Clear FE/TE Results"),this,SLOT(zero_ft()));
      menu_view->insertItem(tr("Clear TA Results"),this,SLOT(zero_ta()));
      menu_view->insertSeparator();
      menu_view->insertItem(tr("Clear ALL"),this,SLOT(clear_all()));
//    menubar->insertItem("View",menu_view);
      MenuBarEditor->insertItem(tr("View"),menu_view);
      menu_device = new QPopupMenu (this);
      menu_device->insertItem(tr("Rescan IDE/SCSI bus"),this,SLOT(scanbus()));
      menu_device->insertItem(tr("Update media info"),this,SLOT(update_device_info()));
//    menubar->insertItem("Device",menu_device);
      MenuBarEditor->insertItem(tr("Device"),menu_device);

      menu_about = new QPopupMenu (this);
      menu_about->insertItem(tr("About QPxTool"),this,SLOT(about()));
//    menubar->insertItem("About",menu_about);
      MenuBarEditor->insertItem(tr("About"),menu_about);

//    menu_help = new QPopupMenu (this);
//    menu_help->insertItem("About Qt",this,SLOT(aboutQt()));
//    menubar->insertItem("Help",menu_help);


// -----------------
//    Status Bar init
// -----------------

      progress_test = new QProgressBar (this);
//    status_device->setGeometry(QSize(220,16));
      progress_test->setMinimumSize(QSize(160,16));
      progress_test->setMaximumSize(QSize(160,18));
      progress_test->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred));
      statusBar()->addWidget(progress_test);
      progress_test->reset();

      status_current_test = new QLabel (this);
      status_current_test->setMinimumSize(QSize(160,16));
      status_current_test->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred));
      statusBar()->addWidget(status_current_test);

      status_media_type = new QLabel (this);
      status_media_type->setMinimumSize(QSize(200,16));
      status_media_type->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred));
      statusBar()->addWidget(status_media_type);

      status_MID = new QLabel (this);
      status_MID->setMinimumSize(QSize(320,16));
      status_MID->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred));
      statusBar()->addWidget(status_MID);

// -----------------
//    Graph lines init
// ------------------------------------------------------------
      printf(tr("** Read TR graph init...\n"));

      CanvasRD = new QCanvas ( pix_rate_rd, "CanvasRD" );
      CanvasRD->setBackgroundColor ( white );
      CanvasRD->setAdvancePeriod ( 100 );
      CanvasRD->resize ( hres, vres );
      CanvasViewRD = new QCanvasView ( CanvasRD, pix_rate_rd, "CanvasViewRD" );
      CanvasViewRD->resize ( hres+4, vres+4 );
// -----------------
      GridRD = (QCanvasLine**) malloc (grids_RD*sizeof(QCanvasLine*));
      DrawGridRD();
// -----------------
      RezRD = (QCanvasLine**) malloc ((hres)*sizeof(QCanvasLine*));
      for (i=0; i< hres; i++) {
            RezRD[i] = new QCanvasLine( CanvasRD );
            RezRD[i]->setPen(QPen(QColor(0xFF,0,0), 1, SolidLine));
            RezRD[i]->show();
      }

// ------------------------------------------------------------
      printf(tr("** Cx/Pi graph init... "));

      Canvas0 = new QCanvas ( pix_r0, "Canvas0" );
      Canvas0->setBackgroundColor ( white );
      Canvas0->setAdvancePeriod ( 100 );
      Canvas0->resize ( hres, vres );
      CanvasView0 = new QCanvasView ( Canvas0, pix_r0, "CanvasView0" );
      CanvasView0->resize ( hres+4, vres+4 );
// -----------------
      printf(tr("C1/PIE"));
      Rez0 = (QCanvasLine**) malloc ((hres)*sizeof(QCanvasLine*));
      for (i=0; i< hres; i++) {
            Rez0[i] = new QCanvasLine( Canvas0 );
            Rez0[i]->setPen(QPen(QColor(0,0xC0,0), 1, SolidLine));
//          Rez0[i]->setPen(QPen(qRgba(0,0xC0,0,0x10), 1, SolidLine));
//          Rez0[i]->show();
      }
      printf(tr(", C2/PIF"));
      Rez1 = (QCanvasLine**) malloc (hres*sizeof(QCanvasLine*));
      for (i=0; i< hres; i++) {
            Rez1[i] = new QCanvasLine( Canvas0 ); // ( Canvas1 );
            Rez1[i]->setPen(QPen(QColor(0xFF,0,0), 1, SolidLine));
//          Rez1[i]->show();
      }
      printf(tr(", CU\n"));
      Rez2 = (QCanvasLine**) malloc (hres*sizeof(QCanvasLine*));
      for (i=0; i< hres; i++) {
            Rez2[i] = new QCanvasLine( Canvas0 ); // ( Canvas1 );
            Rez2[i]->setPen(QPen(QColor(0,0,0), 1, SolidLine));
//          Rez2[i]->show();
      }
// -----------------
      Grid0 = (QCanvasLine**) malloc (grids_CX*sizeof(QCanvasLine*));
      DrawGrid0();

// ------------------------------------------------------------
      printf(tr("** J/B graph init..."));

      CanvasJB = new QCanvas ( pix_jb, "CanvasJB" );
      CanvasJB->setBackgroundColor ( white );
      CanvasJB->setAdvancePeriod ( 100 );
      CanvasJB->resize ( hres, vres );
      CanvasViewJB = new QCanvasView ( CanvasJB, pix_jb, "CanvasViewJB" );
      CanvasViewJB->resize ( hres+4, vres+4 );
// -----------------
      GridJB = (QCanvasLine**) malloc (grids_JB*sizeof(QCanvasLine*));
      DrawGridJB();
// -----------------
      RezJ = (QCanvasLine**) malloc ((hres)*sizeof(QCanvasLine*));
      for (i=0; i< hres; i++) {
            RezJ[i] = new QCanvasLine( CanvasJB );
            RezJ[i]->setPen(QPen(QColor(0,0x80,0), 1, SolidLine));
//          RezJ[i]->show();
      }
      printf(tr(" Jitter OK"));

      RezB = (QCanvasLine**) malloc ((hres)*sizeof(QCanvasLine*));
      for (i=0; i< hres; i++) {
            RezB[i] = new QCanvasLine( CanvasJB ); // ( Canvas1 );
            RezB[i]->setPen(QPen(QColor(0xFF,0,0), 1, SolidLine));
//          RezB[i]->show();
      }
      printf(tr(", Beta OK\n"));

// ------------------------------------------------------------
      printf(tr("** FE/TE graph init..."));

      CanvasFT = new QCanvas ( pix_fete, "CanvasFT" );
      CanvasFT->setBackgroundColor ( white );
      CanvasFT->setAdvancePeriod ( 100 );
      CanvasFT->resize ( hres, vres );
      CanvasViewFT = new QCanvasView ( CanvasFT, pix_fete, "CanvasViewFT" );
      CanvasViewFT->resize ( hres+4, vres+4 );
// -----------------
      RezFE = (QCanvasLine**) malloc ((hresft)*sizeof(QCanvasLine*));
      GridFT = (QCanvasLine**) malloc (grids_FT*sizeof(QCanvasLine*));
      DrawGridFT();
// -----------------
      for (i=0; i< hresft; i++) {
            RezFE[i] = new QCanvasLine( CanvasFT ); // ( Canvas1 );
            RezFE[i]->setPen(QPen(QColor(0xFF,0,0), 1, SolidLine));
//          RezTE[i]->show();
      }
      printf(tr(" FE"));
      RezTE = (QCanvasLine**) malloc ((hresft)*sizeof(QCanvasLine*));
      for (i=0; i< hresft; i++) {
            RezTE[i] = new QCanvasLine( CanvasFT ); // ( Canvas1 );
            RezTE[i]->setPen(QPen(QColor(0,0x80,0), 1, SolidLine));
//          RezTE[i]->show();
      }
      printf(tr(", TE\n"));

// ------------------------------------------------------------
      printf(tr("** TA graph init..."));

      CanvasTAP = new QCanvas ( pix_tap, "CanvasTAP" );
      CanvasTAP->setBackgroundColor ( white );
      CanvasTAP->setAdvancePeriod ( 100 );
      CanvasTAP->resize ( hresta, vresta );
      CanvasViewTAP = new QCanvasView ( CanvasTAP, pix_tap, "CanvasViewTAP" );
      CanvasViewTAP->resize ( hresta+4, vresta+4 );
// -----------------
      CanvasTAL = new QCanvas ( pix_tal, "CanvasTAL" );
      CanvasTAL->setBackgroundColor ( white );
      CanvasTAL->setAdvancePeriod ( 100 );
      CanvasTAL->resize ( hresta, vresta );
      CanvasViewTAL = new QCanvasView ( CanvasTAL, pix_tal, "CanvasViewTAL" );
      CanvasViewTAL->resize ( hresta+4, vresta+4 );
// -----------------
      for (i=0; i<6; i++)
            {RezTAP[i] = (QCanvasLine**) malloc ((hresta)*sizeof(QCanvasLine*));
            RezTAL[i] = (QCanvasLine**) malloc ((hresta)*sizeof(QCanvasLine*));}
      for (i=0; i<6; i++) {
            for (j=0; j< hresta; j++) {
                  RezTAP[i][j] = new QCanvasLine( CanvasTAP );
                  RezTAP[i][j]->setPen(QPen(QColor(0,0,0xFF), 1, SolidLine));
                  RezTAL[i][j] = new QCanvasLine( CanvasTAL );
                  RezTAL[i][j]->setPen(QPen(QColor(0xFF,0,0), 1, SolidLine));
            }
            if (!i) TA_show(0); else TA_hide(i);
      }
// -----------------
      GridTAP = (QCanvasLine**) malloc (grids_TA*sizeof(QCanvasLine*));
      GridTAL = (QCanvasLine**) malloc (grids_TA*sizeof(QCanvasLine*));
      DrawGridTA();
      printf(tr(" OK\n"));

// ------------------------------------------------------------
// Limit Vlines
      Limits[0] = new QCanvasLine( CanvasRD );
      Limits[1] = new QCanvasLine( Canvas0 );
      Limits[2] = new QCanvasLine( CanvasJB );
      Limits[3] = new QCanvasLine( CanvasFT );
      Limits[4] = new QCanvasLine( CanvasFT );
      for (i=0;i<5;i++) {
            Limits[i]->setPen(QPen(QColor(0,0,0), 2, SolidLine));
            Limits[i]->setPoints(hres,0,hres,vres);
            Limits[i]->show();
      }
      for (i=0;i<int(spindowns);i++){
            combo_spindown->insertItem(spindown_tbl[i]);
      }
      printf(tr("** PixMaps init...\n"));
      pix_logo.convertFromImage(QImage(q_xpm),0);
      pix_ok.convertFromImage(QImage(ok_xpm),0);
      pix_no.convertFromImage(QImage(no_xpm),0);
      pix_unknown.convertFromImage(QImage(unknown_xpm),0);

      check_c1pie->setChecked(true);
      check_c2pif->setChecked(true);
      check_cu->setChecked(true);
      check_jitter->setChecked(true);
      check_beta->setChecked(true);
      check_fe->setChecked(true);
      check_te->setChecked(true);
      push_px_cx_ext->setEnabled(false);
      
      Exx.BLER= (int*) malloc (hres*sizeof(int));
      Exx.E11 = (int*) malloc (hres*sizeof(int));
      Exx.E21 = (int*) malloc (hres*sizeof(int));
      Exx.E31 = (int*) malloc (hres*sizeof(int));
      Exx.E12 = (int*) malloc (hres*sizeof(int));
      Exx.E22 = (int*) malloc (hres*sizeof(int));
      Exx.E32 = (int*) malloc (hres*sizeof(int));

      Exx.color[0] = color_BLER;
      Exx.color[1] = color_E11; Exx.color[2] = color_E21; Exx.color[3] = color_E31;
      Exx.color[4] = color_E12; Exx.color[5] = color_E22; Exx.color[6] = color_E32;
      ext_cx_active = 0;

      session = -1;
      for (i=0;i<255;i++) sessions[i]=NULL;

      thread = new ScanThread();
      thread->set_parent(this);

      for (i=0;i<(VENDORS+1);i++)combo_commands->insertItem(vendor[i]);

      combo_VariRecStrategy_cd->clear();
      for (i=0; i<varirec_max_str_cd; i++) combo_VariRecStrategy_cd->insertItem(varirec_str_cd_tbl[i]);
      combo_VariRecStrategy_dvd->clear();
      for (i=0; i<varirec_max_str_dvd; i++) combo_VariRecStrategy_dvd->insertItem(varirec_str_dvd_tbl[i]);
      
      combo_silent_cd_rd->clear();
      for (i=0; (silent_cd_rd_tbl[i].val != 0xFF); i++)  combo_silent_cd_rd->insertItem(silent_cd_rd_tbl[i].name);
      combo_silent_cd_wr->clear();
      for (i=0; (silent_cd_wr_tbl[i].val != 0xFF); i++)  combo_silent_cd_wr->insertItem(silent_cd_wr_tbl[i].name);
      combo_silent_dvd_rd->clear();
      for (i=0; (silent_dvd_rd_tbl[i].val != 0xFF); i++) combo_silent_dvd_rd->insertItem(silent_dvd_rd_tbl[i].name);
      combo_silent_dvd_wr->clear();
      for (i=0; (silent_dvd_wr_tbl[i].val != 0xFF); i++) combo_silent_dvd_wr->insertItem(silent_dvd_wr_tbl[i].name);

      combo_silent_access->clear();
      combo_silent_access->insertItem(tr("Fast"));
      combo_silent_access->insertItem(tr("Slow"));

//    printf("** scanbus...\n");
//    drive = new drive_info;
      drive = NULL;
      scanbus();

      printf(tr("** clearing results...\n"));
      clear_all();
      printf(tr("** init done...\n"));
// Hiding incomplete...
//*/
}

QPxToolWidget::~QPxToolWidget()
{
      quit();
}

int QPxToolWidget::print_disc_type(drive_info* drive) //(int media, int disc_type)
{
      if (drive->media.disc_type & DISC_DVD)    {
            switch (drive->media.disc_type) {
                  case DISC_DVDplusR:
                        status_media_type->setText("DVD+R");
                        text_media_type->setText("DVD+R"); break;
                  case DISC_DVDplusRW:
                        status_media_type->setText("DVD+RW");
                        text_media_type->setText("DVD+RW"); break;
                  case DISC_DVDplusRDL:
                        status_media_type->setText("DVD+R DL");
                        text_media_type->setText("DVD+R DL"); break;
                  case DISC_DVDminusR:
                        status_media_type->setText("DVD-R Sequential");
                        text_media_type->setText("DVD-R Sequential"); break;
                  case DISC_DVDminusRWS:
                        status_media_type->setText("DVD-RW Sequential");
                        text_media_type->setText("DVD-RW Sequential"); break;
                  case DISC_DVDminusRWR:
                        status_media_type->setText("DVD-RW Restricted Overwrite");
                        text_media_type->setText("DVD-RW Restricted Overwrite"); break;
                  case DISC_DVDminusRDL:
                        status_media_type->setText("DVD-R DL Sequential");
                        text_media_type->setText("DVD-R DL Sequential"); break;
                  case DISC_DVDROM:
                        status_media_type->setText("DVD-ROM");
                        text_media_type->setText("DVD-ROM"); break;
                  default:
                        status_media_type->setText("DVD, <unknown type>");
                        text_media_type->setText("DVD, <unknown type>");
            }
      } else 
      if (drive->media.disc_type & DISC_CD) {
            switch (drive->media.disc_type & DISC_CD) {
                  case DISC_CDROM:
                        status_media_type->setText("CD-ROM");
                        text_media_type->setText("CD-ROM"); break;
                  case DISC_CDR:
                        status_media_type->setText("CD-R");
                        text_media_type->setText("CD-R"); break;
                  case DISC_CDRW:
                  switch (drive->media.disc_type & DISC_CDRWSUBT) {
                        case DISC_CDRWMS:
                              status_media_type->setText("CD-RW, Multi Speed");
                              text_media_type->setText("CD-RW, Multi Speed"); break;
                        case DISC_CDRWHS:
                              status_media_type->setText("CD-RW, High Speed");
                              text_media_type->setText("CD-RW, High Speed"); break;
                        case DISC_CDRWUS:
                              status_media_type->setText("CD-RW, Ultra Speed");
                              text_media_type->setText("CD-RW, Ultra Speed"); break;
                        case DISC_CDRWUSP:
                              status_media_type->setText("CD-RW, Ultra Speed+");
                              text_media_type->setText("CD-RW, Ultra Speed+"); break;
                        default:
                              status_media_type->setText("CD-RW, <unknown subtype>");
                              text_media_type->setText("CD-RW, <unknown subtype>"); break;
                  }; break;
                  default:
                        status_media_type->setText("CD, <unknown type>");
                        text_media_type->setText("CD, <unknown type>");
            }
      } else 
      if (!drive->media.disc_type) {
            status_media_type->setText(tr("No disc"));
            text_media_type->setText(tr("No disc"));
      } else {
            status_media_type->setText(tr("unknown"));
            text_media_type->setText(tr("unknown"));
      }
      return 1;
}

int QPxToolWidget::print_book_type(drive_info* drive) //(int book_type)
{
      text_book_type->setText(QString("%1 [rev %2]").arg(_book_type_tbl[(drive->media.book_type&0xF0)>>4]).arg(drive->media.book_type&0x0F));   
      return 1;
}

void QPxToolWidget::scanbus()
{
      if (drive) delete drive;
      drvcnt=0;
      int i,inq;
      combo_drive->clear();
      textDebug->append(tr("** Scaning for MMC compliant devices..."));
      printf(tr("** Scaning for MMC compliant devices...\n"));
      for (i=0; i<_devcnt; i++) {
            strcpy(device,_devtbl[i]);
            drive = new drive_info(device);
            inq=inquiry(drive);
            switch (inq) {
                  case 0x00:
                        strcpy(drvtbl[drvcnt],_devtbl[i]);
                        textDebug->append(QString().sprintf("%s: %s %s %s",drvtbl[drvcnt],drive->ven,drive->dev,drive->fw));
                        combo_drive->insertItem(QString().sprintf("%s: %s %s %s",drvtbl[drvcnt],drive->ven,drive->dev,drive->fw));
                        drvcnt++;
                        printf("%s: %s %s %s\n",drive->device,drive->ven,drive->dev,drive->fw);
                        break;
                  case ERR_NO_DEV:
//                      printf("%s: no device found\n",drive->device);
                        break;
                  case ERR_NO_SCSI:
                        printf("%s: not a valid SCSI device\n",drive->device);
                        break;
                  case ERR_NO_MMC:
                        printf("%s: %s %s %s",drive->device,drive->ven,drive->dev,drive->fw);
                        printf(": device is not MMC compliant\n");
                        break;
                  default:
                        printf("%s: ???\n",drive->device);
                        break;
            }
            delete drive;
      }
      textDebug->append(QString(tr("** Scan compleete: %1 device(s) found")).arg(drvcnt));
      printf("** Scan compleete: %d device(s) found\n",drvcnt);
      combo_drive->setCurrentItem(0);
      drive= new drive_info(drvtbl[0]);
      select_device(QString("%1").arg(drive->device));
}

void QPxToolWidget::select_device(const QString& drv)
{
      int drivenum;
      drivenum=combo_drive->currentItem();
      printf(tr("\nSelected: %s\n"),drv.data());
      delete drive;
      strcpy(device,drvtbl[drivenum]);
      drive = new drive_info(device);
      drive->ven_ID = 0; drive->dev_ID = 0;
      text_vendor->clear();
      text_model->clear();
      text_fw->clear();
      text_tla->setText("N/A");
      text_serial->setText("N/A");
      text_speed->setText("0x");
      status_media_type->clear();
      text_media_type->clear();

      check_ss->setEnabled(false);
      check_hcdr->setEnabled(false);
      check_speedread->setEnabled(false);

      check_PoweRec->setEnabled(false);
      check_GigaRec->setEnabled(false);
      combo_GigaRecValue->setEnabled(false);
      check_VariRec_cd->setEnabled(false);
      combo_VariRecPower_cd->setEnabled(false);
      combo_VariRecStrategy_cd->setEnabled(false);
      check_VariRec_dvd->setEnabled(false);
      combo_VariRecPower_dvd->setEnabled(false);
      combo_VariRecStrategy_dvd->setEnabled(false);

      check_bitset_r->setEnabled(false);
      check_bitset_rdl->setEnabled(false);
      check_simul_dvdplus->setEnabled(false);
      group_autostrategy->setEnabled(false);
      group_silent->setEnabled(false);
      group_plexeraser->setEnabled(false);

      text_pr_spd->setText("n/a");
      check_cx->setEnabled(false);
      push_px_cx_ext->setEnabled(false);
      check_jb_cd->setEnabled(false);
      check_pie->setEnabled(false);
      check_pif->setEnabled(false);
      check_jb_dvd->setEnabled(false);
      check_ta->setEnabled(false);
      push_scan_start->setEnabled(false);
//    combo_scan_speed->setEnabled(false);
//    combo_Speed->setEnabled(false);
      combo_Speed->clear();
// //       push_refresh->setEnabled(false);
      devtype=inquiry(drive);
      switch (devtype & 0xFF) {
            case 0x03:
                  textDebug->append(QString(tr("<font color=red>Unable to open: %1</font>")).arg(drive->device));
                  return;
            case 0x0F:
                  textDebug->append(QString(tr("<font color=red>Not an MMC unit: %1</font>")).arg(drive->device));
                  return;
      }
//    push_refresh->setEnabled(true );
      text_vendor->setText(drive->ven);
      text_model->setText(drive->dev);
      text_fw->setText(drive->fw);
//    status_device->setText(QString(" %1 %2 %3").arg(drive->ven).arg(drive->dev).arg(drive->fw));
      convert_to_ID(drive);
      combo_commands->setCurrentItem(drive->ven_ID);
      read_buffer_capacity(drive);
      text_buf_size->setText(QString("%1KB").arg(drive->buffer_size));
      detect_capabilities(drive);
      text_loader->setText(QString("%1").arg(loader_list[drive->loader_id]));
      detect_iface(drive);
      text_iface->setText(QString("%1").arg(drive->iface));

      show_spindown_time(drive);
      if (drive->parms.spindown_idx < spindowns) {
            combo_spindown->setEnabled(true);
            combo_spindown->setCurrentItem(drive->parms.spindown_idx);
      } else {
            combo_spindown->setEnabled(false);
            combo_spindown->setCurrentItem(0);
      }

#ifdef __FEATURE_DEBUG_
      int   fn,id,ftr;
      char  flen;//*/
      for (fn=0; fn<46 ; fn++) {
            get_feature(drive, FEATURES[fn].ID , &flen, &ftr);
            printf("\nFeature 0x%04X: ",FEATURES[fn].ID);
            printf(" %s\n  ",FEATURES[fn].DESC);// else printf("\n");
            for (id=0; id<flen+4; id++) {
                  printf(" 0x%02X",drive->rd_buf[id] & 0xFF);
                  if (!((id+1)%8)) printf("\n  ");
            }
            if (((id)%8)) printf("\n");
      }
      for (fn=0xFF00; fn<0xFFFF ; fn++) {
            get_feature(drive, fn , &flen, &ftr);
            if (flen>4) {
                  printf("\nFeature 0x%04X:  Vendor specific\n  ",fn);
//                if (ftr) 
//                printf(" %s\n  ",FEATURES[fn].DESC);// else printf("\n");
                  for (id=0; id<flen+4; id++) {
                        printf(" 0x%02X",drive->rd_buf[id] & 0xFF);
                        if (!((id+1)%8)) printf("\n  ");
                  }
                  if (((id)%8)) printf("\n");
            }
      }
      printf("\n");
#endif //__FEATURE_DEBUG_
      update_device_info();
      show_capabilities(drive);
      combo_commands->setEnabled(false);
      if ((drive->ven_ID == WR_GENERIC) || (drive->dev_ID == 1 ))
            combo_commands->setEnabled(true);
}

void QPxToolWidget::show_capabilities(drive_info* drive)
{
      printf("Drive capabilities:       0x%08X\n",drive->capabilities);
      printf("Drive Read capabilities:  0x%08X\n",drive->rd_capabilities);
      printf("Drive Write capabilities: 0x%08X\n",drive->wr_capabilities);

      if (drive->capabilities & CAP_REMOVABLE_MEDIA) pix_REMOVABLE_MEDIA->setPixmap(pix_ok);
            else pix_REMOVABLE_MEDIA->setPixmap(pix_no);
      if (drive->capabilities & CAP_SMART) pix_SMART->setPixmap(pix_ok);
            else pix_SMART->setPixmap(pix_no);
      if (drive->capabilities & CAP_MICROCODE_UPGRADE) pix_MICROCODE_UPGRADE->setPixmap(pix_ok);
            else pix_MICROCODE_UPGRADE->setPixmap(pix_no);
      if (drive->capabilities & CAP_MORPHING) pix_MORPHING->setPixmap(pix_ok);
            else pix_MORPHING->setPixmap(pix_no);
      if (drive->capabilities & CAP_POWER_MANAGEMENT) pix_POWER_MANAGEMENT->setPixmap(pix_ok);
            else pix_POWER_MANAGEMENT->setPixmap(pix_no);
      if (drive->capabilities & CAP_EMBEDDED_CHANGER) pix_EMBEDDED_CHANGER->setPixmap(pix_ok);
            else pix_EMBEDDED_CHANGER->setPixmap(pix_no);
      if ((drive->capabilities & CAP_DEFECT_MANAGEMENT)) pix_DEFECT_MANAGEMENT->setPixmap(pix_ok);
            else pix_DEFECT_MANAGEMENT->setPixmap(pix_no);
      if (drive->capabilities & CAP_REAL_TIME_STREAMING) pix_REAL_TIME_STREAMING->setPixmap(pix_ok);
            else pix_REAL_TIME_STREAMING->setPixmap(pix_no);
      if (drive->capabilities & CAP_REAL_TIME_STREAMING) pix_REAL_TIME_STREAMING->setPixmap(pix_ok);
            else pix_REAL_TIME_STREAMING->setPixmap(pix_no);
      if (drive->capabilities & CAP_DVD_CPRM) pix_DVD_CPRM->setPixmap(pix_ok);
            else pix_DVD_CPRM->setPixmap(pix_no);
      if (drive->capabilities & CAP_DVD_CSS) pix_DVD_CSS->setPixmap(pix_ok);
            else pix_DVD_CSS->setPixmap(pix_no);
      if (drive->capabilities & CAP_C2) pix_C2->setPixmap(pix_ok);
            else pix_C2->setPixmap(pix_no);
      if (drive->capabilities & CAP_CD_TEXT) pix_CD_TEXT->setPixmap(pix_ok);
            else pix_CD_TEXT->setPixmap(pix_no);
      if (drive->capabilities & CAP_CD_AUDIO) pix_CD_AUDIO->setPixmap(pix_ok);
            else pix_CD_AUDIO->setPixmap(pix_no);
      if (drive->capabilities & CAP_DAE) pix_DAE->setPixmap(pix_ok);
            else pix_DAE->setPixmap(pix_no);
      if (drive->capabilities & CAP_ACCURATE_STREAM) pix_ACCURATE_STREAM->setPixmap(pix_ok);
            else pix_ACCURATE_STREAM->setPixmap(pix_no);

      if (drive->capabilities & CAP_COMPOSITE) pix_COMPOSITE->setPixmap(pix_ok); 
            else pix_COMPOSITE->setPixmap(pix_no);
      if (drive->capabilities & CAP_DIGITAL_PORT_1) pix_DIGITAL_PORT_1->setPixmap(pix_ok);
            else pix_DIGITAL_PORT_1->setPixmap(pix_no);
      if (drive->capabilities & CAP_DIGITAL_PORT_2) pix_DIGITAL_PORT_2->setPixmap(pix_ok);
            else pix_DIGITAL_PORT_2->setPixmap(pix_no);
      if (drive->capabilities & CAP_MULTISESSION) pix_MULTISESSION->setPixmap(pix_ok);
            else pix_MULTISESSION->setPixmap(pix_no);
      if (drive->capabilities & CAP_MODE2_FORM1) pix_MODE2_FORM1->setPixmap(pix_ok);
            else pix_MODE2_FORM1->setPixmap(pix_no);
      if (drive->capabilities & CAP_MODE2_FORM2) pix_MODE2_FORM2->setPixmap(pix_ok);
            else pix_MODE2_FORM2->setPixmap(pix_no);
      if (drive->capabilities & CAP_TEST_WRITE) pix_TEST_WRITE->setPixmap(pix_ok);
            else pix_TEST_WRITE->setPixmap(pix_no);
      if (drive->capabilities & CAP_READ_BAR_CODE) pix_READ_BAR_CODE->setPixmap(pix_ok);
            else pix_READ_BAR_CODE->setPixmap(pix_no);
      if (drive->capabilities & CAP_UPC) pix_UPC->setPixmap(pix_ok);
            else pix_UPC->setPixmap(pix_no);
      if (drive->capabilities & CAP_ISRC) pix_ISRC->setPixmap(pix_ok);
            else pix_ISRC->setPixmap(pix_no);
      if (drive->capabilities & CAP_SIDE_CHANGE) pix_SIDE_CHANGE->setPixmap(pix_ok);
            else pix_SIDE_CHANGE->setPixmap(pix_no);
      if (drive->capabilities & CAP_LOCK) check_lock->setEnabled(true);
            else check_lock->setEnabled(true);
      if (drive->capabilities & CAP_EJECT) button_eject->setEnabled(true);
            else button_eject->setEnabled(true);
// ************ SHOW READ CAPABILITIES: ************
      if (drive->rd_capabilities & DEVICE_CD_R) pix_rd_cdr->setPixmap(pix_ok);
            else pix_rd_cdr->setPixmap(pix_no);
      if (drive->rd_capabilities & DEVICE_CD_RW) pix_rd_cdrw->setPixmap(pix_ok);
            else pix_rd_cdrw->setPixmap(pix_no);
      if (drive->rd_capabilities & DEVICE_DVD_ROM) pix_rd_dvd_rom->setPixmap(pix_ok);
            else pix_rd_dvd_rom->setPixmap(pix_no);
      if (drive->rd_capabilities & DEVICE_DVD_RAM) pix_rd_dvd_ram->setPixmap(pix_ok);
            else pix_rd_dvd_ram->setPixmap(pix_no);
      if (drive->rd_capabilities & DEVICE_DVD_R) pix_rd_dvd_r->setPixmap(pix_ok);
            else pix_rd_dvd_r->setPixmap(pix_no);
//    if (drive->rd_capabilities & DEVICE_DVD_RW) pix_rd_dvd_rw->setPixmap(pix_ok);
//          else pix_rd_dvd_rw->setPixmap(pix_no);
//    if (drive->rd_capabilities & DEVICE_DVD_R_DL) pix_rd_dvd_r_dl->setPixmap(pix_ok);
//          else pix_rd_dvd_r_dl->setPixmap(pix_no);
      if (drive->rd_capabilities & DEVICE_DVD_PLUS_R) pix_rd_dvdpr->setPixmap(pix_ok);
            else pix_rd_dvdpr->setPixmap(pix_no);
      if (drive->rd_capabilities & DEVICE_DVD_PLUS_RW) pix_rd_dvdprw->setPixmap(pix_ok);
            else pix_rd_dvdprw->setPixmap(pix_no);
      if (drive->rd_capabilities & DEVICE_DVD_PLUS_R_DL) pix_rd_dvdpr_dl->setPixmap(pix_ok);
            else pix_rd_dvdpr_dl->setPixmap(pix_no);

      if (drive->rd_capabilities & DEVICE_DDCD_R) pix_rd_ddcd_r->setPixmap(pix_ok);
            else pix_rd_ddcd_r->setPixmap(pix_no);
      if (drive->rd_capabilities & DEVICE_DDCD_RW) pix_rd_ddcd_rw->setPixmap(pix_ok);
            else pix_rd_ddcd_rw->setPixmap(pix_no);

      if (drive->rd_capabilities & DEVICE_MRW) pix_rd_MRW->setPixmap(pix_ok);
            else pix_rd_MRW->setPixmap(pix_no);
// ************ SHOW WRITE CAPABILITIES: ************
      if (drive->wr_capabilities & DEVICE_CD_R) pix_wr_cdr->setPixmap(pix_ok);
            else pix_wr_cdr->setPixmap(pix_no);
      if (drive->wr_capabilities & DEVICE_CD_RW) pix_wr_cdrw->setPixmap(pix_ok);
            else pix_wr_cdrw->setPixmap(pix_no);
      if (drive->wr_capabilities & DEVICE_DVD_RAM) pix_wr_dvd_ram->setPixmap(pix_ok);
            else pix_wr_dvd_ram->setPixmap(pix_no);
      if (drive->wr_capabilities & DEVICE_DVD_R) pix_wr_dvd_r->setPixmap(pix_ok);
            else pix_wr_dvd_r->setPixmap(pix_no);
      if (drive->wr_capabilities & DEVICE_DVD_RW) pix_wr_dvd_rw->setPixmap(pix_ok);
            else pix_wr_dvd_rw->setPixmap(pix_no);
      if (drive->wr_capabilities & DEVICE_DVD_R_DL) pix_wr_dvd_r_dl->setPixmap(pix_ok);
            else pix_wr_dvd_r_dl->setPixmap(pix_no);
      if (drive->wr_capabilities & DEVICE_DVD_PLUS_R) pix_wr_dvdpr->setPixmap(pix_ok);
            else pix_wr_dvdpr->setPixmap(pix_no);
      if (drive->wr_capabilities & DEVICE_DVD_PLUS_RW) pix_wr_dvdprw->setPixmap(pix_ok);
            else pix_wr_dvdprw->setPixmap(pix_no);
      if (drive->wr_capabilities & DEVICE_DVD_PLUS_R_DL) pix_wr_dvdpr_dl->setPixmap(pix_ok);
            else pix_wr_dvdpr_dl->setPixmap(pix_no);

      if (drive->wr_capabilities & DEVICE_DDCD_R) pix_wr_ddcd_r->setPixmap(pix_ok);
            else pix_wr_ddcd_r->setPixmap(pix_no);
      if (drive->wr_capabilities & DEVICE_DDCD_RW) pix_wr_ddcd_rw->setPixmap(pix_ok);
            else pix_wr_ddcd_rw->setPixmap(pix_no);

      if (drive->wr_capabilities & DEVICE_MRW) pix_wr_MRW->setPixmap(pix_ok);
            else pix_wr_MRW->setPixmap(pix_no);
}

void QPxToolWidget::update_device_info()
{
      drive->ven_features=0;
      drive->chk_features=0;
      detect_check_capabilities(drive);
      if ((drive->ven_ID == WR_PLEXTOR))
      {
            plextor_get_TLA(drive);
            text_tla->setText(drive->TLA);
            get_drive_serial_number(drive);
            text_serial->setText(drive->serial);
            if ((drive->dev_ID == PLEXTOR_760)) {
                  px755_get_auth_code(drive, drive->rd_buf);
                  px755_calc_auth_code(drive->rd_buf);
                  if (px755_send_auth_code(drive, drive->rd_buf)) {
                        printf(" _______________________________________________________ \n");
                        printf("|                                                       |\n");
                        printf("|       WARNING!!!  Detected locked PX-755/PX-760!      |\n");
                        printf("|              It has protected commands                |\n");
                        printf("|    you'll not get full fucntionality of this drive    |\n");
                        printf("|_______________________________________________________|\n");
                  }
            }
            if (!plextor_get_hidecdr_singlesession(drive)) drive->ven_features|=PX_HCDRSS;
            if (!plextor_get_speedread(drive)) drive->ven_features|=PX_SPDREAD;
            if (drive->wr_capabilities) {
                  if (!plextor_get_powerec(drive)) {
                        drive->ven_features|=PX_POWEREC;
                        plextor_get_speeds(drive);
                  }
                  if (!plextor_get_gigarec(drive)) drive->ven_features|=PX_GIGAREC;
                  if (!plextor_get_varirec(drive, VARIREC_CD)) drive->ven_features|=PX_VARIREC_CD;
//                if (!plextor_get_securec(drive)) drive->ven_features|=PX_SECUREC;
                  if (!plextor_get_silentmode(drive)) drive->ven_features|=PX_SILENT;
            }
            if (drive->wr_capabilities & DEVICE_DVD) {
                  if (!plextor_get_varirec(drive, VARIREC_DVD)) drive->ven_features|=PX_VARIREC_DVD;
                  if (!plextor_get_bitset(drive, PLEX_BITSET_R)) drive->ven_features|=PX_BITSET_R;
                  if (!plextor_get_bitset(drive, PLEX_BITSET_RDL)) drive->ven_features|=PX_BITSET_RDL;
                  if (!plextor_get_autostrategy(drive)) drive->ven_features|=PX_ASTRATEGY;
                  if (!plextor_get_testwrite_dvdplus(drive)) drive->ven_features|=PX_SIMUL_PLUS;
            }
            if (drive->dev_ID == PLEXTOR_760) drive->ven_features|=PX_ERASER;
/*
            printf("Trying opcode E9 modes...\n");
            for (int i=0; i<256; i++) {if (!plextor_get_mode(drive,i)) printf(" MODE 0x%02X\n",i);}
*/
/*
            printf("Trying opcode ED modes...\n");
            for (int i=0; i<256; i++) {if (!plextor_get_mode2(drive,i)) printf(" MODE 0x%02X\n",i);}
*/
      };
      printf("** Drive features...\n");
      printf("\t[%s] Hide CD-R & SingleSession\n", drive->ven_features & PX_HCDRSS ? "+" : "-");
      printf("\t[%s] SpeedRead\n", drive->ven_features & PX_SPDREAD ? "+" : "-");
      printf("\t[%s] PoweRec\n", drive->ven_features & PX_POWEREC ? "+" : "-");
      printf("\t[%s] GigaRec\n", drive->ven_features & PX_GIGAREC ? "+" : "-");
      printf("\t[%s] VariRec CD\n", drive->ven_features & PX_VARIREC_CD ? "+" : "-");
      printf("\t[%s] VariRec DVD\n", drive->ven_features & PX_VARIREC_DVD ? "+" : "-");
//    printf("\t[%s] SecuRec\n", drive->ven_features & PX_SECUREC ? "+" : "-");
      printf("\t[%s] Silent mode\n", drive->ven_features & PX_SILENT ? "+" : "-");
      printf("\t[%s] Bitsetting on DVD+R\n", drive->ven_features & PX_BITSET_R ? "+" : "-");
      printf("\t[%s] Bitsetting on DVD+R DL\n", drive->ven_features & PX_BITSET_RDL ? "+" : "-");
      printf("\t[%s] Simulation on DVD+R(W)\n", drive->ven_features & PX_SIMUL_PLUS ? "+" : "-");
      printf("\t[%s] Autostrategy\n", drive->ven_features & PX_ASTRATEGY ? "+" : "-");
      printf("\t[%s] PlexEraser\n", drive->ven_features & PX_ERASER ? "+" : "-");

      get_media_info(drive);
//    if (drive->rd_capabilities & DEVICE_DVD)
      read_rpc_state(drive);
      text_rpc->setText(QString().sprintf("%s",rpc_phase[drive->rpc.phase]));
      if (drive->rpc.phase > 1) {
            text_region->setText(QString().sprintf("%d",drive->rpc.region));
            text_left_u->setText(QString().sprintf("%d",drive->rpc.ch_u));
            text_left_v->setText(QString().     sprintf("%d",drive->rpc.ch_v));
      } else {
            text_region->setText("n/a");
            text_left_u->setText("n/a");
            text_left_v->setText("n/a");
      }
      if (drive->media.disc_type & DISC_DVD) {
            read_disc_regions(drive);
      }

      if (drive->capabilities & CAP_LOCK) {
            get_lock(drive);
            if (drive->parms.status & STATUS_LOCK) check_lock->setChecked(true);
            else check_lock->setChecked(false);
      }
      if (drive->ven_features & PX_HCDRSS) {
            check_ss->setEnabled(true);
            check_ss->setChecked(drive->plextor.sss);
            check_hcdr->setEnabled(true);
            check_hcdr->setChecked(drive->plextor.hcdr);
      }
      if (drive->ven_features & PX_SPDREAD) {
            check_speedread->setEnabled(true);
            check_speedread->setChecked(drive->plextor.spdread);
      }
      if (drive->ven_features & PX_POWEREC) {
            check_PoweRec->setEnabled(true);
            if (drive->plextor.powerec_state) {
                  check_PoweRec->setChecked(true);
            } else {
                  check_PoweRec->setChecked(false);
            }
            show_powerec_speed();
      } else {
            text_pr_spd->setText("n/a");
      }
      if (drive->ven_features & PX_GIGAREC) {
            combo_GigaRecValue->clear();
            check_GigaRec->setEnabled(true);
            if (drive->dev_ID >= PLEXTOR_760) {
                  combo_GigaRecValue->insertItem("0.7");
                  combo_GigaRecValue->insertItem("0.8");
                  combo_GigaRecValue->insertItem("0.9");
                  combo_GigaRecValue->insertItem("1.1");
                  combo_GigaRecValue->insertItem("1.2");
                  combo_GigaRecValue->insertItem("1.3");
            } else {
                  combo_GigaRecValue->insertItem("0.6");
                  combo_GigaRecValue->insertItem("0.7");
                  combo_GigaRecValue->insertItem("0.8");
                  combo_GigaRecValue->insertItem("1.2");
                  combo_GigaRecValue->insertItem("1.3");
                  if (drive->dev_ID == PLEXTOR_PREMIUM)
                        combo_GigaRecValue->insertItem("1.4");
            }
            if (drive->plextor.gigarec)
            {
                  if (drive->dev_ID >= PLEXTOR_760) {
                        switch (drive->plextor.gigarec) {
                              case GIGAREC_07: grecn=0; break;
                              case GIGAREC_08: grecn=1; break;
                              case GIGAREC_09: grecn=2; break;
                              case GIGAREC_11: grecn=3; break;
                              case GIGAREC_12: grecn=4; break;
                              case GIGAREC_13: grecn=5; break;
                        }
                  } else {
                        switch (drive->plextor.gigarec) {
                              case GIGAREC_06: grecn=0; break;
                              case GIGAREC_07: grecn=1; break;
                              case GIGAREC_08: grecn=2; break;
                              case GIGAREC_12: grecn=3; break;
                              case GIGAREC_13: grecn=4; break;
                              case GIGAREC_14: grecn=5; break;
                        }
                  }
                  combo_GigaRecValue->setCurrentItem(grecn);
                  combo_GigaRecValue->setEnabled(true);
                  check_GigaRec->setChecked(true);
            } else {
                  check_GigaRec->setChecked(false);
            }
      }
      if (drive->ven_features & PX_VARIREC_CD) {
//          print_varirec(drive, VARIREC_CD);
            combo_VariRecPower_cd->clear();
            check_VariRec_cd->setEnabled(true);
            int vrecn;
            for (vrecn=0; vrecn<9; vrecn++)     combo_VariRecPower_cd->insertItem(varirec_pwr_tbl[vrecn].name);
            if (drive->plextor.varirec_state_cd)
            {
                  vrecn=0;
                  while ((varirec_pwr_tbl[vrecn].val!=0xFF) &
                        (varirec_pwr_tbl[vrecn].val!=(drive->plextor.varirec_pwr_cd & 0xFF))) vrecn++;
                  combo_VariRecPower_cd->setCurrentItem(vrecn);
                  combo_VariRecPower_cd->setEnabled(true);
                  combo_VariRecStrategy_cd->setCurrentItem(drive->plextor.varirec_str_cd);
                  combo_VariRecStrategy_cd->setEnabled(true);
                  check_VariRec_cd->setChecked(true);
            } else {
                  combo_VariRecPower_cd->setCurrentItem(4);
                  combo_VariRecStrategy_cd->setCurrentItem(0);
                  check_VariRec_cd->setChecked(false);
            }
      }
      if (drive->ven_features & PX_VARIREC_DVD) {
//          print_varirec(drive, VARIREC_DVD);
            combo_VariRecPower_dvd->clear();
            check_VariRec_dvd->setEnabled(true);
            int vrecn;
            for (vrecn=0; vrecn<9; vrecn++)     combo_VariRecPower_dvd->insertItem(varirec_pwr_tbl[vrecn].name);
            if (drive->plextor.varirec_state_dvd)
            {
                  vrecn=0;
                  while ((varirec_pwr_tbl[vrecn].val!=0xFF) &
                        (varirec_pwr_tbl[vrecn].val!=(drive->plextor.varirec_pwr_dvd & 0xFF))) vrecn++;
                  combo_VariRecPower_dvd->setCurrentItem(vrecn);
                  combo_VariRecPower_dvd->setEnabled(true);
                  combo_VariRecStrategy_dvd->setCurrentItem(drive->plextor.varirec_str_dvd);
                  combo_VariRecStrategy_dvd->setEnabled(true);
                  check_VariRec_dvd->setChecked(true);
            } else {
                  combo_VariRecPower_dvd->setCurrentItem(4);
                  combo_VariRecStrategy_dvd->setCurrentItem(0);
                  check_VariRec_dvd->setChecked(false);
            }
      }
      if (drive->ven_features & PX_BITSET_R) {
            check_bitset_r->setEnabled(true);
            if (drive->book_plus_r)
                  check_bitset_r->setChecked(true);
            else
                  check_bitset_r->setChecked(false);
      }
      if (drive->ven_features & PX_BITSET_RDL) {
            check_bitset_rdl->setEnabled(true);
            if (drive->book_plus_rdl)
                  check_bitset_rdl->setChecked(true);
            else
                  check_bitset_rdl->setChecked(false);
      }
      if (drive->ven_features & PX_SILENT) {
            group_silent->setEnabled(true);
//                update_silent_mode(drive);
            printf("\tSilent mode is %s\n",drive->plextor_silent.state? "ON":"OFF");
            plextor_print_silentmode_state(drive);
      }
      if (drive->ven_features & PX_SIMUL_PLUS) {
            check_simul_dvdplus->setEnabled(true);
            if (drive->plextor.testwrite_dvdplus)
                  check_simul_dvdplus->setChecked(true);
            else
                  check_simul_dvdplus->setChecked(false);
      }
      if (drive->ven_features & PX_ASTRATEGY) {
            group_autostrategy->setEnabled(true);
            plextor_print_autostrategy_state(drive);
            if (drive->dev_ID > PLEXTOR_716) {
                  radio_as_forced->setEnabled(true);
                  radio_as_on->setEnabled(true);
            } else {
                  radio_as_forced->setEnabled(false);
                  radio_as_on->setEnabled(false);
            }
            switch (drive->astrategy.state)
            {
                  case AS_AUTO: radio_as_auto->setChecked(true); break;
                  case AS_ON: radio_as_on->setChecked(true); break;
                  case AS_FORCED: radio_as_forced->setChecked(true); break;
                  case AS_OFF: radio_as_off->setChecked(true); break;
            }
      }
}

void QPxToolWidget::get_media_info(drive_info* drive)
{
      QString     g1,g2,g3,g4;
#ifdef __DISP_TRK
      track_info track;
      for (int i=0; i<255; i++)
            if (sessions[i]) {delete sessions[i]; sessions[i]=NULL;}
#endif
      int i;
//    push_scan_start->setEnabled(false);
      combo_scan_speed->setEnabled(false);
      combo_scan_speed->clear();

      check_rd_rate->setEnabled(false);
      check_cx->setEnabled(false);
      push_px_cx_ext->setEnabled(false);
      check_jb_cd->setEnabled(false);
      check_pie->setEnabled(false);
      check_pif->setEnabled(false);
      check_jb_dvd->setEnabled(false);
      check_fete->setEnabled(false);
      check_ta->setEnabled(false);

      text_layers->setText("n/a");
      text_book_type->setText("n/a");
      text_writer->setText("n/a");
      text_MID->setText("n/a");
      status_MID->setText("n/a");
      text_gigarec_rate->setText("n/a");
      strcpy(drive->media.MID,"n/a");
      determine_disc_type(drive);
      print_disc_type(drive);
      get_read_speed(drive);
//    TR1G->clear();CX1G->clear();JB1G->clear();
//    TR2G->clear();CX2G->clear();JB2G->clear();
//    TR3G->clear();CX3G->clear();JB3G->clear();
//    TR4G->clear();CX4G->clear();JB4G->clear();
      TR10->clear();TR20->clear();TR30->clear();
      TR40->clear();TR50->clear();TR60->clear();

      detect_speeds();
      if (drive->media.disc_type) {
            check_rd_rate->setEnabled(true);
//          if (drive->wr_capabilities)
            read_capacity(drive);
            text_sz->setText(QString("%1MB (%2 sectors)").arg(drive->media.capacity/512).arg(drive->media.capacity));
            printf("Disc read capacity: %d sectors/%d ECC blocks/%dMB/%02d:%02d.%02dMSF\n", drive->media.capacity, drive->media.capacity/16, drive->media.capacity/512, (drive->media.capacity-75)/4500, ((drive->media.capacity)/75)%60, drive->media.capacity%75);

            read_free(drive);
            text_cap_blank->setText(QString("%1MB (%2 sectors)").arg(drive->media.capacity_free/512).arg(drive->media.capacity_free));
            printf("Disc free capacity: %d sectors/%d ECC blocks/%dMB/%02d:%02d.%02dMSF\n", drive->media.capacity_free, drive->media.capacity_free/16, drive->media.capacity_free/512, (drive->media.capacity_free-75)/4500, ((drive->media.capacity_free)/75)%60, drive->media.capacity_free%75);

            drive->media.capacity_total = drive->media.capacity+drive->media.capacity_free;
            text_sz_total->setText(QString("%1MB (%2 sectors)").arg(drive->media.capacity_total/512).arg(drive->media.capacity_total));
            printf("Total capacity: %d sectors/%d ECC blocks/%dMB/%02d:%02d.%02dMSF\n", drive->media.capacity_total, drive->media.capacity_total/16, drive->media.capacity_total/512, (drive->media.capacity_total-75)/4500, ((drive->media.capacity_total)/75)%60, drive->media.capacity_total%75);

#ifdef __DISP_TRK
            session=-1;
            if (drive->media.tracks) {
                  for (i=0; i<drive->media.tracks;) {
                        track.n = ++i;
                        read_track_info(drive, &track);
                        if (track.session<255) {
                        if ((track.session-1)>session) {
                              session = track.session-1;
                              printf("Session %d...\n",session+1);
                              sessions[session] = new QListViewItem(list_tracks,QString().sprintf("Session%02d",track.session), "", "", "", "", "");
                        }
//                      tracks = new QListViewItem(list_tracks,"Tracks","Start","End","Type","State");
                        if (track.track_mode == 2)
                              new QListViewItem(sessions[session],
                              QString().sprintf("Track%02d",track.n),
                              QString().sprintf("%s ",track_mode[track.track_mode]),
                              QString().sprintf(" %d:%02d.%02d",track.time.m,track.time.s,track.time.f),
                              QString().sprintf(" %d:%02d.%02d",track.msf_start.m,track.msf_start.s,track.msf_start.f),
                              QString().sprintf(" %d:%02d.%02d",track.msf_end.m,track.msf_end.s,track.msf_end.f) );
                        else
                              new QListViewItem(sessions[session],
                              QString().sprintf("Track%02d",track.n),
                              QString().sprintf(" %s/%s",track_mode[track.track_mode],data_mode[track.data_mode]),
                              QString().sprintf(" %dM",track.size >> 9),
                              QString().sprintf(" %d",track.start),
                              QString().sprintf(" %d",track.end) );
                        sessions[session]->setOpen(true);
                        }
                  }
                  text_sessions->setText(QString().sprintf("%d",drive->media.sessions));
                  text_tracks->setText(QString().sprintf("%d",drive->media.tracks));
            }
#endif
            text_dstate->setText(QString().sprintf("%s",disc_status_list[drive->media.dstatus]));
            text_sstate->setText(QString().sprintf("%s",session_status_list[drive->media.sstatus]));
            text_erasable->setText(QString().sprintf("%s",drive->media.erasable ? "yes" : "no" ));
            if (!drive->media.dstatus) DrawTestLimits(hres+1,hres+1);
      //    if (!drive->media.sstatus) {drive->media.sessions--; drive->media.tracks--;}
            push_scan_start->setEnabled(true);
      } else {
            text_sessions->setText("n/a");
            text_tracks->setText("n/a");
            text_dstate->setText("n/a");
            text_sstate->setText("n/a");
            text_sz_total->setText("n/a");
            text_sz->setText("n/a");
            text_cap_blank->setText("n/a");
            text_erasable->setText("n/a");
            DrawTestLimits(hres+1,hres+1);
      }

      if ( drive->media.disc_type & DISC_DVD ) {
            if (!(drive->media.disc_type & DISC_DVDROM)) {
                  text_MID->setText(drive->media.MID);
                  status_MID->setText(drive->media.MID);
                  text_writer->setText(drive->media.writer);
            }
            if (drive->media.dstatus) check_rd_rate->setEnabled(true);
//*
            if (drive->chk_features & CHK_PIE) check_pie->setEnabled(true);
            if (drive->chk_features & CHK_PIF) check_pif->setEnabled(true);
            if (drive->chk_features & CHK_JB_DVD) check_jb_dvd->setEnabled(true);
            if (drive->chk_features & CHK_FETE) check_fete->setEnabled(true);
            if (drive->chk_features & CHK_TA) check_ta->setEnabled(true);
//*/
/*
            if ((drive->chk_features & CHK_PIE) && (drive->media.dstatus)) check_pie->setEnabled(true);
            if ((drive->chk_features & CHK_PIF) && (drive->media.dstatus)) check_pif->setEnabled(true);
            if ((drive->chk_features & CHK_JB_DVD) && (drive->media.dstatus)) check_jb_dvd->setEnabled(true);
            if ((drive->chk_features & CHK_FETE) && (!drive->media.dstatus)) check_fete->setEnabled(true);
            if ((drive->chk_features & CHK_TA) && (drive->media.dstatus)) check_ta->setEnabled(true);
//*/
            print_disc_type(drive);
            print_book_type(drive);
            text_layers->setText(QString("%1").arg(drive->media.layers));
//          if (drive->media.dstatus) {
            combo_scan_speed->insertItem("2x");
            combo_scan_speed->insertItem("5x");
            combo_scan_speed->insertItem("8x");
            combo_scan_speed->insertItem("12x");
            combo_scan_speed->setEnabled(true);
            switch (drive->parms.scan_speed_dvd)
            {
                  case 5: combo_scan_speed->setCurrentItem(1); break;
                  case 8: combo_scan_speed->setCurrentItem(2); break;
                  default: combo_scan_speed->setCurrentItem(0);
            }
            DrawTestLimits(drive->media.capacity/(hscaleDVD*drive->media.layers), drive->media.capacity_free/(hscaleDVD*drive->media.layers));
            combo_Speed->setEnabled(true);
            g1=QString("%1G").arg(drive->media.layers*1);
            g2=QString("%1G").arg(drive->media.layers*2);
            g3=QString("%1G").arg(drive->media.layers*3);
            g4=QString("%1G").arg(drive->media.layers*4);
            TR10->setText("4");
            TR20->setText("8");
            TR30->setText("12");
            TR40->setText("16");
            TR50->setText("20");
      } else if ( drive->media.disc_type & DISC_CD ) {
            if (!(drive->media.disc_type & DISC_CDROM)) {
                  text_MID->setText(drive->media.MID);
                  status_MID->setText(drive->media.MID);
            }
            if (drive->media.dstatus) check_rd_rate->setEnabled(true);
//*
            if (drive->chk_features & CHK_CX) {
                  check_cx->setEnabled(true);
                  if ((drive->ven_ID == WR_PLEXTOR)) push_px_cx_ext->setEnabled(true);
            }
            if (drive->chk_features & CHK_JB_CD) check_jb_cd->setEnabled(true);
            if (drive->chk_features & CHK_FETE) check_fete->setEnabled(true);
//*/
/*
            if ((drive->chk_features & CHK_CX) && (drive->media.dstatus)) check_cx->setEnabled(true);
            if ((drive->chk_features & CHK_JB_CD) && (drive->media.dstatus)) check_jb_cd->setEnabled(true);
            if ((drive->chk_features & CHK_FETE) && (!drive->media.dstatus)) check_fete->setEnabled(true);
//*/
            combo_scan_speed->insertItem("4x");
            combo_scan_speed->insertItem("8x");
            combo_scan_speed->insertItem("24x");
            combo_scan_speed->insertItem("32x");
            combo_scan_speed->insertItem("40x");
            switch (drive->parms.scan_speed_cd)
            {
                  case 8: combo_scan_speed->setCurrentItem(1); break;
                  case 24: combo_scan_speed->setCurrentItem(2); break;
                  default: combo_scan_speed->setCurrentItem(0);
            }
            if (((drive->ven_ID == WR_PLEXTOR)) && (drive->ven_features & PX_GIGAREC)) {
                  plextor_get_gigarec(drive);
                  int g=0;
                  while ((gigarec_tbl[g].val!=0xFF) & (gigarec_tbl[g].val!=(drive->plextor.gigarec_disc & 0xFF))) g++;
                  text_gigarec_rate->setText(gigarec_tbl[g].name);
            }
            DrawTestLimits(drive->media.capacity/hscaleCD, drive->media.capacity_free/hscaleCD);
            combo_Speed->setEnabled(true);
            g1=tr("176M/20min"); g2=tr("352M/40min"); g3=tr("528M/60min"); g4=tr("704M/80min");
            TR10->setText("10");
            TR20->setText("20");
            TR30->setText("30");
            TR40->setText("40");
            TR50->setText("50");
            TR60->setText("60");
      }
      TR1G->setText(g1);CX1G->setText(g1);JB1G->setText(g1);FT1G->setText(g1);
      TR2G->setText(g2);CX2G->setText(g2);JB2G->setText(g2);FT2G->setText(g2);
      TR3G->setText(g3);CX3G->setText(g3);JB3G->setText(g3);FT3G->setText(g3);
      TR4G->setText(g4);CX4G->setText(g4);JB4G->setText(g4);FT4G->setText(g4);
//    if ( drive->media.type != Media_NoMedia ) combo_Speed->setEnabled(true);
//    if (drive->media.disc_type)
            combo_scan_speed->setEnabled(true);
      status_current_test->setText("idle...");
      if (drive->ven_features & PX_SILENT) silent_mode_update(drive);
      if (drive->ven_features & PX_ERASER) {
            drive->plextor.plexeraser=PLEXERASER_QUICK;
            group_plexeraser->setEnabled(true);
            radio_pxerase_quick->setChecked(true);
            if (drive->media.disc_type & (DISC_CDR | DISC_DVDplusR | DISC_DVDminusR))
                  push_pxerase->setEnabled(true);
            else
                  push_pxerase->setEnabled(false);
      }
}

// void QPxToolWidget::set_scan_speed(const QString& speed)
void QPxToolWidget::set_scan_speed(const QString&)
{
      if ( drive->media.disc_type & DISC_DVD )
            drive->parms.scan_speed_dvd=speeds_sc_dvd[combo_scan_speed->currentItem()];
      else
            drive->parms.scan_speed_cd=speeds_sc_cd[combo_scan_speed->currentItem()];
}

// void QPxToolWidget::set_spindown_time(const QString& spindown)
void QPxToolWidget::set_spindown_time(const QString&)
{
      if (drive->parms.spindown_idx<spindowns) {
            drive->parms.spindown_idx=combo_spindown->currentItem();
            set_spindown(drive);
            show_spindown_time(drive);
      }
}

void QPxToolWidget::show_spindown_time(drive_info* drive)
{
      get_spindown(drive);
      text_spindown->setText(spindown_tbl[drive->parms.spindown_idx]);
}

void QPxToolWidget::lock(int state){
      if (((drive->parms.status & STATUS_LOCK) == STATUS_LOCK) == (state == 2)) return;
      if (state) drive->parms.status |= STATUS_LOCK;
      else drive->parms.status &= (~STATUS_LOCK);
      set_lock(drive);
      check_lock->setChecked((drive->parms.status & STATUS_LOCK));
}

void QPxToolWidget::do_load_eject(){
      if (!get_media_status(drive)) {
            printf("Media %s; Tray is %s\n",
                  (drive->parms.status & STATUS_MEDIA_PRESENT) ? "present" : "absent",
                  (drive->parms.status & STATUS_OPEN) ? "opened" : "closed");
      } else {
            printf("Can't get media status\n");
            drive->parms.status |= STATUS_OPEN;
      }
      load_eject(drive, (drive->parms.status & STATUS_OPEN));
//    load_eject(drive, true);
}

void QPxToolWidget::detect_speeds()
{
      int   idx, spd, prev_spd, spd_kb;
      get_read_speed(drive);
      get_write_speed(drive);
      spd_kb = drive->parms.read_speed_kb;
      printf(tr("== Detecting supported read speeds...\n"));
      for (idx=1; idx<speed_tbl_size;idx++) {
            drive->parms.speed_tbl[idx]=-1;
            drive->parms.speed_tbl_kb[idx]=-1;
      }
      speedidx = 0;
      if ( drive->media.disc_type & DISC_DVD ) {
            drive->parms.read_speed_kb=-1;
            if (!set_read_speed(drive)) {
                  get_read_speed(drive);
                  printf("Max DVD speed via GET_CD_SPEED: %dkB/s\n", drive->parms.read_speed_kb);
                  if ((drive->capabilities & CAP_REAL_TIME_STREAMING) && (!get_performance(drive))) {
                        if (drive->perf.spd_e > 1)
                              drive->parms.max_read_speed_kb =
                                    drive->perf.spd_e;
//                                  (int)(drive->perf.spd_e*((float)2294912/(float)drive->perf.lba_e));
//                      drive->parms.max_read_speed_kb = drive->perf.spd_e;
                        drive->parms.max_read_speed_dvd = (drive->parms.max_read_speed_kb/1350);
                        printf("Max DVD speed via GET_PERFORMANCE: %dkB/s (%dX)\n",
                              drive->parms.max_read_speed_kb, drive->parms.max_read_speed_dvd);
                        drive->parms.speed_mult = drive->parms.read_speed_kb/drive->parms.max_read_speed_dvd;
                        if (drive->parms.speed_mult < 600) drive->parms.speed_mult = 176;
                  } else {
                        drive->parms.max_read_speed_kb = drive->parms.read_speed_kb;
                        printf("GET_PERFORMANCE error: using default multiplier\n");
                        drive->parms.max_read_speed_dvd = (drive->parms.max_read_speed_kb/1350);
                        drive->parms.speed_mult = 1350;
                  }
//                drive->parms.read_speed_kb = spd_kb;
//                set_read_speed(drive);
//                drive->parms.speed_mult= drive->parms.max_read_speed_kb/drive->parms.max_read_speed_dvd;
                  printf("1X multiplier: %d kB/s\n", drive->parms.speed_mult);
                  printf("Max spd: %dkB/s, %dX\n",drive->parms.max_read_speed_kb, drive->parms.max_read_speed_dvd);

                  idx=0; prev_spd=0;
                  for (spd=1; ((idx<speed_tbl_size) && (spd < (drive->parms.max_read_speed_dvd+2))); spd++) {
//                for (spd=1; ((idx<speed_tbl_size) && (spd < 17)); spd++) {
                        drive->parms.read_speed_kb = spd * (drive->parms.speed_mult+1);
                        printf("Trying:  %dX (%d kB/s)\n", spd, drive->parms.read_speed_kb);
                        set_read_speed(drive);
                        get_read_speed(drive);
                        drive->parms.read_speed_dvd = drive->parms.read_speed_kb / drive->parms.speed_mult;
                        if (prev_spd != drive->parms.read_speed_dvd) {
//                            spd = drive->parms.read_speed_dvd;
                              spd = max(spd, drive->parms.read_speed_dvd);
                              drive->parms.speed_tbl[idx] = drive->parms.read_speed_dvd;
                              drive->parms.speed_tbl_kb[idx] = drive->parms.read_speed_kb;
                              printf("Found:  %dX (%d kB/s)\n", drive->parms.speed_tbl[idx], drive->parms.speed_tbl_kb[idx]);
                              prev_spd = drive->parms.read_speed_dvd;
                              idx++;
                              if (drive->capabilities & CAP_REAL_TIME_STREAMING) get_performance(drive);
                        }
                  }
            } else {
                  speedidx=-1;
            }
      } else {
            drive->parms.read_speed_kb=-1;
            if (!set_read_speed(drive)) {
                  get_read_speed(drive);
                  drive->parms.max_read_speed_kb = drive->parms.read_speed_kb;
                  drive->parms.max_read_speed_cd = (drive->parms.max_read_speed_kb/176);
//                drive->parms.speed_mult=drive->parms.max_read_speed_kb/drive->parms.max_read_speed_cd;
                  drive->parms.speed_mult=176;
                  printf("Maximum CD speed: %dX (%d kB/s); 1X = %d kB/s\nSpeeds:\n",
                        drive->parms.max_read_speed_cd,drive->parms.max_read_speed_kb,drive->parms.speed_mult);
                  idx=0; prev_spd=0;
                  for (spd=1; ((idx<speed_tbl_size) && (spd < (drive->parms.max_read_speed_cd+2))); spd++) {
//                for (spd=1; ((idx<speed_tbl_size) && (spd < 72)); spd++) {
                        drive->parms.read_speed_kb = spd * (drive->parms.speed_mult+1);
                        printf("Trying:  %dX (%d kB/s)\n", spd, drive->parms.read_speed_kb);
                        set_read_speed(drive);
                        get_read_speed(drive);
                        drive->parms.read_speed_cd = drive->parms.read_speed_kb / drive->parms.speed_mult;
                        if (prev_spd != drive->parms.read_speed_cd) {
//                            spd = drive->parms.read_speed_cd;
                              spd = max(spd, drive->parms.read_speed_cd);
                              drive->parms.speed_tbl[idx] = drive->parms.read_speed_cd;
                              drive->parms.speed_tbl_kb[idx] = drive->parms.read_speed_kb;
                              printf("Found:  %dX (%d kB/s)\n", drive->parms.speed_tbl[idx], drive->parms.speed_tbl_kb[idx]);
                              prev_spd = drive->parms.read_speed_cd;
                              idx++;
                              if (drive->capabilities & CAP_REAL_TIME_STREAMING) get_performance(drive);
                        }
                  }
            } else {
                  speedidx=-1;
            }
      }
      combo_Speed->clear();
      idx=0;
      if (!speedidx) {
            while ((idx<speed_tbl_size) && (drive->parms.speed_tbl[idx]>0)){
                  int mlt = 176;
                  if ( drive->media.disc_type & DISC_DVD ) mlt=1385;
//                combo_Speed->insertItem(QString().sprintf("%1dX",drive->parms.speed_tbl[idx]));

                  combo_Speed->insertItem(QString().sprintf("%2dX (%d kB/s)",
                        drive->parms.speed_tbl[idx],mlt*drive->parms.speed_tbl[idx]));
                  if ((spd_kb/drive->parms.speed_mult)==drive->parms.speed_tbl[idx]) speedidx = idx;
                  idx++;
            }
      } else {
            speedidx = 0;
      }
//    combo_Speed->insertItem(tr("max"));
      printf("======\n");
      drive->parms.read_speed_kb = spd_kb;
      set_read_speed(drive);
      combo_Speed->setCurrentItem(speedidx);
      show_read_speed(drive);
}

void QPxToolWidget::set_speed(const QString& speed)
{
      char spdstr[20];
      strcpy(spdstr,speed.data());
      speedidx = combo_Speed->currentItem();

      drive->parms.read_speed_kb = drive->parms.speed_tbl_kb[speedidx];
      printf(tr("Setting speed %d kB/s [index %d]\n"),drive->parms.read_speed_kb,speedidx);
      set_read_speed(drive);
      show_read_speed(drive);
}

void QPxToolWidget::show_read_speed(drive_info* drive)
{
      get_read_speed(drive); //(drive->device,&drive->parms.read_speed_kb);
#ifdef __DEBUG
      printf("Current Read Speed  : %dkB/s (%dx CD, %dx DVD)\n",drive->parms.read_speed_kb, drive->parms.read_speed_kb/176, drive->parms.read_speed_kb/1385);
#endif
      if (drive->media.disc_type & DISC_DVD) {
            drive->parms.read_speed_dvd = drive->parms.read_speed_kb/drive->parms.speed_mult;
            text_speed->setText(QString("%1x").arg(drive->parms.read_speed_dvd));
      } else {
            drive->parms.read_speed_cd = drive->parms.read_speed_kb/176;
            text_speed->setText(QString("%1x").arg(drive->parms.read_speed_cd));
      }
}

void QPxToolWidget::silent_mode_update(drive_info* drive)
{
      int rd,wr,eject,load,access=0,state;
      int idx;
      plextor_get_silentmode(drive);
      state=drive->plextor_silent.state;
      if (!state) {
            group_silent->setChecked(false);
            return;
      }
      group_silent->setChecked(true);
      rd=drive->plextor_silent.read_speed;
      wr=drive->plextor_silent.write_speed;     
      if (drive->plextor_silent.access_speed == SILENT_ACCESS_SLOW) access=1;
      eject=drive->plextor_silent.eject_speed;
      load=drive->plextor_silent.load_speed;

      if ( drive->media.disc_type & DISC_DVD ) {
            combo_silent_cd_rd->setEnabled(false);
            combo_silent_cd_wr->setEnabled(false);
            combo_silent_dvd_rd->setEnabled(true);
            combo_silent_dvd_wr->setEnabled(true);
            idx=0;
            while ((silent_dvd_rd_tbl[idx].val!=0xFF) & (silent_dvd_rd_tbl[idx].val!=(rd & 0xFF))) idx++;
            combo_silent_dvd_rd->setCurrentItem(idx);
            idx=0;
            while ((silent_dvd_wr_tbl[idx].val!=0xFF) & (silent_dvd_wr_tbl[idx].val!=(wr & 0xFF))) idx++;
            combo_silent_dvd_wr->setCurrentItem(idx);
      }else{
            combo_silent_cd_rd->setEnabled(true);
            combo_silent_cd_wr->setEnabled(true);
            combo_silent_dvd_rd->setEnabled(false);
            combo_silent_dvd_wr->setEnabled(false);
            idx=0;
            while ((silent_cd_rd_tbl[idx].val!=0xFF) & (silent_cd_rd_tbl[idx].val!=(rd & 0xFF))) idx++;
            combo_silent_cd_rd->setCurrentItem(idx);
            idx=0;
            while ((silent_cd_wr_tbl[idx].val!=0xFF) & (silent_cd_wr_tbl[idx].val!=(wr & 0xFF))) idx++;
            combo_silent_cd_wr->setCurrentItem(idx);
      }
      combo_silent_access->setCurrentItem(access);
      slider_tray_eject->setValue(eject);
      slider_tray_load->setValue(load);
      if (state) {
            group_silent->setChecked(true);
      } else {
            group_silent->setChecked(false);
            plextor_set_silentmode_disable(drive, 0);
      }
}

void QPxToolWidget::silent_mode_test()
{
      do_load_eject();
      do_load_eject();
      get_media_info(drive);
}

void QPxToolWidget::silent_mode_save()
{
      int idx;
      if (!combo_silent_access->currentItem())
            drive->plextor_silent.access_speed = SILENT_ACCESS_FAST;
      else
            drive->plextor_silent.access_speed = SILENT_ACCESS_SLOW;
      if ( drive->media.disc_type & DISC_DVD ) {
            idx = combo_silent_dvd_rd->currentItem();
            drive->plextor_silent.read_speed = silent_dvd_rd_tbl[idx].val;
            idx = combo_silent_dvd_wr->currentItem();
            drive->plextor_silent.write_speed = silent_dvd_wr_tbl[idx].val;
            plextor_set_silentmode_disc(drive, SILENT_DVD, 1);
      } else {
            idx = combo_silent_cd_rd->currentItem();
            drive->plextor_silent.read_speed = silent_cd_rd_tbl[idx].val;
            idx = combo_silent_cd_wr->currentItem();
            drive->plextor_silent.write_speed = silent_cd_wr_tbl[idx].val;
            plextor_set_silentmode_disc(drive, SILENT_CD, 1);
      }
      drive->plextor_silent.load_speed = slider_tray_load->value();
      drive->plextor_silent.eject_speed = slider_tray_eject->value();
      plextor_set_silentmode_tray(drive, SILENT_CD, 1);
}

void QPxToolWidget::silent_mode_toggle(bool state)
{
//    if (drive->plextor_silent.state == state) return;
//    int disc_type = SILENT_CD;
      int idx;
      if (state) {
            idx = combo_silent_cd_rd->currentItem();
            drive->plextor_silent.read_speed = silent_cd_rd_tbl[idx].val;
            idx = combo_silent_cd_wr->currentItem();
            drive->plextor_silent.write_speed = silent_cd_wr_tbl[idx].val;
            if (!combo_silent_access->currentItem())
                  drive->plextor_silent.access_speed = SILENT_ACCESS_FAST;
            else
                  drive->plextor_silent.access_speed = SILENT_ACCESS_SLOW;
            plextor_set_silentmode_disc(drive, SILENT_CD, 0);
            if ( drive->media.disc_type & DISC_DVD )
            {
                  combo_silent_cd_rd->setEnabled(false);
                  combo_silent_cd_wr->setEnabled(false);
                  combo_silent_dvd_rd->setEnabled(true);
                  combo_silent_dvd_wr->setEnabled(true);
                  idx = combo_silent_dvd_rd->currentItem();
                  drive->plextor_silent.read_speed = silent_dvd_rd_tbl[idx].val;
                  idx = combo_silent_dvd_wr->currentItem();
                  drive->plextor_silent.write_speed = silent_dvd_wr_tbl[idx].val;
                  plextor_set_silentmode_disc(drive, SILENT_DVD, 0);
            } else {
                  combo_silent_cd_rd->setEnabled(true);
                  combo_silent_cd_wr->setEnabled(true);
                  combo_silent_dvd_rd->setEnabled(false);
                  combo_silent_dvd_wr->setEnabled(false);
            }
            drive->plextor_silent.load_speed = slider_tray_load->value();
            drive->plextor_silent.eject_speed = slider_tray_eject->value();
            plextor_set_silentmode_tray(drive, SILENT_CD, 0);
      } else {
            plextor_set_silentmode_disable(drive, 1);
      }
}

void QPxToolWidget::silent_mode_set_cd(const QString&)
{
      int idx = combo_silent_cd_rd->currentItem();
      drive->plextor_silent.read_speed = silent_cd_rd_tbl[idx].val;
      idx = combo_silent_cd_wr->currentItem();
      drive->plextor_silent.write_speed = silent_cd_wr_tbl[idx].val;
      plextor_set_silentmode_disc(drive, SILENT_CD, 0);
}

void QPxToolWidget::silent_mode_set_dvd(const QString&)
{
      int idx = combo_silent_dvd_rd->currentItem();
      drive->plextor_silent.read_speed = silent_dvd_rd_tbl[idx].val;
      idx = combo_silent_dvd_wr->currentItem();
      drive->plextor_silent.write_speed = silent_dvd_wr_tbl[idx].val;
      plextor_set_silentmode_disc(drive, SILENT_DVD, 0);
}

void QPxToolWidget::silent_mode_set_access_time(const QString&)
{
      int disc_type = SILENT_CD;
      if ( drive->media.disc_type & DISC_DVD ) disc_type = SILENT_DVD;
      plextor_get_silentmode(drive);
      if (!combo_silent_access->currentItem())
            drive->plextor_silent.access_speed = SILENT_ACCESS_FAST;
      else
            drive->plextor_silent.access_speed = SILENT_ACCESS_SLOW;
      plextor_set_silentmode_disc(drive, disc_type, 0);
      plextor_get_silentmode(drive);
}

void QPxToolWidget::silent_mode_set_load(int load_speed)
{
      int disc_type = SILENT_CD;
      plextor_get_silentmode(drive);
      drive->plextor_silent.load_speed = load_speed;
      if ( drive->media.disc_type & DISC_DVD ) disc_type = SILENT_DVD;
      plextor_set_silentmode_tray(drive, disc_type, 0);
      plextor_get_silentmode(drive);
}

void QPxToolWidget::silent_mode_set_eject(int eject_speed)
{
      int disc_type = SILENT_CD;
      plextor_get_silentmode(drive);
      drive->plextor_silent.eject_speed = eject_speed;
      if ( drive->media.disc_type & DISC_DVD ) disc_type = SILENT_DVD;
      plextor_set_silentmode_tray(drive, disc_type, 0);
      plextor_get_silentmode(drive);
}

void QPxToolWidget::as_off_toggled(bool state)
{
      if ((!state) || (drive->astrategy.state == AS_OFF)) return;
//    printf("** as_off_toggled %s\n", state?"ON":"OFF");
      drive->astrategy.state = AS_OFF;
      plextor_set_autostrategy(drive);
}

void QPxToolWidget::as_auto_toggled(bool state)
{
      if ((!state) || (drive->astrategy.state == AS_AUTO)) return;
//    printf("** as_auto_toggled %s\n", state?"ON":"OFF");
      drive->astrategy.state = AS_AUTO;
      plextor_set_autostrategy(drive);
}

void QPxToolWidget::as_forced_toggled(bool state)
{
      if ((!state) || (drive->astrategy.state == AS_FORCED)) return;
//    printf("** as_forced_toggled %s\n", state?"ON":"OFF");
      drive->astrategy.state = AS_FORCED;
      plextor_set_autostrategy(drive);
}

void QPxToolWidget::as_on_toggled(bool state)
{
      if ((!state) || (drive->astrategy.state == AS_ON)) return;
//    printf("** as_on_toggled %s\n", state?"ON":"OFF");
      drive->astrategy.state = AS_ON;
      plextor_set_autostrategy(drive);
}

void QPxToolWidget::asdb_edit()
{
      asdb_edit_dialog *asdb_editor;
      asdb_drive = new drive_info(drive->device);
      drivecpy(asdb_drive, drive);
      asdb_editor = new asdb_edit_dialog(this,"ASDB",1);
      asdb_editor->exec();
      delete asdb_editor;
      delete asdb_drive;
}

void QPxToolWidget::mqck()
{
      mqchk_dialog *mqchk;
      mqchk_drive = new drive_info(drive->device);
      drivecpy(mqchk_drive, drive);
      mqchk = new mqchk_dialog(this,"MQChk",1);
      mqchk->exec();
      delete mqchk;
      delete mqchk_drive;
}

void QPxToolWidget::pxerase_quick_toggled(bool state)
{
      if ((!state) || (drive->plextor.plexeraser == PLEXERASER_QUICK)) return;
      drive->plextor.plexeraser = PLEXERASER_QUICK;
      printf("\tPlexEraser Quick\n");
}

void QPxToolWidget::pxerase_full_toggled(bool state)
{
      if ((!state) || (drive->plextor.plexeraser == PLEXERASER_FULL)) return;
      drive->plextor.plexeraser = PLEXERASER_FULL;
      printf("\tPlexEraser Full\n");
}

void QPxToolWidget::do_plexeraser()
{
      QMessageBox* PxEMsg = new QMessageBox (QString("PlexEraser"),
            QString(tr("PlexEraser will <b>destruct</b> information on the inserted disc. Are you sure?")),
            QMessageBox::Warning,
            QMessageBox::Yes,
            QMessageBox::Cancel | QMessageBox::Default | QMessageBox::Escape,
            QMessageBox::NoButton,
            this);
//          3,2,0);
      int pxe = PxEMsg->exec();
      delete PxEMsg;
      if (pxe == QMessageBox::Yes) {
            printf("** Starting PlexEraser...\n");
            plextor_plexeraser(drive);
      } else {
            printf("** PlexEraser canceled\n");
      }
}

void QPxToolWidget::set_powerec_state(int state)
{
      if (drive->plextor.powerec_state == ((state == 2))) return;
      if (state == 2)
      {    // Enable PoweRec
            drive->plextor.powerec_state = 1;
            plextor_set_powerec(drive);
      } else {    // Disable PoweRec
            drive->plextor.powerec_state = 0;
            plextor_set_powerec(drive);
      }
      show_powerec_speed();
}

void QPxToolWidget::show_powerec_speed()
{
      if ( drive->media.disc_type & DISC_DVD ) {
            text_pr_spd->setText(QString().sprintf("%6.2f",drive->plextor.powerec_spd/1385.0));
      } else {
            text_pr_spd->setText(QString().sprintf("%6.2f",drive->plextor.powerec_spd/176.4));
      }
}

void QPxToolWidget::set_gigarec_state(int state)
{
//    if ((drive->plextor.gigarec != 0) == ((state == 2))) return;
      int g=0;
      char VAL[5];
      strcpy(VAL,combo_GigaRecValue->currentText().data());
      if (state == 2)
      {    // Enable GigaRec
            combo_GigaRecValue->setEnabled(true);
//          drive->plextor.gigarec = gigarecarr[combo_GigaRecValue->currentValue()];

            while ((gigarec_tbl[g].val!=0xFF) & (strncmp(gigarec_tbl[g].name,VAL,3)!=0)) g++;

//          while ((gigarec_tbl[g].val!=0xFF) & (gigarec_tbl[g].val!=(i & 0xFF))) g++;

//          drive->plextor.gigarec = gigarecarr[combo_GigaRecValue->currentItem()];
            drive->plextor.gigarec = gigarec_tbl[g].val;
            plextor_set_gigarec(drive);
      } else {    // Disable GigaRec
            combo_GigaRecValue->setEnabled(false);
            drive->plextor.gigarec = GIGAREC_10;
            plextor_set_gigarec(drive);
      }
//    plextor_get_gigarec(drive);
#ifdef __DEBUG
//    print_gigarec_value(drive);
#endif
}

void QPxToolWidget::set_gigarec_value(const QString& value)
{
      int g=0;
      char VAL[5];
      strcpy(VAL,value.data());
      while ((gigarec_tbl[g].val!=0xFF) & (strncmp(gigarec_tbl[g].name,VAL,3)!=0)) g++;
//    drive->plextor.gigarec = gigarecarr[combo_GigaRecValue->currentItem()];
//    printf("Selected value: %s (%s)\n",VAL,gigarec_tbl[g].name);
      drive->plextor.gigarec = gigarec_tbl[g].val;
      plextor_set_gigarec(drive);

#ifdef __DEBUG
//    print_gigarec_value(drive);
#endif
}

void QPxToolWidget::set_varirec_state_cd(int state)
{
      if (drive->plextor.varirec_state_cd == ((state == 2))) return;
      int v=0;
      char PWR[4];
      strcpy(PWR,combo_VariRecPower_cd->currentText().data());
//    printf("change_varirec_state()\n");
      if (state == 2)
      {    // Enable VariRec
            combo_VariRecPower_cd->setEnabled(true);
            combo_VariRecStrategy_cd->setEnabled(true);
            drive->plextor.varirec_state_cd =  1;
            while ((varirec_pwr_tbl[v].val != 0xFF) & (strncmp(varirec_pwr_tbl[v].name,PWR,2)!=0)) v++;
            drive->plextor.varirec_pwr_cd = varirec_pwr_tbl[v].val;
            plextor_set_varirec(drive, VARIREC_CD);
      } else {    // Disable VariRec
            combo_VariRecPower_cd->setEnabled(false);
            combo_VariRecStrategy_cd->setEnabled(false);
            drive->plextor.varirec_state_cd =  0;
            drive->plextor.varirec_pwr_cd = VARIREC_NULL;
            plextor_set_varirec(drive, VARIREC_CD);
      }
#ifdef __DEBUG
      print_varirec(drive, VARIREC_CD);
#endif
}

void QPxToolWidget::set_varirec_state_dvd(int state)
{
      if (drive->plextor.varirec_state_dvd == ((state == 2))) return;
      int v=0;
      char PWR[4];
      strcpy(PWR,combo_VariRecPower_dvd->currentText().data());
//    printf("change_varirec_state()\n");
      if (state == 2)
      {    // Enable VariRec
            combo_VariRecPower_dvd->setEnabled(true);
            combo_VariRecStrategy_dvd->setEnabled(true);
            drive->plextor.varirec_state_dvd =  1;
            while ((varirec_pwr_tbl[v].val != 0xFF) & (strncmp(varirec_pwr_tbl[v].name,PWR,2)!=0)) v++;
            drive->plextor.varirec_pwr_dvd = varirec_pwr_tbl[v].val;
            plextor_set_varirec(drive, VARIREC_DVD);
      } else {    // Disable VariRec
            combo_VariRecPower_dvd->setEnabled(false);
            combo_VariRecStrategy_dvd->setEnabled(false);
            drive->plextor.varirec_state_dvd =  0;
            drive->plextor.varirec_pwr_dvd = VARIREC_NULL;
            plextor_set_varirec(drive, VARIREC_DVD);
      }
#ifdef __DEBUG
      print_varirec(drive, VARIREC_DVD);
#endif
}

void QPxToolWidget::set_varirec_power_cd(const QString& power)
{
      int v=0;
      char PWR[4];
      strcpy(PWR,power.data());
      while ((varirec_pwr_tbl[v].val != 0xFF) & (strncmp(varirec_pwr_tbl[v].name,PWR,2)!=0)) v++;
//    printf("Selected power: %s (%s)\n",PWR,varirec_pwr_tbl[v].name);
      drive->plextor.varirec_state_cd =  1;
//    drive->plextor.varirec_pwr = varirecarr[v];
      drive->plextor.varirec_pwr_cd = varirec_pwr_tbl[v].val;
      plextor_set_varirec(drive, VARIREC_CD);
#ifdef __DEBUG
      print_varirec(drive, VARIREC_CD);
#endif
}

void QPxToolWidget::set_varirec_power_dvd(const QString& power)
{
      int v=0;
      char PWR[4];
      strcpy(PWR,power.data());
      while ((varirec_pwr_tbl[v].val != 0xFF) & (strncmp(varirec_pwr_tbl[v].name,PWR,2)!=0)) v++;
//    printf("Selected power: %s (%s)\n",PWR,varirec_pwr_tbl[v].name);
      drive->plextor.varirec_state_dvd =  1;
//    drive->plextor.varirec_pwr = varirecarr[v];
      drive->plextor.varirec_pwr_dvd = varirec_pwr_tbl[v].val;
      plextor_set_varirec(drive, VARIREC_DVD);
#ifdef __DEBUG
      print_varirec(drive, VARIREC_DVD);
#endif
}

void QPxToolWidget::set_varirec_strategy_cd(const QString&)
{
      drive->plextor.varirec_state_cd =  1;
      drive->plextor.varirec_str_cd = combo_VariRecStrategy_cd->currentItem();
      plextor_set_varirec(drive, VARIREC_CD);
#ifdef __DEBUG
      print_varirec(drive, VARIREC_CD);
#endif
}

void QPxToolWidget::set_varirec_strategy_dvd(const QString&)
{
      drive->plextor.varirec_state_dvd =  1;
      drive->plextor.varirec_str_dvd = combo_VariRecStrategy_dvd->currentItem();
      plextor_set_varirec(drive, VARIREC_DVD);
#ifdef __DEBUG
      print_varirec(drive, VARIREC_DVD);
#endif
}

void QPxToolWidget::set_hcdr_state(int state)
{
      if (drive->plextor.hcdr == ((state == 2))) return;
      printf("\tTurning Hide-CDR %s\n",state ? "ON" : "OFF");
      if (state == 2)
      {    // Enable Hide CD-R
            plextor_set_hidecdr(drive, 1);
      } else {    // Disable Hide CD-R
            plextor_set_hidecdr(drive, 0);
      }
//    plextor_get_hidecdr_singlesession(drive);
#ifdef __DEBUG
      print_hcdr_state(drive);
#endif
}

void QPxToolWidget::set_ss_state(int state)
{
      if (drive->plextor.sss == ((state == 2))) return;
      printf("\tTurning SingleSession %s\n",state ? "ON" : "OFF");
      if (state == 2)
      {    // Enable SingleSession
            plextor_set_singlesession(drive, 1);
      } else {    // Disable SingleSession
            plextor_set_singlesession(drive, 0);
      }
//    plextor_get_hidecdr_singlesession(drive);
#ifdef __DEBUG
      print_sss_state(drive);
#endif
}

void QPxToolWidget::set_speedread_state(int state)
{
      if (drive->plextor.spdread == ((state == 2))) return;
      printf("\tTurning SpeedRead %s\n",state?"ON":"OFF");
      if (state == 2)
      {    // Enable SpeedRead
            plextor_set_speedread(drive, 1);
            set_speed(combo_Speed->currentText());
      } else {    // Disable SpeedRead
            plextor_set_speedread(drive, 0);
            show_read_speed(drive);
      }
//    plextor_get_speedread(drive);
#ifdef __DEBUG
      print_speedread_state(drive);
#endif
}

void QPxToolWidget::set_bitset_r(int state)
{
      int book = ((state == 2));
      if (drive->book_plus_r == book) return;
      printf("\tTurning Bitset on DVD+R: %s\n",book ? "ON":"OFF");
      drive->book_plus_r = book;
      plextor_set_bitset(drive, PLEX_BITSET_R);
}

void QPxToolWidget::set_bitset_rdl(int state)
{
      int book = ((state == 2));
      if (drive->book_plus_rdl == book) return;
      printf("\tTurning Bitset on DVD+R DL: %s\n",book ? "ON":"OFF");
      drive->book_plus_rdl = book;
      plextor_set_bitset(drive, PLEX_BITSET_RDL);
}

void QPxToolWidget::set_simul_dvdplus(int state)
{
      int simul = ((state == 2));
      if (drive->plextor.testwrite_dvdplus == simul) return;
      printf("\tTurning DVD+R(W) Simulation: %s\n",simul ? "ON":"OFF");
      drive->plextor.testwrite_dvdplus = simul;
      plextor_set_testwrite_dvdplus(drive);
}

void QPxToolWidget::toggle_c1pie(bool state)
{
      int   i;
      if (state) for (i=0;i<hres;i++) Rez0[i]->show();
      else for (i=0;i<hres;i++) Rez0[i]->hide();
}

void QPxToolWidget::toggle_c2pif(bool state)
{
      int   i;
      if (state) for (i=0;i<hres;i++) Rez1[i]->show();
      else for (i=0;i<hres;i++) Rez1[i]->hide();
}

void QPxToolWidget::toggle_cu(bool state)
{
      int   i;
      if (state) for (i=0;i<hres;i++) Rez2[i]->show();
      else for (i=0;i<hres;i++) Rez2[i]->hide();
}

void QPxToolWidget::toggle_jitter(bool state)
{
      int   i;
      if (state) for (i=0;i<hres;i++) RezJ[i]->show();
      else for (i=0;i<hres;i++) RezJ[i]->hide();
}

void QPxToolWidget::toggle_beta(bool state)
{
      int   i;
      if (state) for (i=0;i<hres;i++) RezB[i]->show();
      else for (i=0;i<hres;i++) RezB[i]->hide();
}

void QPxToolWidget::toggle_fe(bool state)
{
      int   i;
      if (state) for (i=0;i<hresft;i++) RezFE[i]->show();
      else for (i=0;i<hresft;i++) RezFE[i]->hide();
}

void QPxToolWidget::toggle_te(bool state)
{
      int   i;
      if (state) for (i=0;i<hresft;i++) RezTE[i]->show();
      else for (i=0;i<hresft;i++) RezTE[i]->hide();
}

void QPxToolWidget::set_scan_commands(const QString&)
{
      int cmd_idx = combo_commands->currentItem();
      printf("set_scan_commands(%s)\n",vendor[cmd_idx]);
      drive->ven_ID = cmd_idx;
      drive->dev_ID = 1;

      if ( drive->media.disc_type & DISC_DVD ) {
            check_pie->setEnabled(true);
            check_pif->setEnabled(true);
            check_jb_dvd->setEnabled(true);
            drive->chk_features |= CHK_PI | CHK_PO | CHK_JB_DVD;
      } else if ( drive->media.disc_type & DISC_CD ) {
            check_cx->setEnabled(true);
            check_jb_cd->setEnabled(true);
            drive->chk_features |= CHK_CX | CHK_JB_CD;
      }
}

void QPxToolWidget::draw_ext_cx()
{
//    printf("draw_ext_cx()\n");
      px_ecx = new plextor_ext_cx(0, "0", FALSE, 0,
            Exx.BLER, Exx.E11, Exx.E21, Exx.E31, Exx.E12, Exx.E22, Exx.E32,
            Exx.tot, Exx.max, Exx.avg, Exx.color, drive->media.capacity/hscaleCD);
      ext_cx_active = 1;
      px_ecx->exec();
      ext_cx_active = 0;
      delete px_ecx;
}

void QPxToolWidget::run_tests()
{
      drive->parms.tests=0;
      if (check_rd_rate->isChecked())     drive->parms.tests|=TEST_RATE_RD;
      if (check_cx->isChecked())    drive->parms.tests|=TEST_CD_CX;
      if (check_jb_cd->isChecked()) drive->parms.tests|=TEST_CD_JB;
      if (check_pie->isChecked())   drive->parms.tests|=TEST_DVD_PIE;
      if (check_pif->isChecked())   drive->parms.tests|=TEST_DVD_PIF;
      if (check_jb_dvd->isChecked())      drive->parms.tests|=TEST_DVD_JB;
      if (check_ta->isChecked())    drive->parms.tests|=TEST_DVD_TA;
      if (check_fete->isChecked())  drive->parms.tests|=TEST_FETE;
//    get_media_info(drive);
      push_scan_start->setEnabled(false);
//    push_refresh->setEnabled(false);
      push_skip->setEnabled(true);
      push_abort->setEnabled(true);

      thread->set_drive(drive);
#ifdef __USE_QTHREAD
//    thread->start(QThread::NormalPriority);
      thread->start(QThread::HighPriority);
#else
      pthread_create(drive->test_thread_id, NULL, scan, (void*)thread);
#endif
}

void QPxToolWidget::updatePieC1Data(int c1t, int c1m, float c1a)
{
      c1pie_total=c1t; c1pie_max=c1m; c1pie_avg=c1a;
      text_c1pie_total->setText(QString().sprintf("%d",c1pie_total));
      text_c1pie_avg->setText(QString().sprintf("%9.2f",c1pie_avg));
      text_c1pie_max->setText(QString().sprintf("%d",c1pie_max));
}

void QPxToolWidget::updatePifC2Data(int c2t, int c2m, float c2a)
{
      c2pif_total=c2t; c2pif_max=c2m; c2pif_avg=c2a;
      text_c2pif_total->setText(QString().sprintf("%d",c2pif_total));
      text_c2pif_avg->setText(QString().sprintf("%9.2f",c2pif_avg));
      text_c2pif_max->setText(QString().sprintf("%d",c2pif_max));
}

void QPxToolWidget::updatePofCUData(int c3t, int c3m, float c3a)
{
      cu_total=c3t; cu_max=c3m; cu_avg=c3a;
      text_cu_total->setText(QString().sprintf("%d",cu_total));
      text_cu_avg->setText(QString().sprintf("%9.2f",cu_avg));
      text_cu_max->setText(QString().sprintf("%d",cu_max));
}

void QPxToolWidget::updateJBData(float jmax, float jmin, float javg, float bmax, float bmin, float bavg)
{
      j_max=jmax; j_min=jmin; j_avg=javg;
      b_max=bmax; b_min=bmin; b_avg=bavg;
      text_j_max->setText(QString().sprintf("%7.2f",j_max));
      text_j_min->setText(QString().sprintf("%7.2f",j_min));
      text_j_avg->setText(QString().sprintf("%7.2f",j_avg));
      text_b_max->setText(QString().sprintf("%5.1f",b_max));
      text_b_min->setText(QString().sprintf("%5.1f",b_min));
      text_b_avg->setText(QString().sprintf("%5.1f",b_avg));
}

void QPxToolWidget::DrawTestLimits(int idx, int idx2)
{
      int i;
      for (i=0;i<3;i++) Limits[i]->setPoints(idx+2,0,idx+2,vres);
      Limits[3]->setPoints(idx,0,idx,vres);
      Limits[4]->setPoints(idx+idx2+2,0,idx+idx2+2,vres);
}

void QPxToolWidget::DrawResRD(int idx,int spd)
{
      int   y1;
      if (idx>0)  y1=RezRD[idx]->endPoint().y();
      else        y1=vres-spd;
      RezRD[idx+1]->setPoints(idx,y1,idx+1,vres-spd);
}

void QPxToolWidget::DrawRes0(int idx,int err0)
{
      if (err0>0) err0=(int)(100*(float)log10(err0)+10);
      else err0=1;
      Rez0[idx]->setPoints(idx,vres,idx,vres-err0);  // C1 / PIE
}

void QPxToolWidget::DrawRes1(int idx, int err1)
{
      if (err1>0) err1=(int)(100*(float)log10(err1)+10);
      else err1=1;
      Rez1[idx]->setPoints(idx,vres,idx,vres-err1);  // C2 / PIF
}

void QPxToolWidget::DrawRes2(int idx, int err2)
{
      if (err2>0) err2=(int)(100*(float)log10(err2)+10);
      else err2=1;
      Rez2[idx]->setPoints(idx,vres,idx,vres-err2);  // CU
}

//void QPxToolWidget::DrawResJB(float pos,int jitter, int beta)
void QPxToolWidget::DrawResJB(int idx, int jmin, int jmax, short int bmin, short int bmax)
{
      jmin=vres-jmin/10; jmax=vres-jmax/10;
      RezJ[idx]->setPoints(idx,jmin,idx,max(jmax, jmin+1));
      bmin=vres/2-bmin*2; bmax=vres/2-bmax*2;
      RezB[idx]->setPoints(idx,bmin-1,idx,max(bmax, bmin+1));
}

void QPxToolWidget::DrawResFT(int idx, int ofe, int ote, int nfe, int nte)
{
      RezFE[idx]->setPoints(idx*6,vres-ofe*5,(idx+1)*6,vres-nfe*5);
      RezTE[idx]->setPoints(idx*6,vres-ote*5,(idx+1)*6,vres-nte*5);
}

void QPxToolWidget::DrawResTAP(int pass, int idx, int val)
{
      if (val>0) val=(int)((float)log10(val)*20.0);
      RezTAP[pass][idx]->setPoints(idx,vresta,idx,vresta-val);
}

void QPxToolWidget::DrawResTAL(int pass, int idx, int val)
{
      if (val>0) val=(int)((float)log10(val)*20.0);
      RezTAL[pass][idx]->setPoints(idx,vresta,idx,vresta-val);
}

void QPxToolWidget::TA_layer_0(bool show)
{
      TA_layer=0;
      TA_cur=TA_layer*3+TA_zone;
      if (show) TA_show(TA_cur);
      else    TA_hide(TA_cur);
}

void QPxToolWidget::TA_layer_1(bool show)
{
      TA_layer=1;
      TA_cur=TA_layer*3+TA_zone;
      if (show) TA_show(TA_cur);
      else    TA_hide(TA_cur);
}

void QPxToolWidget::TA_zone_0(bool show){
      TA_zone=0;
      TA_cur=TA_layer*3+TA_zone;
      if (show) TA_show(TA_cur);
      else    TA_hide(TA_cur);
}

void QPxToolWidget::TA_zone_1(bool show){
      TA_zone=1;
      TA_cur=TA_layer*3+TA_zone;
      if (show) TA_show(TA_cur);
      else    TA_hide(TA_cur);
}

void QPxToolWidget::TA_zone_2(bool show){
      TA_zone=2;
      TA_cur=TA_layer*3+TA_zone;
      if (show) TA_show(TA_cur);
      else    TA_hide(TA_cur);
}

void QPxToolWidget::TA_show(int TA)
{
      for (int i=0; i< hresta; i++) { RezTAP[TA][i]->show(); RezTAL[TA][i]->show(); }
}

void QPxToolWidget::TA_hide(int TA)
{
      for (int i=0; i< hresta; i++) { RezTAP[TA][i]->hide(); RezTAL[TA][i]->hide(); }
}

void QPxToolWidget::DrawGridRD()
{
      int   i;
      for (i=0;i<grids_RD;i++) GridRD[i] = new QCanvasLine( CanvasRD );
      for (i=0; i<9; i++) {
            GridRD[i]->setPen(QPen(QColor(0x80,0x80,0x80), 1, SolidLine));
            GridRD[i]->setPoints((i+1)*60,0,(i+1)*60,vres);
            GridRD[i]->show();
      }
      for (i=0;i<12;i++) {
            if ((i%2)==1)     GridRD[i+9]->setPen(QPen(QColor(0,0,0xFF), 1, SolidLine));
            else        GridRD[i+9]->setPen(QPen(QColor(0xC0,0xC0,0xC0), 1, SolidLine));
            GridRD[i+9]->setPoints(0,vres-25*(i+1),hres,vres-25*(i+1));
            GridRD[i+9]->show();
      }
}

void QPxToolWidget::DrawGrid0()
{
      int   i;
      int   h[]={4, 220, 280, 10, 100, 1000, 50, 500, 20, 30, 40, 200, 300, 400, 2, 3, 5};
      float lh[18];
      for (i=0; i<grids_CX; i++) Grid0[i] = new QCanvasLine( Canvas0 );
      for (i=0;i<17;i++) lh[i]=100*log10(h[i])+10; lh[17]=10;
      for (i=0; i<3; i++) Grid0[i]->setPen(QPen(QColor(0xFF,0,0), 1, SolidLine));
      for (i=3; i<6; i++) Grid0[i]->setPen(QPen(QColor(0,0,0), 2, SolidLine));
      for (i=6; i<17;i++) Grid0[i]->setPen(QPen(QColor(0,0,0xFF), 1, SolidLine));
      Grid0[17]->setPen(QPen(QColor(0,0,0), 2, SolidLine));
      for (i=0; i<18; i++) {
            Grid0[i]->setPoints(0,vres-(int)lh[i],hres,vres-(int)lh[i]);
            Grid0[i]->show();
      }
      for (i=0; i<9; i++) {
            Grid0[i+18]->setPen(QPen(QColor(0x80,0x80,0x80), 1, SolidLine));
            Grid0[i+18]->setPoints((i+1)*60,0,(i+1)*60,vres);
            Grid0[i+18]->show();
      }
}

void QPxToolWidget::DrawGridJB()
{
      int   i;
      for (i=0;i<grids_JB;i++) GridJB[i] = new QCanvasLine( CanvasJB );
      GridJB[0]->setPen(QPen(QColor(0,0,0), 2, SolidLine));
      GridJB[0]->setPoints(0,vres/2,hres,vres/2);
      for (i=1;i<8;i++) {
            GridJB[i+1]->setPen(QPen(QColor(0,0,0xFF), 1, SolidLine));
            GridJB[i+1]->setPoints(0,vres/2-20*i,hres,vres/2-20*i);
            GridJB[i+9]->setPen(QPen(QColor(0,0,0xFF), 1, SolidLine));
            GridJB[i+9]->setPoints(0,vres/2+20*i,hres,vres/2+20*i);
      }
      for (i=0;i<17;i++) GridJB[i]->show();
      for (i=0; i<9; i++) {
            GridJB[i+17]->setPen(QPen(QColor(0x80,0x80,0x80), 1, SolidLine));
            GridJB[i+17]->setPoints((i+1)*60,0,(i+1)*60,vres);
            GridJB[i+17]->show();
      }
}

void QPxToolWidget::DrawGridFT()
{
      int   i;
      for (i=0;i<grids_FT;i++) GridFT[i] = new QCanvasLine( CanvasFT );
      for (i=0; i<9; i++) {
            GridFT[i]->setPen(QPen(QColor(0x80,0x80,0x80), 1, SolidLine));
            GridFT[i]->setPoints((i+1)*60,0,(i+1)*60,vres);
            GridFT[i]->show();
      }
      for (i=0;i<12;i++) {
            if ((i%2)==1)     GridFT[i+9]->setPen(QPen(QColor(0,0,0xFF), 1, SolidLine));
            else        GridFT[i+9]->setPen(QPen(QColor(0xC0,0xC0,0xC0), 1, SolidLine));
            GridFT[i+9]->setPoints(0,vres-25*(i+1)+1,hres,vres-25*(i+1)+1);
            GridFT[i+9]->show();
      }
}

void QPxToolWidget::DrawGridTA()
{
      int   i,j;
      for (i=4;i<grids_TA;i++) {
            GridTAP[i] = new QCanvasLine( CanvasTAP );
            GridTAP[i]->setPen(QPen(QColor(0,0,0), 1, SolidLine));
            GridTAL[i] = new QCanvasLine( CanvasTAL );
            GridTAL[i]->setPen(QPen(QColor(0,0,0), 1, SolidLine));
      }
      j=0;
      for (i=10;i<10001;i*=10) {
            GridTAP[j] = new QCanvasLine( CanvasTAP );
            GridTAP[j]->setPen(QPen(QColor(0,0xCF,0), 1, SolidLine));
            GridTAP[j]->setPoints(0,vresta-(int)((float)log10(i)*20.0),hresta,vresta-(int)((float)log10(i)*20.0));
            GridTAP[j]->show();
            GridTAL[j] = new QCanvasLine( CanvasTAL );
            GridTAL[j]->setPen(QPen(QColor(0,0xCF,0), 1, SolidLine));
            GridTAL[j]->setPoints(0,vresta-(int)((float)log10(i)*20.0),hresta,vresta-(int)((float)log10(i)*20.0));
            GridTAL[j++]->show();
      }
      for (i=4;i<18;i++){
            GridTAP[i]->setPoints((int)(21.5454*(i-2)),0,(int)(21.5454*(i-2)),vresta);
            GridTAP[i]->show();
            GridTAL[i]->setPoints((int)(21.5454*(i-2)),0,(int)(21.5454*(i-2)),vresta);
            GridTAL[i]->show();
      }
}

void QPxToolWidget::clear_all()
{
      zero_rd();
      zero_cx();
      zero_jb();
      zero_ft();
      zero_ta();
}

void QPxToolWidget::zero_rd()
{
      int i;
      for (i=0; i< hres; i++) {
            RezRD[i]->setPoints(i,vres,i+1,vres);
      }
      text_rd_spd_start_kb->setText("0");
      text_rd_spd_start->setText("0.00");
      text_rd_spd_end_kb->setText("0");
      text_rd_spd_end->setText("0.00");
      text_rd_spd_avg_kb->setText("0");
      text_rd_spd_avg->setText("0.00");
}

void QPxToolWidget::zero_cx()
{
      int i;
      for (i=0; i< hres; i++) {
            Rez0[i]->setPoints(i,vres,i,vres);
            Rez1[i]->setPoints(i,vres,i,vres);
            Rez2[i]->setPoints(i,vres,i,vres);
            Exx.BLER[i]=0;
            Exx.E11[i]=0;
            Exx.E21[i]=0;
            Exx.E31[i]=0;
            Exx.E12[i]=0;
            Exx.E22[i]=0;
            Exx.E32[i]=0;
      }
      for (i=0; i<7; i++) {
            Exx.tot[i] = 0;
            Exx.max[i] = 0;
            Exx.avg[i] = 0.0;
      }
      text_c1pie_total->setText("0");
      text_c1pie_avg->setText("0.00");
      text_c1pie_max->setText("0");
      text_c2pif_total->setText("0");
      text_c2pif_avg->setText("0.00");
      text_c2pif_max->setText("0");
      text_cu_total->setText("0");
      text_cu_avg->setText("0.00");
      text_cu_max->setText("0");
}

void QPxToolWidget::zero_jb()
{
      int i;
      for (i=0; i< hres; i++) {
            RezJ[i]->setPoints(i,vres/2,i,vres/2);
            RezB[i]->setPoints(i,vres/2,i,vres/2);
      }
      text_j_max->setText("0.00");
      text_j_min->setText("0.00");
      text_j_avg->setText("0.00");
      text_b_max->setText("0.0");
      text_b_min->setText("0.0");
      text_b_avg->setText("0.0");
}

void QPxToolWidget::zero_ft()
{
      int i;
      for (i=0; i<hresft; i++) {
            RezFE[i]->setPoints(i*6,vres,(i+1)*6,vres);
            RezTE[i]->setPoints(i*6,vres,(i+1)*6,vres);
      }
      text_f_max->setText("0");
//    text_f_min->setText("0");
      text_f_avg->setText("0.0");
      text_t_max->setText("0");
//    text_t_min->setText("0");
      text_t_avg->setText("0.0");
}

void QPxToolWidget::zero_ta()
{
      int i,j;
      for (i=0; i<6; i++) {
            for (j=0; j< hresta; j++) {
                  RezTAP[i][j]->setPoints(j,vresta-1,j,vresta-1);
                  RezTAL[i][j]->setPoints(j,vresta-1,j,vresta-1);
            }
      }
}

void QPxToolWidget::block_done_rd(block_data* block)
{
      if(!block->idx) zero_rd();
      if((block->idx > (hres-1)) | (block->idx < 0)) return;
      DrawResRD(block->idx, block->speed_h);
      progress_test->setProgress(block->block,block->blocks);
//    printf("block.pit = %d;  block.idx = %d\n",block->pit,block->idx);
      if (!block->pit) {
            if (block->idx == 1) {
//                printf("IDX=0; block->speed_x = %5.2f; block->speed_kb = %d\n",block->speed_x,(int)block->speed_kb);
                  text_rd_spd_start->setText(QString().sprintf("%6.2f",block->speed_x));
                  text_rd_spd_start_kb->setText(QString("%1").arg((int)block->speed_kb));
            }
            text_rd_spd_end->setText(QString().sprintf("%6.2f",block->speed_x));
            text_rd_spd_end_kb->setText(QString("%1").arg((int)block->speed_kb));
      } else {
            text_rd_spd_avg->setText(QString().sprintf("%6.2f",block->speed_x));
            text_rd_spd_avg_kb->setText(QString("%1").arg((int)block->speed_kb));
      }
}

void QPxToolWidget::block_done_c1pie(block_data* block)
{
      if(!block->idx) zero_cx();
      if((block->idx > (hres-1)) | (block->idx < 0)) return;
      DrawRes0(block->idx,block->err_cur);
      updatePieC1Data(block->err_total,block->err_max,block->err_avg);
      progress_test->setProgress(block->block,block->blocks);
}

void QPxToolWidget::block_done_c2pif(block_data* block)
{
      if((block->idx > (hres-1)) | (block->idx < 0)) return;
      DrawRes1(block->idx,block->err_cur);
      updatePifC2Data(block->err_total,block->err_max,block->err_avg);
      progress_test->setProgress(block->block,block->blocks);
}

void QPxToolWidget::block_done_cupof(block_data* block)
{
      if((block->idx > (hres-1)) | (block->idx < 0)) return;
      DrawRes2(block->idx,block->err_cur);
      updatePofCUData(block->err_total,block->err_max,block->err_avg);
}

void QPxToolWidget::block_done_jb(block_data* block)
{
      if(!block->idx) zero_jb();
      if((block->idx > (hres-1)) | (block->idx < 0)) return;

      if (!block->pit) {
            DrawResJB(block->idx,(int)block->jmax,(int)block->jmin,(int)block->bmax,(int)block->bmin);
            progress_test->setProgress(block->block,block->blocks);
      } else
            updateJBData(block->jmax,block->jmin,0,block->bmax,block->bmin,0);
}

void QPxToolWidget::block_done_fete(block_data* block)
{
      if(!block->idx) zero_ft();
      if((block->idx > (hres-1)) | (block->idx < 0)) return;

      DrawResFT(block->block, block->ofe, block->ote, block->nfe, block->nte);
      text_f_max->setText(QString().sprintf("%d",(int)block->bmax));
      text_f_avg->setText(QString().sprintf("%4.1f",block->bmin));
      text_t_max->setText(QString().sprintf("%d",(int)block->jmax));
      text_t_avg->setText(QString().sprintf("%4.1f",block->jmin));
}

void QPxToolWidget::block_done_ta(block_data* block)
{
      DrawResTAP(block->block, block->idx, block->pit);
      DrawResTAL(block->block, block->idx, block->land);
}

void QPxToolWidget::block_done_cx_ext(block_data* block, int event_id)
{
      switch (event_id) {
            case event_block_done_BLER:
                  Exx.BLER [block->idx] = block->err_cur;
                  Exx.tot[0] = block->err_total; Exx.max[0] = block->err_max; Exx.avg[0] = block->err_avg;
                  break;
            case event_block_done_E11:
                  Exx.E11 [block->idx] = block->err_cur;
                  Exx.tot[1] = block->err_total; Exx.max[1] = block->err_max; Exx.avg[1] = block->err_avg;
                  break;
            case event_block_done_E21:
                  Exx.E21 [block->idx] = block->err_cur;
                  Exx.tot[2] = block->err_total; Exx.max[2] = block->err_max; Exx.avg[2] = block->err_avg;
                  break;
            case event_block_done_E31:
                  Exx.E31 [block->idx] = block->err_cur;
                  Exx.tot[3] = block->err_total; Exx.max[3] = block->err_max; Exx.avg[3] = block->err_avg;
                  break;
            case event_block_done_E12:
                  Exx.E12 [block->idx] = block->err_cur;
                  Exx.tot[4] = block->err_total; Exx.max[4] = block->err_max; Exx.avg[4] = block->err_avg;
                  break;
            case event_block_done_E22:
                  Exx.E22 [block->idx] = block->err_cur;
                  Exx.tot[5] = block->err_total; Exx.max[5] = block->err_max; Exx.avg[5] = block->err_avg;
                  break;
            case event_block_done_E32:
                  Exx.E32 [block->idx] = block->err_cur;
                  Exx.tot[6] = block->err_total; Exx.max[6] = block->err_max; Exx.avg[6] = block->err_avg;
                  break;
      }
      if (ext_cx_active) px_ecx->redraw();
}

void QPxToolWidget::show_lba(block_data* block)
{
      text_lba->setText(QString("<tt>%1</tt>").arg(block->lba));
}

void QPxToolWidget::showtime(block_data* block)
{
      int min,sec;
//    block->time/=1000000;
      min=(block->time)/60;
      sec=block->time-min*60;
//    printf("\n** Test time: %lseconds\n",block->time);
      switch (block->test) {
            case TEST_RATE_RD:
                  text_time_rd->setText(QString().sprintf("%d : %02d",min,sec));
                  break;
            case TEST_CD_CX:
            case TEST_DVD_PIE:
            case TEST_DVD_PIF:
            case TEST_DVD_POE:
            case TEST_DVD_POF:
                  text_time_cx->setText(QString().sprintf("%d : %02d",min,sec));
                  break;
            case TEST_CD_JB:
            case TEST_DVD_JB:
                  text_time_jb->setText(QString().sprintf("%d : %02d",min,sec));
                  break;
            case TEST_FETE:
                  text_time_fete->setText(QString().sprintf("%d : %02d",min,sec));
                  break;
            default: 
                  printf("/ Unknown TEST ID: %08X/\n",block->test);
      }
}

void QPxToolWidget::skip_current_test() { thread->skip_test(); }
void QPxToolWidget::abort_tests() { thread->abort_test(); }
void QPxToolWidget::clear_debug() { textDebug->clear(); }
void QPxToolWidget::reset_progress() { status_current_test->setText("Idle..."); progress_test->reset(); }

void QPxToolWidget::fill_res_rd_grid()
{
      int i,j, color;
// V lines
      for (i=0; i<9; i++)
            for (j=0; j<vres; j++)
                  result_rd->setPixel((i+1)*60,j,0x00808080);
// H lines
      for (i=0;i<12;i++) {
            if ((i%2)==1)color = 0x000000FF; else color = 0x00C0C0C0;
            for (j=0; j<hres; j++)
                  result_rd->setPixel(j,vres-25*(i+1),color);
      }
// Vertical limit line:
      for (j=0; j<vres; j++) {result_rd->setPixel(res_cap,j,0x00000000);result_rd->setPixel(res_cap+1,j,0x00000000);}
}

void QPxToolWidget::fill_res_cx_grid()
{
      int   i,j;
// V lines
      for (i=0; i<9; i++)
            for (j=0; j<vres; j++)
                  result_cx->setPixel((i+1)*60,j,0x00808080);
// H lines
      int   h[18]={4, 220, 280, 10, 100, 1000, 50, 500,
            20, 30, 40, 200, 300, 400, 1, 2,
            3, 5};
      int   color[18]={0x00FF0000,0x00FF0000,0x00FF0000,0, 0,0,0x000000FF,0x000000FF,
            0x000000FF,0x000000FF,0x000000FF,0x000000FF, 0x000000FF,0x000000FF,0,0x000000FF,
            0x000000FF,0x000000FF};
      float lh[18];
      for (i=0;i<18;i++) lh[i]=100*log10(h[i])+10;
      for (i=0; i<18; i++) {
            for (j=0; j<hres; j++) result_cx->setPixel(j,vres-(int)lh[i],color[i]);
            if (!color[i]) for (j=0; j<hres; j++) result_cx->setPixel(j,vres-(int)lh[i]+1,color[i]);
      }
// Vertical limit line:
      for (j=0; j<vres; j++) {result_cx->setPixel(res_cap,j,0x00000000);result_cx->setPixel(res_cap+1,j,0x00000000);}
}

void QPxToolWidget::fill_res_cx_ext_grid(int ext)
{
      int   i,j;
      int   vres2 = vres/2;
// V lines
      for (i=0; i<9; i++)
            for (j=0; j<(vres/2); j++)
                  result_cx->setPixel((i+1)*60,j,0x00808080);
// H lines
      int   h[17]={220, 10, 100, 1000, 50, 500, 20, 30, 40, 200, 300, 400, 1, 2, 3, 4, 5};
      int   color[17]={0x00FF0000, 0, 0, 0, 0x000000FF, 0x000000FF, 0x000000FF, 0x000000FF, 0x000000FF, 0x000000FF,
                        0x000000FF, 0x000000FF, 0, 0x000000FF, 0x000000FF, 0x000000FF, 0x000000FF};
      float lh[17];
      for (i=0;i<17;i++) lh[i]=50*log10(h[i])+5;
      if ((ext != CD_EXT_BLER)) lh[0]=1;
      for (i=0; i<17; i++) {
            for (j=0; j<hres; j++) result_cx->setPixel(j,vres2-(int)lh[i],color[i]);
            if (!color[i]) for (j=0; j<hres; j++) result_cx->setPixel(j,vres2-(int)lh[i]+1,color[i]);
      }
// Vertical limit line:
      for (j=0; j<(vres2); j++) {result_cx->setPixel(res_cap,j,0x00000000);result_cx->setPixel(res_cap+1,j,0x00000000);}
}

void QPxToolWidget::fill_res_jb_grid()
{
      int   i,j;
// V lines
      for (i=0; i<9; i++)
            for (j=0; j<vres; j++)
                  result_jb->setPixel((i+1)*60,j,0x00808080);
// H lines
      for (j=1; j<8; j++)
            for (i=0; i<hres; i++){
                  result_jb->setPixel(i,vres/2-20*j,0x000000FF);
                  result_jb->setPixel(i,vres/2+20*j,0x000000FF);
      }
      for (i=0; i<hres; i++) {
            result_jb->setPixel(i,vres/2,0x00000000);
            result_jb->setPixel(i,vres/2-1,0x00000000);
      }
// Vertical limit line:
      for (j=0; j<vres; j++) {result_jb->setPixel(res_cap,j,0x00000000);result_jb->setPixel(res_cap+1,j,0x00000000);}
}

void QPxToolWidget::fill_res_ft_grid()
{
      int i,j, color;
// V lines
      for (i=0; i<9; i++)
            for (j=0; j<vres; j++)
                  result_ft->setPixel((i+1)*60,j,0x00808080);
// H lines
      for (i=0;i<12;i++) {
            if ((i%2)==1)color = 0x000000FF; else color = 0x00C0C0C0;
            for (j=0; j<hres; j++)
                  result_ft->setPixel(j,vres-25*(i+1),color);
      }
// Vertical limit line:
      for (j=0; j<vres; j++) {result_ft->setPixel(res_cap,j,0x00000000);result_ft->setPixel(res_cap+1,j,0x00000000);}
}

void QPxToolWidget::fill_res_ta_grid(int layer, int zone)
{

      int   i,j,h;
// H grid lines
      for (i=10;i<10001; i*=10) {
            h=(int)((float)log10(i)*20.0);
            for (j=0; j<hresta; j++) {
                  result_ta->setPixel(hresta*layer+j,vresta*(zone*2+1)-h,0x0000CF00);
                  result_ta->setPixel(hresta*layer+j,vresta*(zone*2+2)-h,0x0000CF00);
            }
      }
      for (j=0; j<hresta; j++) {
            result_ta->setPixel(hresta*layer+j,vresta*(zone*2),0x00000000);
            result_ta->setPixel(hresta*layer+j,vresta*(zone*2+1),0x00C0C0C0);
            result_ta->setPixel(hresta*layer+j,vresta*(zone*2+1)-1,0x00C0C0C0);
            result_ta->setPixel(hresta*layer+j,vresta*(zone*2+2)-1,0x00000000);
      }
      for (i=2;i<16;i++){
            h = (int)(21.5454*i);
            for (j=0; j<vresta; j++) {
                  result_ta->setPixel(hresta*layer+h,vresta*(zone*2+1)-j-1,0x00000000);
                  result_ta->setPixel(hresta*layer+h,vresta*(zone*2+2)-j-1,0x00000000);
            }
      }
}

void QPxToolWidget::fill_res_rd()
{
      int i,j,y1,y2,c;
      for (i=0; i<hres; i++) for (j=0; j<vres; j++) result_rd->setPixel(i,j,0x00FFFFFF);
      for (i=0; i<res_cap; i++) {
            y1 = RezRD[i]->startPoint().y(); if (y1>(vres-1)) y1=vres-1; if (y1<0) y1=0;
            y2 = RezRD[i]->endPoint().y(); if (y2>(vres-1)) y2=vres-1; if (y2<0) y2=0;
            c=(min(y1,y2)+max(y1,y2))/2;
            for (j=min(y1,c) ; j<max(y1,c) ; j++)
                  result_rd->setPixel(i,j,0x00FF0000);
            for (j=min(c,y2) ; j<=max(c,y2) ; j++)
                  result_rd->setPixel(i+1,j,0x00FF0000);
      }
      fill_res_rd_grid();
}

void QPxToolWidget::fill_res_cx()
{
      int i,j,h;
      for (i=0; i<hres; i++) for (j=0; j<vres; j++) result_cx->setPixel(i,j,0x00FFFFFF);
      for (i=0; i<res_cap; i++) {
            h = vres - Rez0[i]->endPoint().y();
            if (h>=vres) h=vres-1; if (h<1) h=1;
            for (j=vres-1 ; j>(vres-h) ; j--) result_cx->setPixel(i,j,0x0000C000);

            h = vres - Rez1[i]->endPoint().y();
            if (h>=vres) h=vres-1; if (h<1) h=1;
            for (j=vres-1 ; j>(vres-h) ; j--) result_cx->setPixel(i,j,0x00FF0000);

            h = vres - Rez2[i]->endPoint().y();
            if (h>=vres) h=vres-1; if (h<1) h=1;
            for (j=vres-1 ; j>(vres-h) ; j--) result_cx->setPixel(i,j,0x00000000);
      }
      fill_res_cx_grid();
}

void QPxToolWidget::fill_res_cx_ext(int ext){
      int *arr = NULL;
      int vres2 = vres/2;
      int color = 0;
      switch (ext) {
            case CD_EXT_BLER: arr=Exx.BLER; color = Exx.color[0]; break;
            case CD_EXT_E11:  arr=Exx.E11;  color = Exx.color[1]; break;
            case CD_EXT_E21:  arr=Exx.E21;  color = Exx.color[2]; break;
            case CD_EXT_E31:  arr=Exx.E31;  color = Exx.color[3]; break;
            case CD_EXT_E12:  arr=Exx.E12;  color = Exx.color[4]; break;
            case CD_EXT_E22:  arr=Exx.E22;  color = Exx.color[5]; break;
            case CD_EXT_E32:  arr=Exx.E32;  color = Exx.color[6]; break;
      }
      int i,j,h;
      for (i=0; i<hres; i++) for (j=0; j<vres2; j++) result_cx->setPixel(i,j,0x00FFFFFF);
      for (i=0; i<res_cap; i++) {
            if (arr[i]>0) h=(int)(50*(float)log10(arr[i])+5); else h=1;
            if (h>=vres2) h=(vres2)-1; if (h<1) h=1;
            for (j=vres2-1 ; j>(vres2-h) ; j--) result_cx->setPixel(i,j,color);
      }
      fill_res_cx_ext_grid(ext);
}

void QPxToolWidget::fill_res_jb()
{
      int i,j,j1,j2,b1,b2;
      for (i=0; i<hres; i++) for (j=0; j<vres; j++) result_jb->setPixel(i,j,0x00FFFFFF);
      for (i=0; i<res_cap; i++) {
            b1= RezB[i]->startPoint().y();      b1 = max(0,b1);   b1 = min(b1,vres-1);
            b2= RezB[i]->endPoint().y();  b2 = max(0,b2);   b2 = min(b2,vres-1);
            for(j=min(b1,b2); j<max(b1,b2); j++)
                  result_jb->setPixel(i,j,0x00FF0000);
            j1= RezJ[i]->startPoint().y();      j1 = max(0,j1);   j1 = min(j1,vres-1);
            j2= RezJ[i]->endPoint().y();  j2 = max(0,j2);   j2 = min(j2,vres-1);
            for(j=min(j1,j2); j<max(j1,j2); j++)
                  result_jb->setPixel(i,j,0x00008000);
      }
      fill_res_jb_grid();
}

void QPxToolWidget::fill_res_ft()
{
      int i,ii,j,f1,f2,t1,t2;
      int fl,fh,fc;
      int tl,th,tc;
      int last_blk;
      float df, dt;
      for (i=0; i<hres; i++) for (j=0; j<vres; j++) result_ft->setPixel(i,j,0x00FFFFFF);
      fill_res_ft_grid();
      last_blk = res_cap/6;
      for (i=0; i<last_blk; i++) {
            f1= RezFE[i]->startPoint().y();     f1 = max(0,f1); f1 = min(f1,vres-1);
            f2= RezFE[i]->endPoint().y(); f2 = max(0,f2); f2 = min(f2,vres-1);
            t1= RezTE[i]->startPoint().y();     t1 = max(0,t1); t1 = min(t1,vres-1);
            t2= RezTE[i]->endPoint().y(); t2 = max(0,t2); t2 = min(t2,vres-1);
            df = (f2-f1)/6.0;
            dt = (t2-t1)/6.0;
            for(ii=1; ii<=6; ii++) {
                  fl = min (f1+(int)(df*(ii-1)), f1+(int)(df*ii));
                  fh = max (f1+(int)(df*(ii-1)), f1+(int)(df*ii));
                  fc=(min(fl,fh)+max(fl,fh))/2;
                  for (j=min(fl,fc); j<max(fl,fc); j++) result_ft->setPixel(i*6+ii,j,0x00FF0000);
                  for (j=min(fc,fh); j<=max(fc,fh); j++) result_ft->setPixel(i*6+ii,j,0x00FF0000);

                  tl = min (t1+(int)(dt*(ii-1)), t1+(int)(dt*ii));
                  th = max (t1+(int)(dt*(ii-1)), t1+(int)(dt*ii));
                  tc=(min(tl,th)+max(tl,th))/2;
                  for (j=min(tl,tc); j<max(tl,tc); j++) result_ft->setPixel(i*6+ii,j,0x00008000);
                  for (j=min(tc,th); j<=max(tc,th); j++) result_ft->setPixel(i*6+ii,j,0x00008000);
            }
      }
}

void QPxToolWidget::fill_res_ta()
{
      int i,j,layer,zone,h;
      for (i=0; i<hresta*drive->media.layers; i++) for (j=0; j<vresta*6; j++) result_ta->setPixel(i,j,0x00FFFFFF);
      for (layer=0; layer<drive->media.layers; layer++)
            for (zone=0; zone<3; zone++) {
                  fill_res_ta_grid(layer, zone);
                  for (i=0; i<hresta; i++) {
                        h = vresta - RezTAP[layer*3+zone][i]->endPoint().y(); //vresta-1
                        if (h<0) h=0; if (h>(vresta-1)) h=vresta-1;
                        for (j=0; j<h; j++) result_ta->setPixel(hresta*layer+i,vresta*(zone*2+1)-j-1,0x000000FF);
                        h = vresta - RezTAL[layer*3+zone][i]->endPoint().y();
                        if (h<0) h=0; if (h>(vresta-1)) h=vresta-1;
                        for (j=0; j<h; j++) result_ta->setPixel(hresta*layer+i,vresta*(zone*2+2)-j-1,0x00FF0000);
                  }
            }
}

void QPxToolWidget::file_save_rd()
{
      QString res_name;
      res_name = file_dialog.getSaveFileName("tr_rate.png","*.png");
      if (!res_name.data()) return;
      printf("File: %s...",res_name.data());
      if (drive->media.disc_type & DISC_CD) res_cap = drive->media.capacity/hscaleCD+1;
            else res_cap = (drive->media.capacity/hscaleDVD)/drive->media.layers+1;
      if (res_cap > (hres-2)) res_cap = hres-2;
      result_rd = new QImage (hres,vres,32);
      fill_res_rd();
      result_rd->save(res_name,"PNG");
      delete result_rd;
      printf("saved\n");
}

void QPxToolWidget::file_save_cx()
{
      QString res_name;
      res_name = file_dialog.getSaveFileName("cx.png","*.png");
      if (!res_name.data()) return;
      printf("File: %s...",res_name.data());
      if (drive->media.disc_type & DISC_CD) res_cap = drive->media.capacity/hscaleCD+1;
            else res_cap = (drive->media.capacity/hscaleDVD)/drive->media.layers+1;
      if (res_cap > (hres-2)) res_cap = hres-2;
      result_cx = new QImage (hres,vres,32);
      fill_res_cx();
      result_cx->save(res_name,"PNG");
      delete result_cx;
      printf("saved\n");
}

void QPxToolWidget::file_save_jb()
{
      QString res_name;
      res_name = file_dialog.getSaveFileName("jb.png","*.png");
      if (!res_name.data()) return;
      printf("File: %s...",res_name.data());
      if (drive->media.disc_type & DISC_CD) res_cap = drive->media.capacity/hscaleCD+1;
            else res_cap = (drive->media.capacity/hscaleDVD)/drive->media.layers+1;
      if (res_cap > (hres-2)) res_cap = hres-2;
      result_jb = new QImage (hres,vres,32);
      fill_res_jb();
      result_jb->save(res_name,"PNG");
      delete result_jb;
      printf("saved\n");
}

void QPxToolWidget::file_save_ft()
{
      QString res_name;
      res_name = file_dialog.getSaveFileName("ft.png","*.png");
      if (!res_name.data()) return;
      printf("File: %s...",res_name.data());
      if (drive->media.disc_type & DISC_CD) res_cap = (drive->media.capacity+drive->media.capacity_free)/hscaleCD+1;
            else res_cap = ((drive->media.capacity+drive->media.capacity_free)/hscaleDVD)/drive->media.layers+1;
      if (res_cap > (hres-2)) res_cap = hres-2;
      result_ft = new QImage (hres,vres,32);
      fill_res_ft();
      result_ft->save(res_name,"PNG");
      delete result_ft;
      printf("saved\n");
}

void QPxToolWidget::file_save_ta()
{
      if (drive->media.disc_type & DISC_DVD) {
            QString res_name;
            res_name = file_dialog.getSaveFileName("ta.png","*.png");
            if (!res_name.data()) return;
            printf("File: %s...",res_name.data());
            result_ta = new QImage (hresta*drive->media.layers,vresta*6,32);
            fill_res_ta();
            result_ta->save(res_name,"PNG");
            delete result_ta;
            printf("saved\n");
      } else printf("No DVD -> no TA\n");
}

void QPxToolWidget::generate_result_html(QString res_name, int tests)
{
      FILE  *html;
      printf("Saving html to: '%s'\n",res_name.data());
      html = fopen(res_name.data(), "wt");
      fprintf(html,"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
      fprintf(html,"<html>\n<head>\n\t<title>QPxTool scan results :: %s</title>\n</head>\n",
            line_disc_info->text().data());
      fprintf(html,"\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n");
      fprintf(html,"<body>\n\t<div align=\"center\">\n");
      fprintf(html,"\t<IMG border=\"0\" src=\"logo.png\" alt=\"QPxTool logo\" height=\"50\" width=\"600\"><br>\n");
      fprintf(html,"\t<font size=\"+1\"><b>\n");
      fprintf(html,"\t<table border=\"0\" cellspacing=\"0\" width=\"600\">");
      fprintf(html,"\t<tbody>\n");
      fprintf(html,"\t\t<tr>\n\t\t\t<td align=\"right\">Disc label:</td>\n\t\t\t<td align=\"left\">%s</td>\n\t\t</tr>\n",
            line_disc_info->text().data());
      fprintf(html,"\t\t<tr>\n");
      fprintf(html,"\t\t\t<td align=\"right\" width=\"30%\">Scaned on:</td>\n");
      fprintf(html,"\t\t\t<td align=\"left\" width=\"70%\">%s %s %s @%s</td>\n",
            text_vendor->text().data(),
            text_model->text().data(),
            text_fw->text().data(),
            combo_scan_speed->currentText().data());
      fprintf(html,"\t\t</tr>");
      fprintf(html,"\t</tbody>\n");
      fprintf(html,"\t</table>\n");
      fprintf(html,"\t</b></font>\n");
      fprintf(html,"\t<table border=\"0\" cellspacing=\"0\" width=\"600\">\n");
      fprintf(html,"\t<tbody>\n");
      fprintf(html,"\t\t<tr><td align=\"right\" width=\"30%\"></td><td align=\"left\">TLA# %s, S/N: %s</td></tr>\n",
            text_tla->text().data(),
            text_serial->text().data());
      if (drive->media.disc_type & DISC_CD) {
            fprintf(html,"\t\t<tr><td align=\"right\">Media:</td><td align=\"left\">%s</td></tr>\n",
                  text_media_type->text().data());
            fprintf(html,"\t\t<tr><td align=\"right\">Manufacturer:</td><td align=\"left\">%s</td></tr>\n",
                  text_MID->text().data());
      } else {
            fprintf(html,"\t\t<tr><td align=\"right\">Media/book:</td><td align=\"left\">%s / %s</td></tr>\n",
                  text_media_type->text().data(),
                  text_book_type->text().data());
            fprintf(html,"\t\t<tr><td align=\"right\">MID:</td><td align=\"left\">%s</td></tr>\n",
                  text_MID->text().data());
            fprintf(html,"\t\t<tr><td align=\"right\">written on:</td><td align=\"left\">%s</td></tr>\n",
                  text_writer->text().data());
      }
      fprintf(html,"\t\t<tr><td align=\"right\">capacity:</td><td align=\"left\">%s</td></tr>\n",
            text_sz->text().data());
      fprintf(html,"\t\t<tr><td align=\"right\">comments:</td><td align=\"left\">%s</td></tr>\n",
            line_comments->text().data());
      fprintf(html,"\t</tbody>\n");
      fprintf(html,"\t</table><br>\n");
//  **************  Transfer Rate  **************
      if (tests & CHK_RD) {
            fprintf(html,"\t<br><b>Transfer rate</b><br>\n");
            fprintf(html,"\t<br><IMG border=\"1\" src=\"%s\" alt=\"Transfer Rate\" height=\"320\" width=\"600\"><br>\n",
                  png_name_rd.data());
            fprintf(html,"\t<table border=\"0\" cellspacing=\"0\" width=\"300\">\n");
            fprintf(html,"\t\t<tbody align=\"right\">\n");
            fprintf(html,"\t\t<tr><td>Start</td><td>%skB/s</td><td>%sx</td></tr>\n",
                  text_rd_spd_start_kb->text().data(),
                  text_rd_spd_start->text().data());
            fprintf(html,"\t\t<tr><td>End</td><td>%skB/s</td><td>%sx</td></tr>\n",
                  text_rd_spd_end_kb->text().data(),
                  text_rd_spd_end->text().data());
            fprintf(html,"\t\t<tr><td>Avg</td><td>%skB/s</td><td>%sx</td></tr>\n",
                  text_rd_spd_avg_kb->text().data(),
                  text_rd_spd_avg->text().data());
            fprintf(html,"\t</tbody>\n\t</table>\n");
      }
//  **************  Pi/Cx  **************

      if ((tests & CHK_CX) && (drive->media.disc_type & DISC_CD)) {
            fprintf(html,"\t<br><b>C1/C2/CU scan</b><br>\n");
            fprintf(html,"\t<br><IMG border=\"1\" src=\"%s\" alt=\"C1/C2/CU\" height=\"320\" width=\"600\"><br>\n",
                  png_name_cx.data());
            fprintf(html,"\t<table border=\"0\" cellspacing=\"0\" width=\"300\">\n");
            fprintf(html,"\t<tbody align=\"right\">\n");
            fprintf(html,"\t\t<tr><td></td> <td><font color=#008000>C1</font></td> <td><font color=#FF0000>C2</font></td> <td>CU</td></tr>\n");
            fprintf(html,"\t\t<tr><td>Total</td><td>%s</td><td>%s</td><td>%s</td></tr>\n",
                  text_c1pie_total->text().data(),
                  text_c2pif_total->text().data(),
                  text_cu_total->text().data());
            fprintf(html,"\t\t<tr><td>Max</td><td>%s</td><td>%s</td><td>%s</td></tr>\n",
                  text_c1pie_max->text().data(),
                  text_c2pif_max->text().data(),
                  text_cu_max->text().data());
            fprintf(html,"\t\t<tr><td>Avg</td><td>%s</td><td>%s</td><td>%s</td></tr>\n",
                  text_c1pie_avg->text().data(),
                  text_c2pif_avg->text().data(),
                  text_cu_avg->text().data());
            fprintf(html,"\t</tbody>\n\t</table>\n");
            if ((drive->ven_ID == WR_PLEXTOR )) {
                  fprintf(html,"\t<br><b>Extended CD scan results</b><br>\n");

                  fprintf(html,"\t<br><table border=\"0\" cellspacing=\"0\" width=\"600\">\n");
                  fprintf(html,"\t<tbody align=\"right\">\n");
                  fprintf(html,"\t\t<tr><td></td> <td><font color=#%06X>BLER</font></td>", Exx.color[0]);
                  fprintf(html,"<td><font color=#%06X>E11</font></td> <td><font color=#%06X>E21</font></td>",
                        Exx.color[1], Exx.color[2]);
                  fprintf(html,"<td><font color=#%06X>E31</font></td> <td><font color=#%06X>E12</font></td>",
                        Exx.color[3], Exx.color[4]);
                  fprintf(html,"<td><font color=#%06X>E22</font></td> <td><font color=#%06X>E32</font></td>",
                        Exx.color[5], Exx.color[6]);

                  fprintf(html,"\t\t<tr><td>Total</td><td>%d</td><td>%d</td><td>%d</td><td>%d</td>",
                        Exx.tot[0], Exx.tot[1], Exx.tot[2], Exx.tot[3]);
                  fprintf(html,"<td>%d</td><td>%d</td><td>%d</td></tr>\n",
                        Exx.tot[4], Exx.tot[5], Exx.tot[6]);

                  fprintf(html,"\t\t<tr><td>Max</td><td>%d</td><td>%d</td><td>%d</td><td>%d</td>",
                        Exx.max[0], Exx.max[1], Exx.max[2], Exx.max[3]);
                  fprintf(html,"<td>%d</td><td>%d</td><td>%d</td></tr>\n",
                        Exx.max[4], Exx.max[5], Exx.max[6]);

                  fprintf(html,"\t\t<tr><td>Avg</td><td>%6.2f</td><td>%6.2f</td><td>%6.2f</td><td>%6.2f</td>",
                        Exx.avg[0], Exx.avg[1], Exx.avg[2], Exx.avg[3]);
                  fprintf(html,"<td>%6.2f</td><td>%6.2f</td><td>%6.2f</td></tr>\n",
                        Exx.avg[4], Exx.avg[5], Exx.avg[6]);

                  fprintf(html,"\t</tbody>\n\t</table>\n");


                  fprintf(html,"\t<br>BLER<br>\n");
                  fprintf(html,"\t<IMG border=\"1\" src=\"%s\" alt=\"BLER\" height=\"160\" width=\"600\"><br>\n",
                        png_name_BLER.data());
                  fprintf(html,"\t<br>E11<br>\n");
                  fprintf(html,"\t<IMG border=\"1\" src=\"%s\" alt=\"E11\" height=\"160\" width=\"600\"><br>\n",
                        png_name_E11.data());
                  fprintf(html,"\t<br>E21<br>\n");
                  fprintf(html,"\t<IMG border=\"1\" src=\"%s\" alt=\"E21\" height=\"160\" width=\"600\"><br>\n",
                        png_name_E21.data());
                  fprintf(html,"\t<br>E31<br>\n");
                  fprintf(html,"\t<IMG border=\"1\" src=\"%s\" alt=\"E31\" height=\"160\" width=\"600\"><br>\n",
                        png_name_E31.data());
                  fprintf(html,"\t<br>E12<br>\n");
                  fprintf(html,"\t<IMG border=\"1\" src=\"%s\" alt=\"E12\" height=\"160\" width=\"600\"><br>\n",
                        png_name_E12.data());
                  fprintf(html,"\t<br>E22<br>\n");
                  fprintf(html,"\t<IMG border=\"1\" src=\"%s\" alt=\"E22\" height=\"160\" width=\"600\"><br>\n",
                        png_name_E22.data());
                  fprintf(html,"\t<br>E32<br>\n");
                  fprintf(html,"\t<IMG border=\"1\" src=\"%s\" alt=\"E32\" height=\"160\" width=\"600\"><br>\n",
                        png_name_E32.data());
            }
      }
      if (tests & (CHK_PI | CHK_PO) && (drive->media.disc_type & DISC_DVD)) {
            fprintf(html,"\t<br><b>PIE/PIF scan</b><br>\n");
            fprintf(html,"\t<br><IMG border=\"1\" src=\"%s\" alt=\"PIE/PIF\" height=\"320\" width=\"600\"><br>\n",
                  png_name_cx.data());
            fprintf(html,"\t<table border=\"0\" cellspacing=\"0\" width=\"300\">\n");
            fprintf(html,"\t<tbody align=\"right\">\n");
            fprintf(html,"\t\t<tr><td></td><td><font color=#008000>PIE</font></td><td><font color=#FF0000>PIF</font></td></tr>\n");
            fprintf(html,"\t\t<tr><td>Total</td><td>%s</td><td>%s</td></tr>\n",
                  text_c1pie_total->text().data(),
                  text_c2pif_total->text().data());
            fprintf(html,"\t\t<tr><td>Max</td><td>%s</td><td>%s</td></tr>\n",
                  text_c1pie_max->text().data(),
                  text_c2pif_max->text().data());
            fprintf(html,"\t\t<tr><td>Avg</td><td>%s</td><td>%s</td></tr>\n",
                  text_c1pie_avg->text().data(),
                  text_c2pif_avg->text().data());
            fprintf(html,"\t</tbody>\n");
            fprintf(html,"\t</table>\n");
      }
//  **************  Jitter/Beta  **************
      if (tests & (CHK_JB_CD | CHK_JB_DVD)) {
            fprintf(html,"\t<br><b>Jitter/Beta scan</b><br>\n");
            fprintf(html,"\t<br><IMG border=\"1\" src=\"%s\" alt=\"Jitter/Beta\" height=\"320\" width=\"600\">\n",
                  png_name_jb.data());
            fprintf(html,"\t<table border=\"0\" cellspacing=\"0\" width=\"300\">\n");
            fprintf(html,"\t<tbody align=\"right\">\n");
            fprintf(html,"\t\t<tr><td></td> <td><font color=#008000>Jitter</font></td> <td><font color=#FF0000>Beta</font></td></tr>\n");
            fprintf(html,"\t\t<tr><td>Max</td><td>%s %</td><td>%s %</td></tr>\n",
                  text_j_max->text().data(),
                  text_b_max->text().data());
            fprintf(html,"\t\t<tr><td>Min</td><td>%s %</td><td>%s %</td></tr>\n",
                  text_j_min->text().data(),
                  text_b_min->text().data());
            fprintf(html,"\t\t<tr><td>Avg</td><td>%s %</td><td>%s %</td></tr>\n",
                  text_j_avg->text().data(),
                  text_b_avg->text().data());
            fprintf(html,"\t</tbody>\n");
            fprintf(html,"\t</table>\n");
      }
//  **************  FE/TE  **************
      if (tests & CHK_FETE) {
            fprintf(html,"\t<br><b>Focus/Tracking errors scan</b><br>\n");
            fprintf(html,"\t<br><IMG border=\"1\" src=\"%s\" alt=\"FE/TE\" height=\"320\" width=\"600\">\n",
                  png_name_ft.data());
            fprintf(html,"\t<table border=\"0\" cellspacing=\"0\" width=\"300\">\n");
            fprintf(html,"\t<tbody align=\"right\">\n");
            fprintf(html,"\t\t<tr><td></td> <td><font color=#008000>Tracking</font></td> <td><font color=#FF0000>Focus</font></td></tr>\n");
            fprintf(html,"\t\t<tr><td>Max</td><td>%s</td><td>%s</td></tr>\n",
                  text_t_max->text().data(),
                  text_f_max->text().data());
            fprintf(html,"\t\t<tr><td>Avg</td><td>%s</td><td>%s</td></tr>\n",
                  text_t_avg->text().data(),
                  text_f_avg->text().data());
            fprintf(html,"\t</tbody>\n");
            fprintf(html,"\t</table>\n");
      }
//  **************  Time Analyser  **************
      if (tests & CHK_TA) {
            if (drive->media.disc_type & (DISC_DVDplus | DISC_DVDminus)) {
                  fprintf(html,"\t<br><b>Time Analyser</b><br>\n");
                  fprintf(html,"\t<br><IMG border=\"1\" alt=\"Time Analyser\" src=\"%s\"><br>\n",
                        png_name_ta.data());
            }
      }

//  **************  End of html **************
      fprintf(html,"<br><br>Generated by QPxTool v%s (C) Gennady \"ShultZ\" Kozlov<br>\n",VERSION);
      fprintf(html,"<a href=\"http://qpxtool.sourceforge.net\">http://qpxtool.sourceforge.net</a><br>\n");
      fprintf(html,"</div></body>\n</html>\n");
      fclose (html);
}

void QPxToolWidget::file_save()
{
      char  fname[512],fpath[1024],full_path[1536];
      int   tests;
      QString     res_name;

      save_html_dialog* save_dlg;
      save_dlg = new save_html_dialog(this,"Save ALL",0);
      save_dlg->setParms(drive->chk_features, drive->media.disc_type);
      save_dlg->exec();
      tests = save_dlg->selected();
//    res_name = file_dialog.getSaveFileName("dvd_x.html","*.html");
      res_name = save_dlg->file_name();
//    printf("Tests selected: 0x%04X\n",tests);
      delete save_dlg;
//    printf("SaveHTML DLG deleted\n");
      if (!tests) {
//          printf("SaveHTML canceled\n");
            return;
      }

      if (!res_name.data()) return;
      strcpy(full_path,res_name.data());
      if (drive->media.disc_type & DISC_CD) res_cap = drive->media.capacity/hscaleCD+1;
            else res_cap = (drive->media.capacity/hscaleDVD)/drive->media.layers+1;
      if (res_cap > (hres-2)) res_cap = hres-2;

      printf("Selected file: '%s'\n",full_path);
      file_path_name(full_path, fpath, fname);
      printf("file path: '%s'\n",fpath);
      printf("file name: '%s'\n",fname);
      file_suf_rm(fname);
      printf("file name w/o suffix: '%s'\n",fname);

      logo_name = fpath; logo_name += "logo.png";
      logo->save(logo_name,"PNG");

      if (tests & CHK_RD) {
            result_rd = new QImage (hres,vres,32);
            png_name_rd = fname; png_name_rd += "_tr.png"; full_name_rd = fpath; full_name_rd += png_name_rd;
            printf("TR file: '%s'\n",full_name_rd.data());
            fill_res_rd(); result_rd->save(full_name_rd,"PNG");
            delete result_rd;
      }
      if (tests & (CHK_CX | CHK_PI | CHK_PO)) {
            result_cx = new QImage (hres,vres,32);
            png_name_cx = fname; png_name_cx += "_cx.png"; full_name_cx = fpath; full_name_cx += png_name_cx;
            printf("CX file: '%s'\n",full_name_cx.data());
            fill_res_cx(); result_cx->save(full_name_cx,"PNG");
            delete result_cx;
      }
      if ((tests & CHK_CX) && (drive->media.disc_type & DISC_CD) && (drive->ven_ID == WR_PLEXTOR)) {
            png_name_BLER = fname; png_name_BLER += "_bler.png"; full_name_BLER = fpath; full_name_BLER += png_name_BLER;
            png_name_E11 = fname; png_name_E11 += "_e11.png"; full_name_E11 = fpath; full_name_E11 += png_name_E11;
            png_name_E21 = fname; png_name_E21 += "_e21.png"; full_name_E21 = fpath; full_name_E21 += png_name_E21;
            png_name_E31 = fname; png_name_E31 += "_e31.png"; full_name_E31 = fpath; full_name_E31 += png_name_E31;
            png_name_E12 = fname; png_name_E12 += "_e12.png"; full_name_E12 = fpath; full_name_E12 += png_name_E12;
            png_name_E22 = fname; png_name_E22 += "_e22.png"; full_name_E22 = fpath; full_name_E22 += png_name_E22;
            png_name_E32 = fname; png_name_E32 += "_e32.png"; full_name_E32 = fpath; full_name_E32 += png_name_E32;

            result_cx = new QImage (hres,vres/2,32); printf("BLER file: '%s'\n",full_name_BLER.data());
            fill_res_cx_ext(CD_EXT_BLER); result_cx->save(full_name_BLER,"PNG");
            delete result_cx;

            result_cx = new QImage (hres,vres/2,32); printf("E11 file: '%s'\n",full_name_E11.data());
            fill_res_cx_ext(CD_EXT_E11); result_cx->save(full_name_E11,"PNG");
            delete result_cx;

            result_cx = new QImage (hres,vres/2,32); printf("E21 file: '%s'\n",full_name_E21.data());
            fill_res_cx_ext(CD_EXT_E21); result_cx->save(full_name_E21,"PNG");
            delete result_cx;

            result_cx = new QImage (hres,vres/2,32); printf("E31 file: '%s'\n",full_name_E31.data());

            fill_res_cx_ext(CD_EXT_E31); result_cx->save(full_name_E31,"PNG");
            delete result_cx;

            result_cx = new QImage (hres,vres/2,32); printf("E12 file: '%s'\n",full_name_E21.data());
            fill_res_cx_ext(CD_EXT_E12); result_cx->save(full_name_E12,"PNG");
            delete result_cx;

            result_cx = new QImage (hres,vres/2,32); printf("E22 file: '%s'\n",full_name_E22.data());
            fill_res_cx_ext(CD_EXT_E22); result_cx->save(full_name_E22,"PNG");
            delete result_cx;

            result_cx = new QImage (hres,vres/2,32); printf("E32 file: '%s'\n",full_name_E32.data());
            fill_res_cx_ext(CD_EXT_E32); result_cx->save(full_name_E32,"PNG");
            delete result_cx;
      }
      if (tests & (CHK_JB_CD | CHK_JB_DVD)) {
            result_jb = new QImage (hres,vres,32);
            png_name_jb = fname; png_name_jb += "_jb.png"; full_name_jb = fpath; full_name_jb += png_name_jb;
            printf("JB file: '%s'\n",full_name_jb.data());
            fill_res_jb(); result_jb->save(full_name_jb,"PNG");
            delete result_jb;
      }
      if (tests & CHK_FETE) {
            result_ft = new QImage (hres,vres,32);
            png_name_ft = fname; png_name_ft += "_ft.png"; full_name_ft = fpath; full_name_ft += png_name_ft;
            printf("FT file: '%s'\n",full_name_ft.data());
            fill_res_ft(); result_ft->save(full_name_ft,"PNG");
            delete result_ft;
      }
      if (tests & CHK_TA) {
            png_name_ta = fname; png_name_ta += "_ta.png";
            if (drive->media.disc_type & (DISC_DVDplus | DISC_DVDminus)) {
                  full_name_ta = fpath; full_name_ta += png_name_ta; printf("TA file: '%s'\n",full_name_ta.data());
                  result_ta = new QImage (hresta*drive->media.layers,vresta*6,32);
                  fill_res_ta(); result_ta->save(full_name_ta,"PNG");
                  delete result_ta;
            }
      }
      generate_result_html(res_name, tests);

      printf("saved\n");
}

void QPxToolWidget::end_tests()
{
      status_current_test->setText("idle...");
      push_abort->setEnabled(false);
      push_skip->setEnabled(false);
//    push_refresh->setEnabled(true);
      push_scan_start->setEnabled(true);
      progress_test->setProgress(0,1);
      get_media_info(drive);
}

void QPxToolWidget::about()
{
      about_dialog *about_dlg;
      about_dlg = new about_dialog(this,"About",1);
      about_dlg->show();
}

void QPxToolWidget::customEvent(QCustomEvent *event){
      QMessageBox* msg;
      int event_id = event->type();
      switch (event_id) {
            case event_test_init:
                  combo_drive->setEnabled(false);
                  reset_progress();
                  status_current_test->setText(QString("%1").arg((char*)event->data()));
                  textDebug->append(QString("Starting test: %1").arg((char*)event->data()));
                  break;
/*
            case event_start_rd:
                  zero_rd(); break;
            case event_start_cx:
                  zero_cx(); break;
            case event_start_jb:
                  zero_jb(); break;
            case event_start_ft:
                  zero_ft(); break;
            case event_start_ta:
                  zero_ta(); break;
*/
            case event_debug:
                  textDebug->append(QString("%1").arg((char*)event->data()));
                  break;
            case event_test_done:
//                test_finished();
                  break;
            case event_all_tests_done:
                  end_tests();
                  msg = new QMessageBox (QString(""),
                        QString("All tests complete!"),
                        QMessageBox::Information,
                        QMessageBox::Ok | QMessageBox::Default | QMessageBox::Escape,
                        QMessageBox::NoButton,
                        QMessageBox::NoButton,
                        this);
                  msg->exec();
                  delete msg;
                  combo_drive->setEnabled(true);
                  break;
            case event_tests_aborted:
                  end_tests();
                  msg = new QMessageBox (QString(""),
                        QString("Testing aborted!"),
                        QMessageBox::Information,
                        QMessageBox::Ok | QMessageBox::Default | QMessageBox::Escape,
                        QMessageBox::NoButton,
                        QMessageBox::NoButton,
                        this);
                  msg->exec();
                  delete msg;
                  combo_drive->setEnabled(true);
                  break;
            case event_block_done_rd:
                  block_done_rd((block_data*)event->data());
                  showtime((block_data*)event->data());
                  break;
            case event_block_done_c1pie:
                  block_done_c1pie((block_data*)event->data());
                  showtime((block_data*)event->data());
                  break;
            case event_block_done_c2pif:
                  block_done_c2pif((block_data*)event->data());
                  showtime((block_data*)event->data());
                  break;
            case event_block_done_cupof:
                  block_done_cupof((block_data*)event->data());
                  break;
            case event_block_done_jb:
                  block_done_jb((block_data*)event->data());
                  showtime((block_data*)event->data());
                  break;
            case event_block_done_fete:
                  block_done_fete((block_data*)event->data());
                  showtime((block_data*)event->data());
                  break;
            case event_block_done_ta:
                  block_done_ta((block_data*)event->data());
                  break;

            case event_block_done_BLER:
                  block_done_cx_ext((block_data*)event->data(),event_id);
                  break;
            case event_block_done_E11:
                  block_done_cx_ext((block_data*)event->data(),event_id);
                  break;
            case event_block_done_E21:
                  block_done_cx_ext((block_data*)event->data(),event_id);
                  break;
            case event_block_done_E31:
                  block_done_cx_ext((block_data*)event->data(),event_id);
                  break;
            case event_block_done_E12:
                  block_done_cx_ext((block_data*)event->data(),event_id);
                  break;
            case event_block_done_E22:
                  block_done_cx_ext((block_data*)event->data(),event_id);
                  break;
            case event_block_done_E32:
                  block_done_cx_ext((block_data*)event->data(),event_id);
                  break;
            case event_show_lba:
                  show_lba((block_data*)event->data());
                  break;
            default:
                  break;
      }
}

void QPxToolWidget::quit()
{
      int i=0,j=0;      
      abort_tests();
      printf("\n** Waiting for scan thread to end...\n");
      thread->wait();
      printf("\n** Destroying dynamic objects...\n");
// Destroying results
      printf("**   Destroying results...\n");
      for (i=0; i<hres; i++) {
            delete RezRD[i]; delete Rez0[i]; delete Rez1[i]; delete Rez2[i];
            delete RezJ[i]; delete RezB[i];
      }
      delete RezRD; delete Rez0; delete Rez1; delete Rez2;
      delete RezJ; delete RezB;
      for (i=0; i<hresft; i++) {
            delete RezFE[i]; delete RezTE[i];
      }
      delete RezFE; delete RezTE;
      for (i=0; i<6; i++)
            for (j=0; j<hresta; j++) 
                  { delete RezTAP[i][j]; delete RezTAL[i][j]; }
// Destroying grid
      printf("**   Destroying grid...\n");
      for (i=0;i<grids_RD;i++) delete GridRD[i];
      delete GridRD;
      for (i=0;i<grids_CX;i++) delete Grid0[i];
      delete Grid0;
      for (i=0;i<grids_JB;i++) delete GridJB[i];
      delete GridJB;
      for (i=0;i<grids_FT;i++) delete GridFT[i];
      delete GridFT;
      for (i=0;i<grids_TA;i++)
            { delete GridTAP[i]; delete GridTAL[i]; }
      delete GridTAP; delete GridTAL;
      for (i=0; i<3; i++) delete Limits[i];
//    delete drive->test_thread_id;
      delete drive;
      delete Exx.BLER;
      delete Exx.E11; delete Exx.E21; delete Exx.E31;
      delete Exx.E12; delete Exx.E22; delete Exx.E32;

#ifdef __DISP_TRK
      for (i=0; i<255; i++)
            if (sessions[i]){ delete sessions[i]; sessions[i]=NULL; }
#endif
//    delete pix_ok;
//    delete pix_no;
//    delete pix_unknown;
      delete logo;
      printf("*** Exiting QPxTool\n");
      exit (0);
}

Generated by  Doxygen 1.6.0   Back to index