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

burn_iso_2_dvd.cpp

//This file is part of AcetoneISO. Copyright 2006,2007,2008,2009 Marco Di Antonio and Fabrizio Di Marco (acetoneiso@gmail.com)
//Copyright 2010/2011 Marco Di Antonio

//    AcetoneISO 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 3 of the License, or
//    (at your option) any later version.
//
//    AcetoneISO is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with AcetoneISO.  If not, see <http://www.gnu.org/licenses/>.
#include <QtGui>
#include <QByteArray>
#include <QProcess>
#include <QDBusConnection>
#include <QDBusInterface>
#include <QDBusMessage>
#include <QList>
#include <QVariant>
#include <fcntl.h>
#include <iostream>
#include <QDebug>
#include <Phonon/MediaObject>
#include <Phonon/AudioOutput>
#include "burn_iso_2_dvd.h"



//
burniso2dvd::burniso2dvd( QWidget * parent, Qt::WFlags f) 
      : QDialog(parent, f)
{

    setupUi(this);
    is_erasing = false;
    loaded_success = false;
    QCoreApplication::setApplicationName("AcetoneISO");
    connect( start, SIGNAL( clicked() ), this, SLOT( start_erase() ) );
    connect( push_select_image, SIGNAL( clicked() ), this, SLOT( select_image() ) );

    textBrowser->clear();
    
    //database speed for dvd
    hash_speed[0] = "2";
    hash_speed[1] = "2";
    hash_speed[2] = "2";
    hash_speed[3] = "2";
    hash_speed[4] = "4";
    hash_speed[5] = "4";
    hash_speed[6] = "4";
    hash_speed[7] = "6";
    hash_speed[8] = "6";
    hash_speed[9] = "6";
    hash_speed[10] = "8";
    hash_speed[11] = "8";
    hash_speed[12] = "8";
    hash_speed[13] = "10";
    hash_speed[14] = "10";
    hash_speed[15] = "12";    
    hash_speed[16] = "12";
    hash_speed[17] = "16";
    
    itemRemovedSpeed = 0;
    
    device_scan();
   

}


void burniso2dvd::device_scan() {


/*creo la connessione dbus a hal*/
QDBusConnection conn = QDBusConnection::systemBus();
QDBusInterface hal("org.freedesktop.Hal", "/org/freedesktop/Hal/Manager", "org.freedesktop.Hal.Manager", conn);
/*cerco tutti i dispositivi storage.cdrom con hal via dbus*/
QDBusMessage msg = hal.call( "FindDeviceByCapability", "storage.cdrom");

QList<QVariant> devices = msg.arguments(); 
/*per ogni udi (dispositivo cdrom) che trovo, ricavo vendor, model, velocitĂ  e path*/

//disabilita tutto se non viene trovato almeno 1 periferica
int count = devices.count();
if (count < 1) {
 QMessageBox::warning(this, "AcetoneISO::warning", tr("No CD/DVD device found.\nIf you think this is a bug please report it."));
 disable_buttons();
 devices_combo->addItem( tr("No CD/DVD device found") );
 return;
}


QIcon icon_optical_drive( ":/images/drive-optical.png" );

//scannerizzo tutte le periferiche e le aggiungo nella combobox. questa funzione viene chiamato una sola volta.
QVariant name(devices);
int cc = 0;
int success = -1;
while (cc < count) {
              QString cdrom = name.toStringList()[0]; 
              if (cdrom.isEmpty()) {
                QMessageBox::warning(this, "AcetoneISO::warning", tr("No CD/DVD device found.\nIf you think this is a bug please report it."));
                disable_buttons();
                devices_combo->addItem( tr("No CD/DVD device found") );
                return; 
              }
             // qDebug() << "Found device: " << cdrom; 
              QDBusInterface device("org.freedesktop.Hal", cdrom, "org.freedesktop.Hal.Device", conn);
              
              //vedo se effittivamente il device puo scrivere su dischi dvd-rw
//controllo in seguito se puo scrivere su dvd+rw dal momento che se puo scrivere su dvd+rw puo anche farlo su dvd-rw ma questo ragionamento non funziona al contrario
              msg = device.call("GetProperty", "storage.cdrom.dvdrw");
              QVariant vcan_write_cdrw = msg.arguments()[0];
              bool can_write_cdrw = vcan_write_cdrw.toBool();
              if (!can_write_cdrw) {
                cc = cc + 1;
                continue;
              }
              //success si ricorda sempre la posizione in cui aggiungere all'array indipendentemente dal cc del ciclo while
              success = success + 1;
              //aggiungo id nell'array
              id_device.insert(success, cdrom);         
              /*ottengo il nome del vendor del cdrom*/
              msg = device.call("GetProperty", "storage.vendor");
              QVariant var = msg.arguments()[0]; 
              QString vendor = var.toStringList()[0];
              //qDebug() << "VENDOR" << vendor;
              /*ottengo il nome del modello del cdrom*/
              msg = device.call("GetProperty", "storage.model");
              QVariant var2 = msg.arguments()[0]; 
              QString model = var2.toStringList()[0];
             // qDebug() << "MODEL" << model;

              /*ottengo il path del dispositivo cdrom*/
              msg = device.call("GetProperty", "block.device");
              QVariant var3 = msg.arguments()[0]; 
              device_path.insert(success, var3.toStringList()[0]);
             // qDebug() << "PATH" << device_path;
              
              msg = device.call("GetProperty", "storage.firmware_version");
              QVariant firmwarev = msg.arguments()[0];
              QString firmware = firmwarev.toString();
               /*aggiungo il nome del device nella combobox*/
              QString final_device = vendor.append( "\t" + model + " " + firmware );
              devices_combo->insertItem(success,icon_optical_drive, " " + final_device );
              
              cc = cc + 1;
              }

media_available();
//if < 1 significa che sebbene ci sono 1 o piu periferiche cdrom, nessuna e' capace di scrivere su cd-rw
if (devices_combo->count() < 1) {
  disable_buttons();
  QMessageBox::warning(this, "AcetoneISO::warning", tr("No CD/DVD device found capable of writing to DVD-RW discs.\nIf you think this is a bug please report it."));
  return; 
}
else { //c'e' almeno 1 periferica cdrom in grado di scrivere su dischi cd-rw
  loaded_success = true;
  //crea un timer cosi aggiorna automaticamente la label_info
  timer = new QTimer(this);
  connect(timer, SIGNAL(timeout()), this, SLOT(media_available()));
  timer->start(2000);
  connect( devices_combo, SIGNAL(currentIndexChanged(int) ), this , SLOT( combo_changed(int) ) ); 
}

}


