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 <qpx_transport.h>
#include <qpx_mmc.h>
#include <plextor_features.h>
#include <pioneer_spdctl.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 "scan_events.h"
#include <watcher.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"

#include <libver_qpxtransport.h>
#include <libver_qpxscan.h>
#include <libver_qpxplextor.h>
#include <libver_qpxpioneer.h>

//#define  __ENABLE_PX_POE

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};

//QPxToolWidget::QPxToolWidget(QWidget* parent, const char* name, WFlags fl)
QPxToolWidget::QPxToolWidget(QWidget *parent, const char *name)
        : QPxTool_mainwin_UI(parent,name)
{
      int libver, libver_min;
      printf("** Trying to determine qpx libraries versions...");
      
      libver = libver_qpxtransport();
      libver_min = LIBVER_MIN_TRANSPORT;
      printf("\nlibqpxtransport :");
      printf(" %d.%d.%d",(libver >> 16) & 0xFF, (libver >> 8) & 0xFF, libver & 0xFF);
//    printf("( %s", (libver < libver_min) ? "<" : ">=");
//    printf(" %d.%d.%d)",(libver_min >> 16) & 0xFF, (libver_min >> 8) & 0xFF, libver_min & 0xFF);

      libver = libver_qpxscan();
      libver_min = LIBVER_MIN_SCAN;
      printf("\nlibqpxscan      :");
      printf(" %d.%d.%d",(libver >> 16) & 0xFF, (libver >> 8) & 0xFF, libver & 0xFF);
//    printf("( %s", (libver < libver_min) ? "<" : ">=");
//    printf(" %d.%d.%d\n)",(libver_min >> 16) & 0xFF, (libver_min >> 8) & 0xFF, libver_min & 0xFF);

      libver = libver_qpxplextor();
      libver_min = LIBVER_MIN_PLEXTOR;
      printf("\nlibqpxplextor   :");
      printf(" %d.%d.%d",(libver >> 16) & 0xFF, (libver >> 8) & 0xFF, libver & 0xFF);
//    printf("( %s", (libver < libver_min) ? "<" : ">=");
//    printf(" %d.%d.%d\n)",(libver_min >> 16) & 0xFF, (libver_min >> 8) & 0xFF, libver_min & 0xFF);

      libver = libver_qpxpioneer();
      libver_min = LIBVER_MIN_PIONEER;
      printf("\nlibqpxpioneer   :");
      printf(" %d.%d.%d",(libver >> 16) & 0xFF, (libver >> 8) & 0xFF, libver & 0xFF);
//    printf("( %s", (libver < libver_min) ? "<" : ">=");
//    printf(" %d.%d.%d\n)",(libver_min >> 16) & 0xFF, (libver_min >> 8) & 0xFF, libver_min & 0xFF);

      printf("\n");

      int i,j;
      pix_logo.convertFromImage(QImage(q_xpm),0);
      setIcon(pix_logo);

//    printf(tr("** static init...\n"));
      push_abort->setEnabled(false);
      push_skip->setEnabled(false);

      speedidx=0, devtype=0, drvcnt=0, drvidx=0, grecn=0;
      c1pie_total=0,    c2pif_total=0,    cu_total=0;
      c1pie_max=0,      c2pif_max=0;      cu_max=0;
      c1pie_avg=0.0,    c2pif_avg=0.0,    cu_avg=0.0; 
      j_min=0.0, j_max=0.0, j_avg=0.0;
      b_min=0.0, b_max=0.0, b_avg=0.0;
      TA_cur=0, TA_new=0, TA_layer=0, TA_zone=0;
      silent = 1;
      last_cd_scan_speed = 0; last_dvd_scan_speed = 0;

//    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("** dinamic objects init...\n");
      device=(char*)malloc(0xFF);
      logo = new QImage(logo_xpm);

      printf("** 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("Transfer rate",this,SLOT(file_save_rd()));
      menu_save->insertItem("Cx/Pi",this,SLOT(file_save_cx()));
      menu_save->insertItem("Jitter/Beta",this,SLOT(file_save_jb()));
      menu_save->insertItem("FE/TE",this,SLOT(file_save_ft()));
      menu_save->insertItem("Time analyser",this,SLOT(file_save_ta()));
      menu_file->insertItem("Save results...",menu_save);

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

      menu_about = new QPopupMenu (this);
      menu_about->insertItem("About QPxTool",this,SLOT(about()));
//    menubar->insertItem("About",menu_about);
      MenuBarEditor->insertItem("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);
      stateCol_reset();

      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("** 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("** 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("C1/PIE");
      Rez_00 = (QCanvasLine**) malloc ((hres)*sizeof(QCanvasLine*));
      for (i=0; i< hres; i++) {
            Rez_00[i] = new QCanvasLine( Canvas0 );
            Rez_00[i]->setPen(QPen(QColor(color_BLERl), 1, SolidLine));
      }
// -----------------
      Rez_01 = (QCanvasLine**) malloc ((hres)*sizeof(QCanvasLine*));
      for (i=0; i< hres; i++) {
            Rez_01[i] = new QCanvasLine( Canvas0 );
            Rez_01[i]->setPen(QPen(QColor(color_BLER), 1, SolidLine));
//          Rez0[i]->setPen(QPen(qRgba(0,0xC0,0,0x10), 1, SolidLine));
//          Rez0[i]->show();
      }
// -----------------
      printf(", C2/PIF");
      Rez_10 = (QCanvasLine**) malloc (hres*sizeof(QCanvasLine*));
      for (i=0; i< hres; i++) {
            Rez_10[i] = new QCanvasLine( Canvas0 ); // ( Canvas1 );
            Rez_10[i]->setPen(QPen(QColor(color_E22l), 1, SolidLine));
//          Rez1[i]->show();
      }
// -----------------
      Rez_11 = (QCanvasLine**) malloc (hres*sizeof(QCanvasLine*));
      for (i=0; i< hres; i++) {
            Rez_11[i] = new QCanvasLine( Canvas0 ); // ( Canvas1 );
            Rez_11[i]->setPen(QPen(QColor(color_E22), 1, SolidLine));
//          Rez1[i]->show();
      }
// -----------------
      printf(", CU\n");
      Rez_20 = (QCanvasLine**) malloc (hres*sizeof(QCanvasLine*));
      for (i=0; i< hres; i++) {
            Rez_20[i] = new QCanvasLine( Canvas0 ); // ( Canvas1 );
            Rez_20[i]->setPen(QPen(QColor(color_E32l), 1, SolidLine));
      }
// -----------------
      Rez_21 = (QCanvasLine**) malloc (hres*sizeof(QCanvasLine*));
      for (i=0; i< hres; i++) {
            Rez_21[i] = new QCanvasLine( Canvas0 ); // ( Canvas1 );
            Rez_21[i]->setPen(QPen(QColor(color_E32), 1, SolidLine));
//          Rez2[i]->show();
      }
// -----------------
      Grid0 = (QCanvasLine**) malloc (grids_CX*sizeof(QCanvasLine*));
      DrawGrid0();

// ------------------------------------------------------------
      printf("** 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(color_jitter), 1, SolidLine));
//          RezJ[i]->show();
      }
      printf(" 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(color_beta), 1, SolidLine));
//          RezB[i]->show();
      }
      printf(", Beta OK\n");

// ------------------------------------------------------------
      printf("** 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(color_FE), 1, SolidLine));
//          RezTE[i]->show();
      }
      printf(" FE");
      RezTE = (QCanvasLine**) malloc ((hresft)*sizeof(QCanvasLine*));
      for (i=0; i< hresft; i++) {
            RezTE[i] = new QCanvasLine( CanvasFT ); // ( Canvas1 );
            RezTE[i]->setPen(QPen(QColor(color_TE), 1, SolidLine));
//          RezTE[i]->show();
      }
      printf(", TE\n");

// ------------------------------------------------------------
      printf("** 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(color_TAP), 1, SolidLine));
                  RezTAL[i][j] = new QCanvasLine( CanvasTAL );
                  RezTAL[i][j]->setPen(QPen(QColor(color_TAL), 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(" 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("** 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 = (err*) malloc (hres*sizeof(err));
      Exx.E11 = (err*) malloc (hres*sizeof(err));
      Exx.E21 = (err*) malloc (hres*sizeof(err));
      Exx.E31 = (err*) malloc (hres*sizeof(err));
      Exx.E12 = (err*) malloc (hres*sizeof(err));
      Exx.E22 = (err*) malloc (hres*sizeof(err));
      Exx.E32 = (err*) malloc (hres*sizeof(err));

      Exx.color[0] = color_BLER; Exx.colorl[0] = color_BLERl;
      Exx.color[1] = color_E11;  Exx.colorl[1] = color_E11l;
      Exx.color[2] = color_E21;  Exx.colorl[2] = color_E21l;
      Exx.color[3] = color_E31;  Exx.colorl[3] = color_E31l;
      Exx.color[4] = color_E12;  Exx.colorl[4] = color_E12l;
      Exx.color[5] = color_E22;  Exx.colorl[5] = color_E22l;
      Exx.color[6] = color_E32;  Exx.colorl[6] = color_E32l;
      ext_cx_active = 0;

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

      thread = new ScanThread(this);
      thread_time = new ScanTimer(this);
//    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("Fast");
      combo_silent_access->insertItem("Slow");

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

      printf("** clearing results...\n");
      clear_all();
      printf("** 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("No disc");
            text_media_type->setText("No disc");
      } else {
            status_media_type->setText("unknown");
            text_media_type->setText("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 (watcher->running()) watcher->terminate();
      if (drive) delete drive;
      drvcnt=0;
      int i,inq;
      combo_drive->clear();
      textDebug->append("** Scaning for MMC compliant devices...");
      printf("** 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("** 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("\nSelected: %s\n",drv.data());
      delete drive;
      strcpy(device,drvtbl[drivenum]);
      drive = new drive_info(device);
      watcher->init(drivenum, drive);
      select_device();
}

void QPxToolWidget::select_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);
      text_pr0->setEnabled(false);
      text_pr_spd->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);
      text_vrcd0->setEnabled(false);

      check_VariRec_dvd->setEnabled(false);
      combo_VariRecPower_dvd->setEnabled(false);
      combo_VariRecStrategy_dvd->setEnabled(false);
      text_vrdvd0->setEnabled(false);

      check_bitset_r->setEnabled(false);
      check_bitset_rdl->setEnabled(false);
      check_simul_dvdplus->setEnabled(false);
      group_autostrategy->setEnabled(false);
      group_securec->setEnabled(false);
      group_silent->setEnabled(false);
      group_plexeraser->setEnabled(false);
      group_pioquiet->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("<font color=red>Unable to open: %1</font>").arg(drive->device));
                  return;
            case 0x0F:
                  textDebug->append(QString("<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]));
//printf("detect_iface(drive);\n");
      detect_iface(drive);
      text_iface->setText(QString("%1").arg(drive->iface));
//printf("show_spindown_time(drive);\n");
      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);
      }

//printf("update_device_info();\n");
      update_device_info();
//printf("show_capabilities(drive);\n");
      show_capabilities(drive);
/*
      combo_commands->setEnabled(false);
      if ((drive->ven_ID == WR_GENERIC) || (drive->dev_ID == 1 ))
            combo_commands->setEnabled(true);
//*/
      if (!watcher->running()) watcher->start();
}

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);
            px755_do_auth(drive);
            if (drive->dev_ID == PLEXTOR_760) drive->ven_features|=PX_ERASER;
      };
      if (get_drive_serial_number(drive)) {
            text_serial->setText(drive->serial);
      }
      drive->silent++;
      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_silentmode(drive)) drive->ven_features|=PX_SILENT;
            if (!plextor_get_securec_state(drive)) drive->ven_features|=PX_SECUREC;
      }
      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 (!pioneer_get_quiet(drive)) drive->ven_features|=PIO_QUIET;
      drive->silent--;

/*          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("Hide CD-R           : %s\n", drive->ven_features & PX_HCDRSS ? "YES" : "---");
      printf("SingleSession       : %s\n", drive->ven_features & PX_HCDRSS ? "YES" : "---");
      printf("SpeedRead           : %s\n", drive->ven_features & PX_SPDREAD ? "YES" : "---");
      printf("PoweRec             : %s\n", drive->ven_features & PX_POWEREC ? "YES" : "---");
      printf("GigaRec             : %s\n", drive->ven_features & PX_GIGAREC ? "YES" : "---");
      printf("VariRec CD          : %s\n", drive->ven_features & PX_VARIREC_CD ? "YES" : "---");
      printf("VariRec DVD         : %s\n", drive->ven_features & PX_VARIREC_DVD ? "YES" : "---");
      printf("SecuRec             : %s\n", drive->ven_features & PX_SECUREC ? "YES" : "---");
      printf("Silent mode         : %s\n", drive->ven_features & PX_SILENT ? "YES" : "---");
      printf("DVD+R bitsetting    : %s\n", drive->ven_features & PX_BITSET_R ? "YES" : "---");
      printf("DVD+R DL bitsetting : %s\n", drive->ven_features & PX_BITSET_RDL ? "YES" : "---");
      printf("DVD+R(W) testwrite  : %s\n", drive->ven_features & PX_SIMUL_PLUS ? "YES" : "---");
      printf("AutoStrategy        : %s%s\n",
            drive->ven_features & PX_ASTRATEGY ? "YES" : "---",
            (drive->ven_features & PX_ASTRATEGY) && (drive->dev_ID == PLEXTOR_760) ? " (EXTENDED)" : "");
      printf("PlexEraser          : %s\n", drive->ven_features & PX_ERASER ? "YES" : "---");
      printf("Pioneer Quiet Mode  : %s\n", drive->ven_features & PIO_QUIET ? "YES" : "---");
      printf("**\n");
      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) {
            text_pr0->setEnabled(true);
            text_pr_spd->setEnabled(true);
            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_SECUREC) {
            group_securec->setEnabled(true);
            check_securec_changed(!drive->plextor.securec);
            if (drive->plextor.securec) push_securec->setText("Deactivate");
            else push_securec->setText("Activate");
      }
      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);
*/
            check_simul_dvdplus->setChecked((drive->plextor.testwrite_dvdplus));
      }
      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);
            }