void burniso2dvd::media_available() {
//qDebug() << "media_available()";
//se sto masterizzando deve uscire da qui
if (is_erasing) {
  start->setEnabled(false);
  label_info->setText(tr("AcetoneISO is burning your image to the") + " " + discotipo + "..." );
  return;
}

//if < 1 it means there are no devices capaci di scrivere su dischi cd-rw
if (devices_combo->count() < 1) {
  clean_combobox_speed();
  return; 
}

//se non e' visibile deve disconnettere le connessioni
if (loaded_success) {
  if (!devices_combo->isVisible()) {
    disconnect(devices_combo, 0, 0, 0);
    disconnect(timer, 0, 0, 0);
    loaded_success = false;
  }
}

estimated_time() ;

//scopro se ho un cd dentro il device
/*creo la connessione dbus a hal*/
QDBusConnection conn = QDBusConnection::systemBus();
QDBusMessage msg;
//prendo indice corrente della combobox cosi so chi l'id della periferica selezionata
int current_index = devices_combo->currentIndex();
QString id = id_device[current_index];

//mi connetto alla periferica corrente selezionata in combobox
QDBusInterface device("org.freedesktop.Hal", id, "org.freedesktop.Hal.Device", conn);
//vedo se e' inserito un cd 
msg = device.call("GetProperty", "storage.removable.media_available");
QVariant var5 = msg.arguments()[0];
bool opticDev = var5.toBool();
QString plusminus = QString::fromUtf8("\xC2\xB1"); //0xC2 0xB1
if (!opticDev) {
  label_info->setText(tr("Insert a DVD") + plusminus + "R/RW " + tr("disc.")  );
  start->setEnabled(false);
  clean_combobox_speed();
  //devices_combo->setItemText(cc,tr("No Media Inserted, insert a media and click on refresh button."));
  return;
}

//vedo il tipo di cd inserito
QDBusMessage fbp;
QDBusInterface newh("org.freedesktop.Hal", "/org/freedesktop/Hal/Manager", "org.freedesktop.Hal.Manager", conn);
fbp = newh.call("FindDeviceStringMatch", "info.parent", id);
QList<QVariant> var6 = fbp.arguments();
QString disc_type = var6.at(0).toString();
QDBusInterface device_type("org.freedesktop.Hal", disc_type, "org.freedesktop.Hal.Device", conn);
msg = device_type.call("GetProperty", "volume.disc.type");
QString var7 = msg.arguments()[0].toString();
QString disc_is = var7;
//ferma in caso che il disco inserito non sia un disco DVD±R/RW
QStringList dvd_type;
dvd_type << "dvd_rw" <<   "dvd_plus_rw" << "dvd_r" << "dvd_plus_r" << "dvd_r_dl" << "dvd_plus_r_dl" << "dvd_plus_rw_dl";

    if (!dvd_type.contains(disc_is) ) {
      label_info->setText(tr("The disc isn't a DVD") + plusminus + "R/RW. " +tr("Please insert a DVD") + plusminus + "R/RW " + tr("disc."));   
      clean_combobox_speed();
      return;
    }

 
  dvdHash["dvd_rw"] = "DVD-RW";
  dvdHash["dvd_plus_rw"] = "DVD+RW"; 
  dvdHash["dvd_r"] = "DVD-R";
  dvdHash["dvd_plus_r"] = "DVD+R";
  dvdHash["dvd_r_dl"] = "DVD-R DL";  
  dvdHash["dvd_plus_r_dl"] = "DVD+R DL";   
  dvdHash["dvd_plus_rw_dl"] = "DVD+RW DL";
  
  dvdHashStoragetype["dvd_rw"] = "dvdrw";
  dvdHashStoragetype["dvd_plus_rw"] = "dvdplusrw"; 
  dvdHashStoragetype["dvd_r"] = "dvdr";
  dvdHashStoragetype["dvd_plus_r"] = "dvdplusr";
  dvdHashStoragetype["dvd_r_dl"] = "dvdrdl";  
  dvdHashStoragetype["dvd_plus_r_dl"] = "dvdplusrdl";   
  dvdHashStoragetype["dvd_plus_rw_dl"] = "dvdplusrwdl";

  discotipo = dvdHash[disc_is];

  msg = device_type.call("GetProperty", "volume.disc.is_blank");
  bool disc_blank = msg.arguments()[0].toBool();
  //if disc is not empty and is NOT a rw disc
  if (!disc_blank and !disc_is.contains("rw", Qt::CaseInsensitive)  ) {
    label_info->setText( tr("You inserted a ") + dvdHash[disc_is] + tr(" that is not Empty. Please put an empty DVD") + plusminus + "R/RW " + tr("disc.")  ); 
    start->setEnabled(false); 
    clean_combobox_speed();
    return;
  }
  
  
  msg = device.call("GetProperty", "storage.cdrom." + dvdHashStoragetype[disc_is] );
  QVariant vcan_write_cdrw = msg.arguments()[0];
  bool discobool = vcan_write_cdrw.toBool();
  if (!discobool) {
    label_info->setText( tr("You inserted a ") + discotipo + tr(" disc, however your CD/DVD device is uncapable of writing to such discs.") ); 
    start->setEnabled(false); 
    clean_combobox_speed();
    return;
  }

//check and set combobox speed
  msg = device.call("GetProperty", "storage.cdrom.write_speeds");
  QVariant vspeed = msg.arguments()[0];
  QStringList slist = vspeed.toStringList();
  int count_speed = slist.count();
  int count_combobox = (combo_speed->count() ) + itemRemovedSpeed;
  //fill speed array only one 1 time, occurs again when media changes
  if ( count_speed != count_combobox ) {
    clean_combobox_speed();
    int count_cycle = 0;
    while (count_cycle < count_speed) {
      QString string_speed = slist[count_cycle];
      qreal q_speed = string_speed.toFloat() / 1024 ;
      int int_speed = qRound(q_speed);
      if (int_speed > 17) {
      int_speed = 16; //any speed above 17 force to speed 16x
      }
      string_speed = hash_speed[int_speed] + "x";
      //qDebug() <<  string_speed;
      arraySpeed << string_speed; //put speed in array
      count_cycle++;
    }
  
    //remove duplicate speeds from array and fill combobox speed
    itemRemovedSpeed = arraySpeed.removeDuplicates();
    int countArraySpeed = arraySpeed.count();
    int abc = 0;
    while (abc < countArraySpeed) {
      combo_speed->insertItem(abc, arraySpeed[abc] );
      abc = abc + 1;
    }
    
  }
  
  push_select_image->setEnabled(true);
  label_4->setEnabled(true);
  iso_to_burn_label->setEnabled(true);
  
  discIsNotEmptyAndRWType = "false";
  //if disc is not empty and IS a rw disc
  if (!disc_blank and disc_is.contains("rw", Qt::CaseInsensitive)  ) {
    label_info->setText( tr("You inserted a ") + dvdHash[disc_is] + tr(" that is not Empty. If you continue, AcetoneISO will overwrite your disc!") );
    discIsNotEmptyAndRWType = "true";
  }
  else {
    label_info->setText(discotipo + " " + tr("succesfully found in device."));
  }

}

//cleans combobox speed when something changed, example: user put new cd, changes drive, removes cd
void burniso2dvd::clean_combobox_speed() {
  combo_speed->setEnabled(false);
  int count_combobox = combo_speed->count();
  int count_cycle = 0;
  while (count_cycle < count_combobox) {
    combo_speed->removeItem(count_cycle);
    count_cycle++;
  }
  combo_speed->setEnabled(true);
  
  //reset array speed
  arraySpeed.clear();
  //reset number items removed if duplicates speeds found
  itemRemovedSpeed= 0; 
}




//gestisce quando l'utente cambia periferica nella combobox
void burniso2dvd::combo_changed(int n) {
  int a;
  a = n;
  clean_combobox_speed();
  media_available(); 
}

//user wants to choose which image to burn
void burniso2dvd::select_image() {
  QDir Home = QDir::home();// entro nella home dell'utente
  QString isoToBurnDialog;
  isoToBurnDialog = QFileDialog::getOpenFileName(this,tr("Select ISO Image to Burn"), Home.path() , tr("ISO Image Files (*.iso)"));
  if ( isoToBurnDialog.isNull() )  {
    return;   
  }
  QFileInfo isoInfo(isoToBurnDialog);
  isoToBurnDialog = isoInfo.absoluteFilePath();
  imageToBurn = isoToBurnDialog;

  //image type?
  QStringList checkSupported;
  checkSupported << "iso";
  QString imageType = (isoInfo.suffix()).toLower();
  if (!checkSupported.contains(imageType) ) {
    QMessageBox::warning(this, "AcetoneISO::File Unsupported",tr("The Image you selected is unsupported from AcetoneISO."));
    start->setEnabled(false);
    return;   
  }
  
  
  QFile fileExists(imageToBurn);
  if (!fileExists.exists()) {
     QMessageBox::warning(this, "AcetoneISO::File Not Found",tr("The Image you selected does not exist."));
     start->setEnabled(false);
     return;
  }
  
  
  iso_to_burn_label->setText(imageToBurn);
}