*/
            radio_as_forced->setEnabled(drive->dev_ID > PLEXTOR_716);
            radio_as_on->setEnabled(drive->dev_ID > PLEXTOR_716);

            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;
            }
      }
      if (drive->ven_features & PIO_QUIET) {
            group_pioquiet->setEnabled(true);
            switch (drive->pioneer.silent)
            {
                  case PIO_SILENT_QUIET: radio_pioq_quiet->setChecked(true); break;
                  case PIO_SILENT_PERF: radio_pioq_perf->setChecked(true); break;
                  case PIO_SILENT_STD: radio_pioq_std->setChecked(true); break;
            }
            check_pio_speedlimit->setChecked(drive->pioneer.limit);
      }
}

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_securec_used->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
            get_track_list(drive);
            session=-1;

            if (drive->media.tracks) {
                  for (i=0; i < drive->media.tracks; i++) {
                        if (drive->media.track[i].session<255) {
                        if ((drive->media.track[i].session-1)>session) {
                              session = drive->media.track[i].session-1;
                              printf("Session %d...\n",session+1);
                              sessions[session] = new QListViewItem(list_tracks,
                                    QString().sprintf("Session%02d", drive->media.track[i].session), "", "", "", "", "");
                        }
                        if (drive->media.track[i].track_mode == 2)
                              new QListViewItem(sessions[session],
                              QString().sprintf("Track%02d",i),
                              QString().sprintf("%s ",
                                    track_mode[drive->media.track[i].track_mode]),
                              QString().sprintf(" %d:%02d.%02d",
                                    drive->media.track[i].time.m,
                                    drive->media.track[i].time.s,
                                    drive->media.track[i].time.f),
                              QString().sprintf(" %d:%02d.%02d",
                                    drive->media.track[i].msf_start.m,
                                    drive->media.track[i].msf_start.s,
                                    drive->media.track[i].msf_start.f),
                              QString().sprintf(" %d:%02d.%02d",
                                    drive->media.track[i].msf_end.m,
                                    drive->media.track[i].msf_end.s,
                                    drive->media.track[i].msf_end.f));
                        else
                              new QListViewItem(sessions[session],
                              QString().sprintf("Track%02d",i),
                              QString().sprintf(" %s/%s",
                                    track_mode[drive->media.track[i].track_mode],
                                    data_mode[drive->media.track[i].data_mode]),
                              QString().sprintf(" %dM",drive->media.track[i].size >> 9),
                              QString().sprintf(" %d",drive->media.track[i].start),
                              QString().sprintf(" %d",drive->media.track[i].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->ven_ID == WR_PLEXTOR)) push_px_cx_ext->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);
            combo_scan_speed->setCurrentItem(last_dvd_scan_speed);
            set_scan_speed("");
/*
            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");
            combo_scan_speed->setCurrentItem(last_cd_scan_speed);
            set_scan_speed("");
/*
            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_SECUREC)) {
                  plextor_get_securec_state(drive);
                  text_securec_used->setText(drive->plextor.securec_disc ? "YES" : "NO");
            }
            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="176M/20min"; g2="352M/40min"; g3="528M/60min"; g4="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&)
{
      int idx = combo_scan_speed->currentItem();
      if ( drive->media.disc_type & DISC_DVD ) {
            drive->parms.scan_speed_dvd=speeds_sc_dvd[idx];
            last_dvd_scan_speed = idx;
      } else {
            drive->parms.scan_speed_cd=speeds_sc_cd[idx];
            last_cd_scan_speed = idx;
      }
}

// 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("== 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);
                        if (!silent) 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);
                        if (!silent) 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 (%dkB/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(int speedidx)
{
//    char spdstr[20];
//    strcpy(spdstr,speed.data());

//    speedidx = combo_Speed->currentItem();

      drive->parms.read_speed_kb = drive->parms.speed_tbl_kb[speedidx];
      printf("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;
      combo_silent_cd_rd->setEnabled(!(drive->media.disc_type & DISC_DVD));
      combo_silent_cd_wr->setEnabled(!(drive->media.disc_type & DISC_DVD));
      combo_silent_dvd_rd->setEnabled((drive->media.disc_type & DISC_DVD));
      combo_silent_dvd_wr->setEnabled((drive->media.disc_type & DISC_DVD));

      if ( drive->media.disc_type & DISC_DVD ) {
            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{
            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 ) {
                  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);
            }
            combo_silent_cd_rd->setEnabled(!drive->media.disc_type & DISC_DVD);
            combo_silent_cd_wr->setEnabled(!drive->media.disc_type & DISC_DVD);
            combo_silent_dvd_rd->setEnabled((drive->media.disc_type & DISC_DVD));
            combo_silent_dvd_wr->setEnabled((drive->media.disc_type & DISC_DVD));
            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("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
            text_vrcd0->setEnabled(true);
            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
            text_vrcd0->setEnabled(false);
            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
            text_vrdvd0->setEnabled(true);
            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
            text_vrdvd0->setEnabled(false);
            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);
            if (drive->media.disc_type) detect_speeds();
            show_read_speed(drive);
      } else {    // Disable SpeedRead
            plextor_set_speedread(drive, 0);
            if (drive->media.disc_type) detect_speeds();
            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::securec_act_deact()
{
      QMessageBox* msg;
      char  len = 0;
      char  passwd1[255];
      char  passwd2[255];
      if (drive->plextor.securec) { // SecuRec active -> DeActivate
            plextor_set_securec(drive, 0, NULL);
            plextor_get_securec_state(drive);
            if (!drive->plextor.securec) {
                  check_securec_changed(!drive->plextor.securec);
                  msg = new QMessageBox (QString(""),
                        QString("SecuRec successfully DEactivated!"),
                        QMessageBox::Information,
                        QMessageBox::Ok | QMessageBox::Default | QMessageBox::Escape,
                        QMessageBox::NoButton,
                        QMessageBox::NoButton,
                        this);
                  msg->exec();
                  delete msg;
                  push_securec->setText("Activate\n");
            } else {
                  printf("!!! Failed to Deactivate SecuRec !!!\n");
                  msg = new QMessageBox (QString(""),
                        QString("Failed to DEactivate SecuRec!"),
                        QMessageBox::Critical,
                        QMessageBox::Ok | QMessageBox::Default | QMessageBox::Escape,
                        QMessageBox::NoButton,
                        QMessageBox::NoButton,
                        this);
                  msg->exec();
                  delete msg;
            }
      } else { // SecuRec NOT active -> Activate it
            strcpy(passwd1, line_sr_passwd1->text().data());
            strcpy(passwd2, line_sr_passwd2->text().data());
            if (strcmp(passwd1,passwd2)) {
                  printf("Passwords are NOT identical\n");
                  msg = new QMessageBox (QString(""),
                        QString("Passwords are NOT identical!"),
                        QMessageBox::Warning,
                        QMessageBox::Ok | QMessageBox::Default | QMessageBox::Escape,
                        QMessageBox::NoButton,
                        QMessageBox::NoButton,
                        this);
                  msg->exec();
                  delete msg;
                  return;
            }
            len = strlen(passwd1);
            if (len < 4) {
                  msg = new QMessageBox (QString(""),
                        QString("Password too short!\nShould be at least 4 characters"),
                        QMessageBox::Warning,
                        QMessageBox::Ok | QMessageBox::Default | QMessageBox::Escape,
                        QMessageBox::NoButton,
                        QMessageBox::NoButton,
                        this);
                  msg->exec();
                  delete msg;
                  return;
            }
            plextor_set_securec(drive, len, passwd1);
            plextor_get_securec_state(drive);
            if (drive->plextor.securec) {
                  check_securec_changed(!drive->plextor.securec);
                  msg = new QMessageBox (QString(""),
                        QString("SecuRec successfully activated!"),
                        QMessageBox::Information,
                        QMessageBox::Ok | QMessageBox::Default | QMessageBox::Escape,
                        QMessageBox::NoButton,
                        QMessageBox::NoButton,
                        this);
                  msg->exec();
                  delete msg;
                  push_securec->setText("Dectivate\n");
            } else {
                  printf("!!! Failed to activate SecuRec !!!\n");
                  msg = new QMessageBox (QString(""),
                        QString("Failed to activate SecuRec!\n"),
                        QMessageBox::Critical,
                        QMessageBox::Ok | QMessageBox::Default | QMessageBox::Escape,
                        QMessageBox::NoButton,
                        QMessageBox::NoButton,
                        this);
                  msg->exec();
                  delete msg;
            }
      }
}

void QPxToolWidget::check_securec_changed(int state)
{
      if ((!!state) != (!!drive->plextor.securec))
      check_securec->setChecked(drive->plextor.securec);
}

void QPxToolWidget::set_pioq_quiet(bool set)
      { if (!set) return; pioneer_set_silent(drive, PIO_SILENT_QUIET, false); }

void QPxToolWidget::set_pioq_perf(bool set)
      { if (!set) return; pioneer_set_silent(drive, PIO_SILENT_PERF, false); }

void QPxToolWidget::set_pioq_std(bool set)
      { if (!set) return; pioneer_set_silent(drive, PIO_SILENT_STD, false); }

void QPxToolWidget::set_pioneer_speedlimit_state(int state)
      { pioneer_set_spdlim(drive, !!state, false); }

void QPxToolWidget::pioq_save()
      { pioneer_set_quiet(drive, drive->pioneer.silent, drive->pioneer.limit, true); }

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

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

void QPxToolWidget::toggle_cu(bool state)
{
      int i;
      if (state) for (i=0;i<hres;i++) { Rez_20[i]->show(); Rez_21[i]->show(); }
      else for (i=0;i<hres;i++) { Rez_20[i]->hide(); Rez_21[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;
      push_px_cx_ext->setEnabled(false);

      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 ) {
            if (drive->ven_ID == WR_PLEXTOR) push_px_cx_ext->setEnabled(true);
            check_cx->setEnabled(true);
            check_jb_cd->setEnabled(true);
            drive->chk_features |= CHK_CX | CHK_JB_CD;
      }
}

void QPxToolWidget::draw_ext_cx()
{
      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, Exx.colorl, drive->media.capacity/hscaleCD);
      ext_cx_active = 1;
      px_ecx->exec();
      ext_cx_active = 0;
      delete px_ecx;
}

void QPxToolWidget::run_tests()
{
      watcher->terminate();
      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::HighPriority);
      thread->start(QThread::TimeCriticalPriority);
      thread_time->start(QThread::NormalPriority);
#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 max, int min, int m, int d)
{
//    printf("C1: max = %3d, min = %3d, M = %3d,  D = %3d\n", max, min, m, d);
      int max0 = 0, min0 = 0;
      max0 = m + (int)sqrt(d);
      min0 = m - (int)sqrt(d);
      min0--;
      if (max>0)  max=(int)(100*(float)log10(max)+10); else max=1;
      if (min>0)  min=(int)(100*(float)log10(min)+10); else min=1;
      if (max0>0) max0=(int)(100*(float)log10(max0)+10); else max0=1;
      if (min0>0) min0=(int)(100*(float)log10(min0)+10); else min0=1;
      Rez_00[idx]->setPoints(idx,vres-min,idx,vres-max);  // C1 / PIE
      Rez_01[idx]->setPoints(idx,vres-min0,idx,vres-max0);
}

void QPxToolWidget::DrawRes1(int idx,int max, int min, int m, int d)
{
//    printf("C2: max = %3d, min = %3d, M = %3d,  D = %3d\n", max, min, m, d);
      int max0 = 0, min0 = 0;
      max0 = m + (int)sqrt(d);
      min0 = m - (int)sqrt(d);
      min0--;
      if (max>0) max=(int)(100*(float)log10(max)+10); else max=1;
      if (min>0) min=(int)(100*(float)log10(min)+10); else min=1;
      if (max0>0) max0=(int)(100*(float)log10(max0)+10); else max0=1;
      if (min0>0) min0=(int)(100*(float)log10(min0)+10); else min0=1;
      Rez_10[idx]->setPoints(idx,vres-min,idx,vres-max);  // C2 / PIF
      Rez_11[idx]->setPoints(idx,vres-min0,idx,vres-max0);
}

void QPxToolWidget::DrawRes2(int idx,int max, int min, int m, int d)
{
//    printf("CU: max = %3d, min = %3d, M = %3d,  D = %3d\n", max, min, m, d);
      int max0 = 0, min0 = 0;
      max0 = m + (int)sqrt(d);
      min0 = m - (int)sqrt(d);
      min0--;
      if (max>0) max=(int)(100*(float)log10(max)+10); else max=1;
      if (min>0) min=(int)(100*(float)log10(min)+10); else min=1;
      if (max0>0) max0=(int)(100*(float)log10(max0)+10); else max0=1;
      if (min0>0) min0=(int)(100*(float)log10(min0)+10); else min0=1;
      Rez_20[idx]->setPoints(idx,vres-min,idx,vres-max);  // CU
      Rez_21[idx]->setPoints(idx,vres-min0,idx,vres-max0);
}

//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()
{
      unsigned 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()
{
      unsigned 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()
{
      unsigned 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()
{
      unsigned 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()
{
      unsigned 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()
{
      zero_cx0();
      zero_cx1();
}

void QPxToolWidget::zero_cx0()
{
      int i;
      for (i=0; i< hres; i++) {
            Rez_00[i]->setPoints(i,vres,i,vres); Rez_01[i]->setPoints(i,vres,i,vres);
            Rez_20[i]->setPoints(i,vres,i,vres); Rez_21[i]->setPoints(i,vres,i,vres);
            Exx.BLER[i].max=0; Exx.BLER[i].min=0; Exx.BLER[i].m=0; Exx.BLER[i].d=0;
            Exx.E11[i].max=0;  Exx.E11[i].min=0;  Exx.E11[i].m=0;  Exx.E11[i].d=0;
            Exx.E21[i].max=0;  Exx.E21[i].min=0;  Exx.E21[i].m=0;  Exx.E21[i].d=0;
            Exx.E31[i].max=0;  Exx.E31[i].min=0;  Exx.E31[i].m=0;  Exx.E31[i].d=0;
            Exx.E12[i].max=0;  Exx.E12[i].min=0;  Exx.E12[i].m=0;  Exx.E12[i].d=0;
            Exx.E22[i].max=0;  Exx.E22[i].min=0;  Exx.E22[i].m=0;  Exx.E22[i].d=0;
            Exx.E32[i].max=0;  Exx.E32[i].min=0;  Exx.E32[i].m=0;  Exx.E32[i].d=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_cu_total->setText("0");
      text_cu_avg->setText("0.00");
      text_cu_max->setText("0");
}

void QPxToolWidget::zero_cx1()
{
      int i;
      for (i=0; i< hres; i++) {
            Rez_10[i]->setPoints(i,vres,i,vres); Rez_11[i]->setPoints(i,vres,i,vres);
      }
      text_c2pif_total->setText("0");
      text_c2pif_avg->setText("0.00");
      text_c2pif_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_cx0();
      if((block->idx > (hres-1)) | (block->idx < 0)) return;
      DrawRes0(block->idx, block->err_cur, block->err_min, block->err_m, block->err_d);
      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) zero_cx1();
      if((block->idx > (hres-1)) | (block->idx < 0)) return;
      DrawRes1(block->idx, block->err_cur, block->err_min, block->err_m, block->err_d);
      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, block->err_min, block->err_m, block->err_d);
      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].max = block->err_cur;
                  Exx.BLER [block->idx].min = block->err_min;
                  Exx.BLER [block->idx].m = block->err_m;
                  Exx.BLER [block->idx].d = block->err_d;
                  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].max = block->err_cur;
                  Exx.E11 [block->idx].min = block->err_min;
                  Exx.E11 [block->idx].m = block->err_m;
                  Exx.E11 [block->idx].d = block->err_d;
                  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].max = block->err_cur;
                  Exx.E21 [block->idx].min = block->err_min;
                  Exx.E21 [block->idx].m = block->err_m;
                  Exx.E21 [block->idx].d = block->err_d;
                  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].max = block->err_cur;
                  Exx.E31 [block->idx].min = block->err_min;
                  Exx.E31 [block->idx].m = block->err_m;
                  Exx.E31 [block->idx].d = block->err_d;
                  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].max = block->err_cur;
                  Exx.E12 [block->idx].min = block->err_min;
                  Exx.E12 [block->idx].m = block->err_m;
                  Exx.E12 [block->idx].d = block->err_d;
                  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].max = block->err_cur;
                  Exx.E22 [block->idx].min = block->err_min;
                  Exx.E22 [block->idx].m = block->err_m;
                  Exx.E22 [block->idx].d = block->err_d;
                  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].max = block->err_cur;
                  Exx.E32 [block->idx].min = block->err_min;
                  Exx.E32 [block->idx].m = block->err_m;
                  Exx.E32 [block->idx].d = block->err_d;
                  Exx.tot[6] = block->err_total; Exx.max[6] = block->err_max; Exx.avg[6] = block->err_avg;
                  break;
      }
      if ((ext_cx_active) && (event_id == event_block_done_E32)) 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;
      unsigned int 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;
      unsigned int 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;
      int   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,c,y1,y2;
      for (i=0; i<(int)hres; i++) for (j=0; j<(int)vres; j++) result_rd->setPixel(i,j,0x00FFFFFF);
      for (i=0; i<min(res_cap, hres); i++) {
            y1 = RezRD[i]->startPoint().y(); if (y1>((int)vres-1)) y1=(int)vres-1; if (y1<0) y1=0;
            y2 = RezRD[i]->endPoint().y();   if (y2>((int)vres-1)) y2=(int)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,l;
      for (i=0; i<(int)hres; i++) for (j=0; j<(int)vres; j++) result_cx->setPixel(i,j,0x00FFFFFF);
      for (i=0; i<min(res_cap, hres); i++) {
            h = Rez_00[i]->startPoint().y();
            l = Rez_00[i]->endPoint().y();
            if (h>=vres) h=vres-1; if (h<1) h=1;
            if (l>=vres) l=vres-1; if (l<1) l=1;
            for (j=l ; j<h ; j++) result_cx->setPixel(i,j,color_BLERl);

            h = Rez_01[i]->startPoint().y();
            l = Rez_01[i]->endPoint().y();
            if (h>=vres) h=vres-1; if (h<1) h=1;
            if (l>=vres) l=vres-1; if (l<1) l=1;
            for (j=l ; j<h ; j++) result_cx->setPixel(i,j,color_BLER);
// ******************
            h = Rez_10[i]->startPoint().y();
            l = Rez_10[i]->endPoint().y();
            if (h>=vres) h=vres-1; if (h<1) h=1;
            if (l>=vres) l=vres-1; if (l<1) l=1;
            for (j=l ; j<h ; j++) result_cx->setPixel(i,j,color_E22l);

            h = Rez_11[i]->startPoint().y();
            l = Rez_11[i]->endPoint().y();
            if (h>=vres) h=vres-1; if (h<1) h=1;
            if (l>=vres) l=vres-1; if (l<1) l=1;
            for (j=l ; j<h ; j++) result_cx->setPixel(i,j,color_E22);
// ******************
            h = Rez_20[i]->startPoint().y();
            l = Rez_20[i]->endPoint().y();
            if (h>=vres) h=vres-1; if (h<1) h=1;
            if (l>=vres) l=vres-1; if (l<1) l=1;
            for (j=l ; j<h ; j++) result_cx->setPixel(i,j,color_E32l);

            h = Rez_21[i]->startPoint().y();
            l = Rez_21[i]->endPoint().y();
            if (h>=vres) h=vres-1; if (h<1) h=1;
            if (l>=vres) l=vres-1; if (l<1) l=1;
            for (j=l ; j<h ; j++) result_cx->setPixel(i,j,color_E32);
      }
      fill_res_cx_grid();
}

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

            max0 = arr[i].m + (int)sqrt(arr[i].d);
            min0 = arr[i].m - (int)sqrt(arr[i].d);
            if (max0>0) h=(int)(50*(float)log10(max0)+5); else h=1;
            if (min0>0) l=(int)(50*(float)log10(min0)+5); else l=1;
            if (h>=vres2) h=(vres2)-1; if (h<1) h=1;
            if (l>=vres2) l=(vres2)-1; if (l<1) l=1;
            for (j=vres2-l ; 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<min(res_cap, hres); 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<min(last_blk, hres/6); 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_hgrid(FILE *html)
{
      fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" width=\"600\"><tbody><tr>\n");
      if (drive->media.disc_type & DISC_CD) {
            fprintf(html,"\t\t\t\t<td align=\"left\"   width=\"5%%\"></td>\n");
            fprintf(html,"\t\t\t\t<td align=\"center\" width=\"10%%\">10</td>\n");
            fprintf(html,"\t\t\t\t<td align=\"center\" width=\"10%%\">20</td>\n");
            fprintf(html,"\t\t\t\t<td align=\"center\" width=\"10%%\">30</td>\n");
            fprintf(html,"\t\t\t\t<td align=\"center\" width=\"10%%\">40</td>\n");
            fprintf(html,"\t\t\t\t<td align=\"center\" width=\"10%%\">50</td>\n");
            fprintf(html,"\t\t\t\t<td align=\"center\" width=\"10%%\">60</td>\n");
            fprintf(html,"\t\t\t\t<td align=\"center\" width=\"10%%\">70</td>\n");
            fprintf(html,"\t\t\t\t<td align=\"center\" width=\"10%%\">80</td>\n");
            fprintf(html,"\t\t\t\t<td align=\"center\" width=\"10%%\">90</td>\n");
            fprintf(html,"\t\t\t\t<td align=\"right\"  width=\"5%%\">100</td>\n");
      } else {
            fprintf(html,"\t\t\t\t<td align=\"left\"   width=\"10%%\"></td>\n");
            fprintf(html,"\t\t\t\t<td align=\"center\" width=\"20%%\">%dG</td>\n",drive->media.layers+1);
            fprintf(html,"\t\t\t\t<td align=\"center\" width=\"20%%\">%dG</td>\n",(drive->media.layers+1)*2);
            fprintf(html,"\t\t\t\t<td align=\"center\" width=\"20%%\">%dG</td>\n",(drive->media.layers+1)*3);
            fprintf(html,"\t\t\t\t<td align=\"center\" width=\"20%%\">%dG</td>\n",(drive->media.layers+1)*4);
            fprintf(html,"\t\t\t\t<td align=\"right\"  width=\"10%%\">%dG</td>\n",(drive->media.layers+1)*5);
      }
      fprintf(html,"\t\t\t</tr></tbody></table><br>\n");
}

void QPxToolWidget::generate_result_html_ex_tbl1(FILE *html)
{
      fprintf(html,"\t<table border=\"0\" cellspacing=\"0\" width=\"682\" height=\"180\"><tbody>\n\t<tr>\n");
      fprintf(html,"\t\t<td align=\"right\"  width=\"6%%\">\n");
      fprintf(html,"\t\t<font size=\"-1\">\n");
      fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td>1000</td></tr></table>\n");
      fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"24\"><tr><td></td></tr></table>\n");
      fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"24\"><tr><td>100</td></tr></table>\n");
      fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"24\"><tr><td></td></tr></table>\n");
      fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"24\"><tr><td>10</td></tr></table>\n");
      fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"24\"><tr><td></td></tr></table>\n");
      fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td>1</td></tr></table>\n");
      fprintf(html,"\t\t</font>\n");
      fprintf(html,"\t\t</td>\n");
      fprintf(html,"\t\t<td align=\"center\"  width=\"88%%\">\n");
}

void QPxToolWidget::generate_result_html_ex_tbl2(FILE *html)
{
      fprintf(html,"\t\t</td>\n");
      fprintf(html,"\t\t<td align=\"right\"  width=\"6%%\"></td>\n");
      fprintf(html,"\t</tr>\n");
      fprintf(html,"\t<tr>\n");
      fprintf(html,"\t\t<td>\n\t\t</td>\n");
      fprintf(html,"\t\t<td>\n");
}

void QPxToolWidget::generate_result_html_ex_tbl3(FILE *html)
{
      fprintf(html,"\t\t</td>\n\t</tr>\n\t</tbody></table>\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\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\t</table><br>\n");
//  **************  Transfer Rate  **************
      if (tests & CHK_RD) {
            fprintf(html,"\t<br><b>Transfer rate</b><br><br>\n");
            fprintf(html,"\t<table border=\"0\" cellspacing=\"0\" width=\"660\" height=\"340\"><tbody>\n\t<tr>\n");
            fprintf(html,"\t\t<td align=\"right\"  width=\"6%%\">\n");

            if (drive->media.disc_type & DISC_CD) {
                  fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"45\"><tr><td>60x</td></tr></table>\n");
                  fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"50\"><tr><td>50x</td></tr></table>\n");
                  fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"50\"><tr><td>40x</td></tr></table>\n");
                  fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"50\"><tr><td>30x</td></tr></table>\n");
                  fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"50\"><tr><td>20x</td></tr></table>\n");
                  fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"50\"><tr><td>10x</td></tr></table>\n");
            } else {
                  fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"45\"><tr><td></td></tr></table>\n");
                  fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"50\"><tr><td>18x</td></tr></table>\n");
                  fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"50\"><tr><td>16x</td></tr></table>\n");
                  fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"50\"><tr><td>12x</td></tr></table>\n");
                  fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"50\"><tr><td>8x</td></tr></table>\n");
                  fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"50\"><tr><td>4x</td></tr></table>\n");
            }

            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"25\"><tr><td></td></tr></table>\n");
            fprintf(html,"\t\t\n</td>\n\t\t<td align=\"center\"  width=\"88%%\">");

            fprintf(html,"\t<IMG border=\"1\" src=\"%s\" alt=\"Transfer Rate\" height=\"320\" width=\"600\">\n",
                  png_name_rd.data());
            fprintf(html,"\t\t</td>\n");
            fprintf(html,"\t\t<td align=\"right\"  width=\"6%%\"></td>\n");
            fprintf(html,"\t</tr>\n");
            fprintf(html,"\t<tr>\n");
            fprintf(html,"\t\t<td>\n\t\t</td>\n");
            fprintf(html,"\t\t<td>\n");
            generate_result_html_hgrid(html);
            fprintf(html,"\t\t</td>\n");
            fprintf(html,"\t</tr>\n\t</tbody></table>\n");

            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><br><b>C1/C2/CU scan</b><br><br>\n");
            fprintf(html,"\t<table border=\"0\" cellspacing=\"0\" width=\"682\" height=\"340\"><tbody>\n\t<TR>\n");
            fprintf(html,"\t\t<td align=\"right\"  width=\"6%%\">\n");
            fprintf(html,"\t\t<font size=\"-1\">\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"24\"><tr><td>1000</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"75\"><tr><td></td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"24\"><tr><td>100</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"74\"><tr><td></td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"24\"><tr><td>10</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"75\"><tr><td></td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"24\"><tr><td>1</td></tr></table>\n");
            fprintf(html,"\t\t</font>\n");
            fprintf(html,"\t\t</td>\n");
            fprintf(html,"\t\t<td align=\"center\"  width=\"88%%\">\n");
            fprintf(html,"\t\t\t<IMG border=\"1\" src=\"%s\" alt=\"C1/C2/CU\" height=\"320\" width=\"600\">\n",
                  png_name_cx.data());
            fprintf(html,"\t\t</td>\n");
            fprintf(html,"\t\t<td align=\"right\"  width=\"6%%\"></td>\n");
            fprintf(html,"\t</tr>\n");
            fprintf(html,"\t<tr>\n");
            fprintf(html,"\t\t<td>\n\t\t</td>\n");
            fprintf(html,"\t\t<td>\n");

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

            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=#%06X>C1</font></td>", color_BLER);
            fprintf(html,"<td><font color=#%06X>C2</font></td>", color_E22);
            fprintf(html,"<td><font color=#%06X>CU</font></td></tr>\n", color_E32);
            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><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 width=\"9%%\"></td>\n");
                  fprintf(html,"\t\t\t<td width=\"13%%\"><font color=#%06X>BLER</font></td>\n", Exx.color[0]);
                  fprintf(html,"\t\t\t<td width=\"13%%\"><font color=#%06X>E11</font></td>\n", Exx.color[1]);
                  fprintf(html,"\t\t\t<td width=\"13%%\"><font color=#%06X>E21</font></td>\n", Exx.color[2]);
                  fprintf(html,"\t\t\t<td width=\"13%%\"><font color=#%06X>E31</font></td>\n", Exx.color[3]);
                  fprintf(html,"\t\t\t<td width=\"13%%\"><font color=#%06X>E12</font></td>\n", Exx.color[4]);
                  fprintf(html,"\t\t\t<td width=\"13%%\"><font color=#%06X>E22</font></td>\n", Exx.color[5]);
                  fprintf(html,"\t\t\t<td width=\"13%%\"><font color=#%06X>E32</font></td></tr>\n", Exx.color[6]);
// ******  Total:
                  fprintf(html,"\t\t<tr>\n\t\t\t<td>Total:</td>\n");
                  fprintf(html,"\t\t\t<td>%d</td>\n", Exx.tot[0]);
                  fprintf(html,"\t\t\t<td>%d</td>\n", Exx.tot[1]);
                  fprintf(html,"\t\t\t<td>%d</td>\n", Exx.tot[2]);
                  fprintf(html,"\t\t\t<td>%d</td>\n", Exx.tot[3]);
                  fprintf(html,"\t\t\t<td>%d</td>\n", Exx.tot[4]);
                  fprintf(html,"\t\t\t<td>%d</td>\n", Exx.tot[5]);
                  fprintf(html,"\t\t\t<td>%d</td>\n", Exx.tot[6]);
                  fprintf(html,"\t\t<tr>\n");
// ******  Maximum:
                  fprintf(html,"\t\t<tr>\n\t\t\t<td>Max:</td>\n");
                  fprintf(html,"\t\t\t<td>%d</td>\n", Exx.max[0]);
                  fprintf(html,"\t\t\t<td>%d</td>\n", Exx.max[1]);
                  fprintf(html,"\t\t\t<td>%d</td>\n", Exx.max[2]);
                  fprintf(html,"\t\t\t<td>%d</td>\n", Exx.max[3]);
                  fprintf(html,"\t\t\t<td>%d</td>\n", Exx.max[4]);
                  fprintf(html,"\t\t\t<td>%d</td>\n", Exx.max[5]);
                  fprintf(html,"\t\t\t<td>%d</td>\n", Exx.max[6]);
                  fprintf(html,"\t\t<tr>\n");
// ******  Average:
                  fprintf(html,"\t\t<tr>\n\t\t\t<td>Avg:</td>\n");
                  fprintf(html,"\t\t\t<td>%.2f</td>\n", Exx.avg[0]);
                  fprintf(html,"\t\t\t<td>%.2f</td>\n", Exx.avg[1]);
                  fprintf(html,"\t\t\t<td>%.2f</td>\n", Exx.avg[2]);
                  fprintf(html,"\t\t\t<td>%.2f</td>\n", Exx.avg[3]);
                  fprintf(html,"\t\t\t<td>%.2f</td>\n", Exx.avg[4]);
                  fprintf(html,"\t\t\t<td>%.2f</td>\n", Exx.avg[5]);
                  fprintf(html,"\t\t\t<td>%.2f</td>\n", Exx.avg[6]);
                  fprintf(html,"\t\t<tr>\n");

                  fprintf(html,"\t</tbody>\n\t</table>\n");
//  ******* BLER
                  fprintf(html,"\t<br>BLER<br>\n");
                  generate_result_html_ex_tbl1(html);
                  fprintf(html,"\t\t\t<IMG border=\"1\" src=\"%s\" alt=\"BLER\" height=\"160\" width=\"600\">\n",
                        png_name_BLER.data());
                  generate_result_html_ex_tbl2(html);
                  generate_result_html_hgrid(html);
                  generate_result_html_ex_tbl3(html);
//  ******* E11
                  fprintf(html,"\t<br>E11<br>\n");
                  generate_result_html_ex_tbl1(html);
                  fprintf(html,"\t<IMG border=\"1\" src=\"%s\" alt=\"E11\" height=\"160\" width=\"600\">\n",
                        png_name_E11.data());
                  generate_result_html_ex_tbl2(html);
                  generate_result_html_hgrid(html);
                  generate_result_html_ex_tbl3(html);
//  ******* E21
                  fprintf(html,"\t<br>E21<br>\n");
                  generate_result_html_ex_tbl1(html);
                  fprintf(html,"\t<IMG border=\"1\" src=\"%s\" alt=\"E21\" height=\"160\" width=\"600\">\n",
                        png_name_E21.data());
                  generate_result_html_ex_tbl2(html);
                  generate_result_html_hgrid(html);
                  generate_result_html_ex_tbl3(html);
//  ******* E31
                  fprintf(html,"\t<br>E31<br>\n");
                  generate_result_html_ex_tbl1(html);
                  fprintf(html,"\t<IMG border=\"1\" src=\"%s\" alt=\"E31\" height=\"160\" width=\"600\">\n",
                        png_name_E31.data());
                  generate_result_html_ex_tbl2(html);
                  generate_result_html_hgrid(html);
                  generate_result_html_ex_tbl3(html);
//  ******* E12
                  fprintf(html,"\t<br>E12<br>\n");
                  generate_result_html_ex_tbl1(html);
                  fprintf(html,"\t<IMG border=\"1\" src=\"%s\" alt=\"E12\" height=\"160\" width=\"600\">\n",
                        png_name_E12.data());
                  generate_result_html_ex_tbl2(html);
                  generate_result_html_hgrid(html);
                  generate_result_html_ex_tbl3(html);
//  ******* E22
                  fprintf(html,"\t<br>E22<br>\n");
                  generate_result_html_ex_tbl1(html);
                  fprintf(html,"\t<IMG border=\"1\" src=\"%s\" alt=\"E22\" height=\"160\" width=\"600\">\n",
                        png_name_E22.data());
                  generate_result_html_ex_tbl2(html);
                  generate_result_html_hgrid(html);
                  generate_result_html_ex_tbl3(html);
//  ******* E32
                  fprintf(html,"\t<br>E32<br>\n");
                  generate_result_html_ex_tbl1(html);
                  fprintf(html,"\t<IMG border=\"1\" src=\"%s\" alt=\"E32\" height=\"160\" width=\"600\">\n",
                        png_name_E32.data());
                  generate_result_html_ex_tbl2(html);
                  generate_result_html_hgrid(html);
                  generate_result_html_ex_tbl3(html);
            }
      }
      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<table border=\"0\" cellspacing=\"0\" width=\"682\" height=\"340\"><tbody>\n\t<TR>\n");
            fprintf(html,"\t\t<td align=\"right\"  width=\"6%%\">\n");
            fprintf(html,"\t\t<font size=\"-1\">\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"24\"><tr><td>1000</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"75\"><tr><td></td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"24\"><tr><td>100</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"74\"><tr><td></td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"24\"><tr><td>10</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"75\"><tr><td></td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"24\"><tr><td>1</td></tr></table>\n");
            fprintf(html,"\t\t</font>\n");
            fprintf(html,"\t\t</td>\n");
            fprintf(html,"\t\t<td align=\"center\"  width=\"88%%\">\n");
            fprintf(html,"\t<IMG border=\"1\" src=\"%s\" alt=\"PIE/PIF\" height=\"320\" width=\"600\">\n",
                  png_name_cx.data());
            fprintf(html,"\t\t</td>\n");
            fprintf(html,"\t\t<td align=\"right\"  width=\"6%%\"></td>\n");
            fprintf(html,"\t</tr>\n");
            fprintf(html,"\t<tr>\n");
            fprintf(html,"\t\t<td>\n\t\t</td>\n");
            fprintf(html,"\t\t<td>\n");
            generate_result_html_hgrid(html);
            fprintf(html,"\t\t</td>\n");
            fprintf(html,"\t</tr>\n");
            fprintf(html,"\t</tbody></table>\n");

            fprintf(html,"\t<table border=\"0\" cellspacing=\"0\" width=\"300\">\n");
            fprintf(html,"\t<tbody align=\"right\">\n");
            fprintf(html,"\t\t<tr>\n\t\t\t<td></td>\n");
            fprintf(html,"\t\t\t<td><font color=#%06X>PIE</font></td>\n", color_BLER);
            fprintf(html,"\t\t\t<td><font color=#%06X>PIF</font></td>\n", color_E22);
#ifdef __ENABLE_PX_POE
            if ((drive->ven_ID == WR_PLEXTOR ))
                  fprintf(html,"\t\t\t<td><font color=#%06X>POE</font></td>\n", color_POE);
#endif
            if (drive->chk_features & CHK_POF)
                  fprintf(html,"\t\t\t<td><font color=#%06X>POF</font></td>\n", color_E32);
            fprintf(html,"\t\t</tr>\n");
// *******  Total:
            fprintf(html,"\t\t<tr>\n\t\t\t<td>Total:</td>\n");
            fprintf(html,"\t\t\t<td>%s</td>\n", text_c1pie_total->text().data());
            fprintf(html,"\t\t\t<td>%s</td>\n", text_c2pif_total->text().data());
#ifdef __ENABLE_PX_POE
            if ((drive->ven_ID == WR_PLEXTOR ))
                  fprintf(html,"\t\t\t<td>%s</td>\n", text_poe_total->text().data());
#endif
            if (drive->chk_features & CHK_POF)
                  fprintf(html,"\t\t\t<td>%s</td>\n", text_cu_total->text().data());
            fprintf(html,"\t\t</tr>\n");
// *******  Maximum:
            fprintf(html,"\t\t<tr>\n\t\t\t<td>Max:</td>\n");
            fprintf(html,"\t\t\t<td>%s</td>\n", text_c1pie_max->text().data());
            fprintf(html,"\t\t\t<td>%s</td>\n", text_c2pif_max->text().data());
#ifdef __ENABLE_PX_POE
            if ((drive->ven_ID == WR_PLEXTOR ))
                  fprintf(html,"\t\t\t<td>%s</td>\n", text_poe_max->text().data());
#endif
            if (drive->chk_features & CHK_POF)
                  fprintf(html,"\t\t\t<td>%s</td>\n", text_cu_max->text().data());
            fprintf(html,"\t\t</tr>\n");
// *******  Average:
            fprintf(html,"\t\t<tr>\n\t\t\t<td>Avg:</td>\n");
            fprintf(html,"\t\t\t<td>%s</td>\n", text_c1pie_avg->text().data());
            fprintf(html,"\t\t\t<td>%s</td>\n", text_c2pif_avg->text().data());
#ifdef __ENABLE_PX_POE
            if ((drive->ven_ID == WR_PLEXTOR ))
                  fprintf(html,"\t\t\t<td>%s</td>\n", text_poe_avg->text().data());
#endif
            if (drive->chk_features & CHK_POF)
                  fprintf(html,"\t\t\t<td>%s</td>\n", text_cu_avg->text().data());
            fprintf(html,"\t\t</tr>\n");
            fprintf(html,"\t</tbody>\n\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<table border=\"0\" cellspacing=\"0\" width=\"682\" height=\"340\"><tbody>\n\t<tr>\n");

            fprintf(html,"\t\t<td align=\"right\"  width=\"6%%\">\n");
            fprintf(html,"\t\t<font size=\"-1\" color=#%06X>\n", color_beta);
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"10\"><tr><td></td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td>+7%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td>+6%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td>+5%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td>+4%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td>+3%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td>+2%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td>+1%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td> 0%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td>-1%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td>-2%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td>-3%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td>-4%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td>-5%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td>-6%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td>-7%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"10\"><tr><td></td></tr></table>\n");
            fprintf(html,"\t\t</font>\n");
            fprintf(html,"\t\t</td>\n");

            fprintf(html,"\t\t<td align=\"center\"  width=\"88%%\">\n");
            fprintf(html,"\t\t\t<IMG border=\"1\" src=\"%s\" alt=\"Jitter/Beta\" height=\"320\" width=\"600\">\n",
                  png_name_jb.data());
            fprintf(html,"\t\t</td>\n");

            fprintf(html,"\t\t<td align=\"left\"  width=\"6%%\">\n");
            fprintf(html,"\t\t<font size=\"-1\" color=#%06X>\n", color_jitter);
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"10\"><tr><td></td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td>15%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td>14%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td>13%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td>12%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td>11%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td>10%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td> 9%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td> 8%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td> 7%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td> 6%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td> 5%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td> 4%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td> 3%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td> 2%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"20\"><tr><td> 1%%</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"10\"><tr><td></td></tr></table>\n");
            fprintf(html,"\t\t</font>\n");
            fprintf(html,"\t\t</td>\n");


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


            fprintf(html,"\t<table border=\"0\" cellspacing=\"0\" width=\"300\">\n");
            fprintf(html,"\t<tbody align=\"right\">\n");
            fprintf(html,"\t\t<tr>\n");
            fprintf(html,"\t\t\t<td  width=\"40%%\"></td>\n");
            fprintf(html,"\t\t\t<td width=\"30%%\"><font color=#%06X>Jitter</font></td>\n", color_jitter);
            fprintf(html,"\t\t\t<td width=\"30%%\"><font color=#%06X>Beta</font></td>\n",  color_beta);
            fprintf(html,"\t\t</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\t</table>\n");
      }
//  **************  FE/TE  **************
      if (tests & CHK_FETE) {
            fprintf(html,"\t<br><b>Focus/Tracking errors</b><br>\n");

            fprintf(html,"\t<table border=\"0\" cellspacing=\"0\" width=\"682\" height=\"340\"><tbody>\n\t<tr>\n");
            fprintf(html,"\t\t<td align=\"right\"  width=\"6%%\">\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"45\"><tr><td>60</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"50\"><tr><td>50</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"50\"><tr><td>40</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"50\"><tr><td>30</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"50\"><tr><td>20</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"50\"><tr><td>10</td></tr></table>\n");
            fprintf(html,"\t\t\t<table border=\"0\" cellspacing=\"0\" height=\"25\"><tr><td></td></tr></table>\n");
            fprintf(html,"\t\t</td>\n\t\t<td align=\"center\"  width=\"88%%\">\n");
            fprintf(html,"\t\t\t<IMG border=\"1\" src=\"%s\" alt=\"FE/TE\" height=\"320\" width=\"600\">\n",
                  png_name_ft.data());
            fprintf(html,"\t\t</td>");
            fprintf(html,"\t\t<td align=\"right\"  width=\"6%%\"></td>\n");
            fprintf(html,"\n\t</tr>");
            fprintf(html,"\n\t<tr>");
            fprintf(html,"\n\t\t<td></td>");
            fprintf(html,"\n\t\t<td>\n");
            generate_result_html_hgrid(html);
            fprintf(html,"\t\t</td>\n\t</tr>\n\t</tbody></table>\n");

            fprintf(html,"\t<table border=\"0\" cellspacing=\"0\" width=\"300\">\n");
            fprintf(html,"\t<tbody align=\"right\">\n");
            fprintf(html,"\t\t<tr><td width=\"40%%\"></td>");
            fprintf(html,"<td width=\"30%%\"><font color=#%06X>Tracking</font></td>",color_TE);
            fprintf(html,"<td width=\"30%%\"><font color=#%06X>Focus</font></td></tr>\n", color_FE);
            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\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 w/o suf : '%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::media_changed(int didx, bool insert)
{
      select_device();
      clear_all();
}

void QPxToolWidget::stateCol_reset()
{
      status_current_test->setPaletteForegroundColor(QColor(0x00,0x00,0x00));
      stateCol = 0;
//          color.setHsv( stateCol << 3, 0x80, 0x80 );
//          status_current_test->setPaletteForegroundColor(color);
}

void QPxToolWidget::stateCol_toggle()
{
      QColor color;
      if (!stateCol) {
            stateCol = 0x0F;
            color.setHsv( stateCol << 4, 0xE0, 0x80 );
            status_current_test->setPaletteForegroundColor(color);
      } else {
            stateCol--;
            color.setHsv( stateCol << 4, 0xE0, 0x80 );
            status_current_test->setPaletteForegroundColor(color);
      }
}

void QPxToolWidget::end_tests()
{
      if (thread_time->running()) thread_time->terminate();
      thread_time->wait();

      stateCol_reset();
      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_1sec:
                  stateCol_toggle();
                  break;
            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_poe:
//                block_done_poe((block_data*)event->data());
                  printf("POE plot not implemented yet:(\n");
                  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;

            case event_media_new:
                  media_changed(*(int*)event->data(), true);
                  break;
            case event_media_removed:
                  media_changed(*(int*)event->data(), false);
                  break;
            default:
                  break;
      }
}

void QPxToolWidget::quit()
{
      int i=0,j=0;      
      abort_tests();
      printf("\n** Waiting for scan thread to end...\n");
//    if (thread->running()) thread->terminate();
      thread->wait();
      if (thread_time->running()) thread_time->terminate();
      thread_time->wait();
      if (watcher->running()) watcher->terminate();
      watcher->wait();
      delete watcher;
      printf("\n** Destroying dynamic objects...\n");
// Destroying results
      printf("**   Destroying results...\n");
      for (i=0; i<hres; i++) {
            delete RezRD[i];
            delete Rez_00[i]; delete Rez_01[i];
            delete Rez_10[i]; delete Rez_11[i];
            delete Rez_20[i]; delete Rez_21[i];
            delete RezJ[i]; delete RezB[i];
      }
      delete RezRD;
      delete Rez_00; delete Rez_01;
      delete Rez_10; delete Rez_11;
      delete Rez_20; delete Rez_21;
      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<(int)grids_RD;i++) delete GridRD[i];
      delete GridRD;
      for (i=0;i<(int)grids_CX;i++) delete Grid0[i];
      delete Grid0;
      for (i=0;i<(int)grids_JB;i++) delete GridJB[i];
      delete GridJB;
      for (i=0;i<(int)grids_FT;i++) delete GridFT[i];
      delete GridFT;
      for (i=0;i<(int)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