//estimates time to burn image based on speed
void burniso2dvd::estimated_time() {
  int count_combobox = combo_speed->count();
  if (count_combobox < 1) {
    estimated_label->setText("");
    push_select_image->setEnabled(false);
    label_4->setEnabled(false);
    iso_to_burn_label->setEnabled(false);
    start->setEnabled(false);
    return; 
  }
  imageToBurn = iso_to_burn_label->text();
  QFile fileExists(imageToBurn);
  if (!fileExists.exists()) {
     start->setEnabled(false);
     return;
  }
  start->setEnabled(true);
  QFileInfo isoInfo(imageToBurn);
  QString fileName = isoInfo.fileName();

  //estimated time: size / writing speed
  qint64 imageSize = (isoInfo.size() / 1024) / 1024;
  QString current_speed = combo_speed->currentText();
  current_speed = ( current_speed.split("x"))[0]  ;

  int key_hash = hash_speed.key(current_speed);
  if (key_hash < 1) {
   key_hash = 1; 
  }
  current_speed = QString::number(key_hash);
  
  float f_final_time = imageSize / current_speed.toFloat() + 16;
  int final_time = qRound(f_final_time);
  QString seconds_or_minutes;
  if ( f_final_time < 60) {
      seconds_or_minutes =  QString::number(final_time) + tr(" seconds");
  }
  else {
      f_final_time = f_final_time / 60;
      final_time = qRound(f_final_time);
      seconds_or_minutes = QString::number(final_time) + tr(" minutes");
  }
  
  estimated_label->setText( tr("Estimated time to burn ") + fileName + ": " +  seconds_or_minutes  ); 
}



void burniso2dvd::start_erase() {
  
  QString type = discotipo;
  QMessageBox msgBox;
  QString question = "";
  if (discIsNotEmptyAndRWType == "true") {
    question = tr("You decided to burn the image on the") + " " + discotipo + tr(".\nThe disc is NOT empty so if you continue,\nAcetoneISO will overwrite all your data.\nAre you sure?");
  }
  else {
    question = tr("You decided to burn the image on the") + " " + discotipo + tr("\nAre you sure?");
  }
  discIsNotEmptyAndRWType = "false";
  
  msgBox.setText( question );
  msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
  switch (msgBox.exec()) {
  case QMessageBox::Yes:
    {
      //continue below
     }
     break;
  case QMessageBox::No:
  {
    return; //exit
  }
     break;
  default:
     // should never be reached
     break;
 }

  disable_buttons();
  QString dev = device_path.at(devices_combo->currentIndex());

  //dev = dev.prepend("dev=");
  textBrowser->clear(); 
  erase = new QProcess();
  erase->setReadChannel(QProcess::StandardOutput);
  erase->setProcessChannelMode(QProcess::MergedChannels);   
  //connection to update the display
  connect(erase, SIGNAL(readyReadStandardOutput()), SLOT(updateEraseDisplay() )); 
  connect(erase, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(printOutErase(int, QProcess::ExitStatus)));
  QDir bin("/usr/bin");
  QDir::setCurrent( bin.absolutePath() );
  is_erasing = true;

  //growisofs -dvd-compat -speed=N -Z /dev/dvd=image.iso
  QString current_speed = combo_speed->currentText();
  current_speed = ( current_speed.split("x"))[0];
  dev = dev.append("=\"" + imageToBurn + "\"");
  QString grow = "growisofs -dvd-compat -speed=" + current_speed + "  -Z " + dev;

  //qDebug() << grow;
  erase->start(grow );

  
  
}

//fa loutput nel display del processo wodim
void burniso2dvd::updateEraseDisplay() {
  erase_output = erase->readAllStandardOutput(); 
  //questo evita che prende un output vuoto
  if (erase_output.size() > 2 ) {
    eraseoutput_real = erase_output; //questo si ricorda sempre dell'ultimo output NON vuoto
    textBrowser->setPlainText(erase_output);
  }
  else {
    textBrowser->setPlainText(eraseoutput_real); 
  }
}

//gestisce quando il processo dvd+rw-format finisce
void burniso2dvd::printOutErase(int, QProcess::ExitStatus) {
  
  iso_to_burn_label->setText("");
  
  enable_buttons();
  is_erasing = false;

  int valore_uscita = erase->exitCode();
  if(valore_uscita == 0) {
    if (playcheckbox->isChecked()) {
      play_success();
    }
    QMessageBox::information(this, "AcetoneISO",tr("Process Succesfully Finished!"));
    textBrowser->clear();
    QWidget::close ();
  }
  else {
    if (playcheckbox->isChecked()) {
      play_error();
    }
    QMessageBox::critical(this, "AcetoneISO","Process Error Code: " + QString::number(valore_uscita) );
  }
  
}

//abilita i bottoni
void burniso2dvd::enable_buttons() { 
  start->setEnabled(true);
  devices_combo->setEnabled(true);
  playcheckbox->setEnabled(true);
  combo_speed->setEnabled(true);
  push_select_image->setEnabled(true);
}
//disabilita i bottoni
void burniso2dvd::disable_buttons() {
  start->setEnabled(false);
  devices_combo->setEnabled(false);
  playcheckbox->setEnabled(false);
  combo_speed->setEnabled(false);
  push_select_image->setEnabled(false);
}


void burniso2dvd::play_success() {
  Phonon::MediaObject *mediaObject; 
  Phonon::AudioOutput *audioOutput; 
  Phonon::Path path;
  mediaObject = new Phonon::MediaObject();
  audioOutput = new Phonon::AudioOutput(Phonon::NoCategory);
  path = Phonon::createPath(mediaObject, audioOutput);
  QString file(":/audio/success.ogg");
  mediaObject->setCurrentSource(Phonon::MediaSource(file));
mediaObject->play();
}

void burniso2dvd::play_error() {
  Phonon::MediaObject *mediaObject; 
  Phonon::AudioOutput *audioOutput; 
  Phonon::Path path;
  mediaObject = new Phonon::MediaObject();
  audioOutput = new Phonon::AudioOutput(Phonon::NoCategory);
  path = Phonon::createPath(mediaObject, audioOutput);
  QString file(":/audio/error.ogg");
  mediaObject->setCurrentSource(Phonon::MediaSource(file));
  mediaObject->play();
}



Generated by  Doxygen 1.6.0   Back to index