RecordDialog.cc
上传用户:weiliju62
上传日期:2007-01-06
资源大小:619k
文件大小:13k
源码类别:

SCSI/ASPI

开发平台:

MultiPlatform

  1. /*  cdrdao - write audio CD-Rs in disc-at-once mode
  2.  *
  3.  *  Copyright (C) 1998, 1999  Andreas Mueller <mueller@daneb.ping.de>
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19. /*
  20.  * $Log: RecordDialog.cc,v $
  21.  * Revision 1.1  1999/09/07 11:16:16  mueller
  22.  * Initial revision
  23.  *
  24.  */
  25. static char rcsid[] = "$Id: RecordDialog.cc,v 1.1 1999/09/07 11:16:16 mueller Exp mueller $";
  26. #include <stdio.h>
  27. #include <limits.h>
  28. #include <math.h>
  29. #include <assert.h>
  30. #include "RecordDialog.h"
  31. #include "MessageBox.h"
  32. #include "xcdrdao.h"
  33. #include "Settings.h"
  34. #include "CdDevice.h"
  35. #include "guiUpdate.h"
  36. #include "TocEdit.h"
  37. #include "util.h"
  38. #define MAX_SPEED_ID 5
  39. static RecordDialog::SpeedTable SPEED_TABLE[MAX_SPEED_ID + 1] = {
  40.   { 0, "Max" },
  41.   { 1, "1x" },
  42.   { 2, "2x" },
  43.   { 4, "4x" },
  44.   { 6, "6x" },
  45.   { 8, "8x" }
  46. };
  47. RecordDialog::RecordDialog()
  48. {
  49.   int i;
  50.   Gtk_HBox *hbox;
  51.   Gtk_VBox *vbox;
  52.   Gtk_Table *table;
  53.   Gtk_Label *label;
  54.   active_ = 0;
  55.   tocEdit_ = NULL;
  56.   set_title(string("Record"));
  57.   set_usize(0, 300);
  58.   speedMenuFactory_ = new Gtk_ItemFactory_Menu("<Main>");
  59.   for (i = 0; i <= MAX_SPEED_ID; i++) {
  60.     string s("/");
  61.     s += SPEED_TABLE[i].name;
  62.     speedMenuFactory_->create_item(s, 0, "<Item>", ItemFactoryConnector<RecordDialog, int>(this, &RecordDialog::setSpeed, i));
  63.   }
  64.   speedMenu_ = new Gtk_OptionMenu;
  65.   speedMenu_->set_menu(speedMenuFactory_->get_menu_widget(string("")));
  66.   speed_ = 0;
  67.   speedMenu_->set_history(speed_);
  68.   startButton_ = new Gtk_Button(string(" Start "));
  69.   simulateButton_ = new Gtk_RadioButton(NULL, string("Simulate"));
  70.   writeButton_ = new Gtk_RadioButton(simulateButton_->group(),
  71.      string("Write"));
  72.   
  73.   closeSessionButton_ = new Gtk_CheckButton(string("Close Disk"));
  74.   closeSessionButton_->set_active(true);
  75.   ejectButton_ = new Gtk_CheckButton(string("Eject"));
  76.   ejectButton_->set_active(false);
  77.   reloadButton_ = new Gtk_CheckButton(string("Reload"));
  78.   reloadButton_->set_active(false);
  79.   list_ = new Gtk_CList(6);
  80.   list_->set_column_title(0, string("Bus"));
  81.   list_->set_column_justification(0, GTK_JUSTIFY_CENTER);
  82.   list_->set_column_title(1, string("Id"));
  83.   list_->set_column_justification(1, GTK_JUSTIFY_CENTER);
  84.   list_->set_column_title(2, string("Lun"));
  85.   list_->set_column_justification(2, GTK_JUSTIFY_CENTER);
  86.   list_->set_column_title(3, string("Vendor"));
  87.   list_->set_column_justification(3, GTK_JUSTIFY_LEFT);
  88.   list_->set_column_title(4, string("Model"));
  89.   list_->set_column_justification(4, GTK_JUSTIFY_LEFT);
  90.   list_->set_column_title(5, string("Status"));
  91.   list_->set_column_justification(5, GTK_JUSTIFY_LEFT);
  92.   list_->column_titles_show();
  93.   list_->column_titles_passive();
  94.   list_->set_selection_mode(GTK_SELECTION_MULTIPLE);
  95.   Gtk_VBox *contents = new Gtk_VBox;
  96.   contents->set_spacing(10);
  97.   // available device list
  98.   Gtk_HBox *listHBox = new Gtk_HBox;
  99.   Gtk_VBox *listVBox = new Gtk_VBox;
  100.   hbox = new Gtk_HBox;
  101.   hbox->pack_start(*list_, TRUE, TRUE);
  102.   list_->show();
  103.   Gtk_Adjustment *adjust = new Gtk_Adjustment(0.0, 0.0, 0.0);
  104.   Gtk_VScrollbar *scrollBar = new Gtk_VScrollbar(*adjust);
  105.   hbox->pack_start(*scrollBar, FALSE, FALSE);
  106.   scrollBar->show();
  107.   list_->set_vadjustment(*adjust);
  108.   listHBox->pack_start(*hbox, TRUE, TRUE, 5);
  109.   hbox->show();
  110.   listVBox->pack_start(*listHBox, TRUE, TRUE, 5);
  111.   listHBox->show();
  112.   Gtk_Frame *listFrame = new Gtk_Frame(string("Available Recorder Devices"));
  113.   listFrame->add(*listVBox);
  114.   listVBox->show();
  115.   contents->pack_start(*listFrame, TRUE, TRUE);
  116.   listFrame->show();
  117.   // device settings
  118.   Gtk_Frame *recordOptionsFrame = new Gtk_Frame(string("Record Options"));
  119.   table = new Gtk_Table(3, 2, FALSE);
  120.   table->set_row_spacings(2);
  121.   table->set_col_spacings(30);
  122.   hbox = new Gtk_HBox;
  123.   hbox->pack_start(*table, FALSE, FALSE, 5);
  124.   vbox = new Gtk_VBox;
  125.   vbox->pack_start(*hbox, FALSE, FALSE, 5);
  126.   recordOptionsFrame->add(vbox);
  127.   vbox->show();
  128.   hbox->show();
  129.   table->show();
  130.   
  131.   hbox = new Gtk_HBox;
  132.   hbox->pack_start(*simulateButton_, FALSE, FALSE);
  133.   simulateButton_->show();
  134.   table->attach(*hbox, 0, 1, 0, 1);
  135.   hbox->show();
  136.   hbox = new Gtk_HBox;
  137.   hbox->pack_start(*writeButton_, FALSE, FALSE);
  138.   writeButton_->show();
  139.   table->attach(*hbox, 0, 1, 1, 2);
  140.   hbox->show();
  141.   hbox = new Gtk_HBox;
  142.   hbox->pack_start(*closeSessionButton_, FALSE, FALSE);
  143.   closeSessionButton_->show();
  144.   table->attach(*hbox, 1, 2, 0, 1);
  145.   hbox->show();
  146.   hbox = new Gtk_HBox;
  147.   hbox->pack_start(*ejectButton_, FALSE, FALSE);
  148.   ejectButton_->show();
  149.   table->attach(*hbox, 2, 3, 0, 1);
  150.   hbox->show();
  151.   hbox = new Gtk_HBox;
  152.   label = new Gtk_Label(string("Recording Speed: "));
  153.   hbox->pack_start(*label, FALSE);
  154.   label->show();
  155.   hbox->pack_start(*speedMenu_, FALSE);
  156.   speedMenu_->show();
  157.   table->attach(*hbox, 1, 2, 1, 2);
  158.   hbox->show();
  159.   hbox = new Gtk_HBox;
  160.   hbox->pack_start(*reloadButton_, FALSE);
  161.   reloadButton_->show();
  162.   table->attach(*hbox, 2, 3, 1, 2);
  163.   hbox->show();
  164.   
  165.   
  166.   contents->pack_start(*recordOptionsFrame, FALSE, FALSE);
  167.   recordOptionsFrame->show();
  168.   Gtk_HBox *contentsHBox = new Gtk_HBox;
  169.   contentsHBox->pack_start(*contents, TRUE, TRUE, 10);
  170.   contents->show();
  171.   get_vbox()->pack_start(*contentsHBox, TRUE, TRUE, 10);
  172.   contentsHBox->show();
  173.   get_vbox()->show();
  174.   Gtk_HButtonBox *bbox = new Gtk_HButtonBox(GTK_BUTTONBOX_SPREAD);
  175.   bbox->pack_start(*startButton_);
  176.   startButton_->show();
  177.   connect_to_method(startButton_->clicked, this, &RecordDialog::startAction);
  178.   
  179.   Gtk_Button *cancelButton = new Gtk_Button(string(" Cancel "));
  180.   bbox->pack_start(*cancelButton);
  181.   cancelButton->show();
  182.   connect_to_method(cancelButton->clicked, this, &RecordDialog::cancelAction);
  183.   get_action_area()->pack_start(*bbox);
  184.   bbox->show();
  185.   get_action_area()->show();
  186. }
  187. RecordDialog::~RecordDialog()
  188. {
  189.   DeviceData *data;
  190.   while (list_->rows() > 0) {
  191.     data = (DeviceData*)list_->get_row_data(0);
  192.     delete data;
  193.     list_->remove_row(0);
  194.   }
  195.   delete list_;
  196.   list_ = NULL;
  197.   delete startButton_;
  198.   startButton_ = NULL;
  199. }
  200. void RecordDialog::start(TocEdit *tocEdit)
  201. {
  202.   if (active_) {
  203.     get_window().raise();
  204.     return;
  205.   }
  206.   active_ = 1;
  207.   update(UPD_CD_DEVICES, tocEdit);
  208.   show();
  209. }
  210. void RecordDialog::stop()
  211. {
  212.   if (active_) {
  213.     hide();
  214.     active_ = 0;
  215.   }
  216. }
  217. void RecordDialog::update(unsigned long level, TocEdit *tocEdit)
  218. {
  219.   if (!active_)
  220.     return;
  221.   tocEdit_ = tocEdit;
  222.   if (level & UPD_CD_DEVICES)
  223.     import();
  224.   else if (level & UPD_CD_DEVICE_STATUS)
  225.     importStatus();
  226. }
  227. gint RecordDialog::delete_event_impl(GdkEventAny*)
  228. {
  229.   stop();
  230.   return 1;
  231. }
  232. void RecordDialog::cancelAction()
  233. {
  234.   stop();
  235. }
  236. void RecordDialog::startAction()
  237. {
  238.   int eject, simulate, speed, multiSession, reload;
  239.   int started = 0;
  240.   Toc *toc;
  241.   if (tocEdit_ == NULL)
  242.     return;
  243.   if (list_->selbegin() == list_->selend()) {
  244.     MessageBox msg(this, "Record", 0, 
  245.    "Please select at least one recorder device.", NULL);
  246.     msg.run();
  247.     return;
  248.   }
  249.   toc = tocEdit_->toc();
  250.   if (toc->nofTracks() == 0 || toc->length().lba() < 300) {
  251.     MessageBox msg(this, "Cannot Record", 0,
  252.    "Current toc contains no tracks or",
  253.    "length of at least one track is < 4 seconds.", NULL);
  254.     msg.run();
  255.     return;
  256.   }
  257.   switch (toc->checkCdTextData()) {
  258.   case 0: // OK
  259.     break;
  260.   case 1: // warning
  261.     {
  262.       Ask2Box msg(this, "CD-TEXT Inconsistency", 0, 2,
  263.   "Inconsistencies were detected in the defined CD-TEXT data",
  264.   "which may produce undefined results. See the console",
  265.   "output for more details.",
  266.   "",
  267.   "Do you want to proceed anyway?", NULL);
  268.       if (msg.run() != 1)
  269. return;
  270.     }
  271.     break;
  272.   default: // error
  273.     {
  274.       MessageBox msg(this, "CD-TEXT Error", 0, 
  275.      "The defined CD-TEXT data is erroneous or incomplete.",
  276.      "See the console output for more details.", NULL);
  277.       msg.run();
  278.       return;
  279.     }
  280.     break;
  281.   }
  282.   simulate = writeButton_->get_active() ? 0 : 1;
  283.   multiSession = closeSessionButton_->get_active() ? 0 : 1;
  284.   speed = SPEED_TABLE[speed_].speed;
  285.   eject = ejectButton_->get_active() ? 1 : 0;
  286.   reload = reloadButton_->get_active() ? 1 : 0;
  287.   // If ejecting the CD after recording is requested issue a warning message
  288.   // because buffer under runs may occur for other devices that are recording.
  289.   if (eject && SETTINGS->getInteger(SET_RECORD_EJECT_WARNING) != 0) {
  290.     Ask3Box msg(this, "Record", 1, 2, 
  291. "Ejecting a CD may block the SCSI bus and",
  292. "cause buffer under runs when other devices",
  293. "are still recording.", "",
  294. "Keep the eject setting anyway?", NULL);
  295.     switch (msg.run()) {
  296.     case 1: // keep eject setting
  297.       if (msg.dontShowAgain())
  298. SETTINGS->set(SET_RECORD_EJECT_WARNING, 0);
  299.       break;
  300.     case 2: // don't keep eject setting
  301.       eject = 0;
  302.       ejectButton_->set_active(false);
  303.       break;
  304.     default: // cancel
  305.       return;
  306.       break;
  307.     }
  308.   }
  309.   // The same is true for reloading the disk.
  310.   if (reload && SETTINGS->getInteger(SET_RECORD_RELOAD_WARNING) != 0) {
  311.     Ask3Box msg(this, "Record", 1, 2, 
  312. "Reloading a CD may block the SCSI bus and",
  313. "cause buffer under runs when other devices",
  314. "are still recording.", "",
  315. "Keep the reload setting anyway?", NULL);
  316.     switch (msg.run()) {
  317.     case 1: // keep eject setting
  318.       if (msg.dontShowAgain())
  319. SETTINGS->set(SET_RECORD_RELOAD_WARNING, 0);
  320.       break;
  321.     case 2: // don't keep eject setting
  322.       reload = 0;
  323.       reloadButton_->set_active(false);
  324.       break;
  325.     default: // cancel
  326.       return;
  327.       break;
  328.     }
  329.   }
  330.   
  331.   Gtk_CList::seliterator itr;
  332.   for (itr = list_->selbegin(); itr != list_->selend(); itr++) {
  333.     DeviceData *data = (DeviceData*)list_->get_row_data(*itr);
  334.     if (data != NULL) {
  335.       CdDevice *dev = CdDevice::find(data->bus, data->id, data->lun);
  336.       if (dev != NULL) {
  337. if (dev->recordDao(tocEdit_, simulate, multiSession, speed,
  338.    eject, reload) != 0) {
  339.   message(-2, "Cannot start disk-at-once recording.");
  340. }
  341. else {
  342.   started = 1;
  343. }
  344.       }
  345.     }
  346.   }
  347.   if (started)
  348.     guiUpdate(UPD_CD_DEVICE_STATUS);
  349. }
  350. void RecordDialog::appendTableEntry(CdDevice *dev)
  351. {
  352.   DeviceData *data;
  353.   char buf[50];
  354.   string idStr;
  355.   string busStr;
  356.   string lunStr;
  357.   const gchar *rowStr[6];
  358.   data = new DeviceData;
  359.   data->bus = dev->bus();
  360.   data->id = dev->id();
  361.   data->lun = dev->lun();
  362.   sprintf(buf, "%d", data->bus);
  363.   busStr = buf;
  364.   rowStr[0] = busStr.c_str();
  365.   sprintf(buf, "%d", data->id);
  366.   idStr = buf;
  367.   rowStr[1] = idStr.c_str();
  368.   sprintf(buf, "%d", data->lun);
  369.   lunStr = buf;
  370.   rowStr[2] = lunStr.c_str();
  371.   rowStr[3] = dev->vendor();
  372.   rowStr[4] = dev->product();
  373.   
  374.   rowStr[5] = CdDevice::status2string(dev->status());
  375.   list_->append(rowStr);
  376.   list_->set_row_data(list_->rows() - 1, data);
  377.   if (dev->status() == CdDevice::DEV_READY)
  378.     list_->set_selectable(list_->rows() - 1, true);
  379.   else
  380.     list_->set_selectable(list_->rows() - 1, false);
  381. }
  382. void RecordDialog::import()
  383. {
  384.   CdDevice *drun;
  385.   DeviceData *data;
  386.   int i;
  387.   list_->freeze();
  388.   while (list_->rows() > 0) {
  389.     data = (DeviceData*)list_->get_row_data(0);
  390.     delete data;
  391.     list_->remove_row(0);
  392.   }
  393.   for (drun = CdDevice::first(); drun != NULL; drun = CdDevice::next(drun)) {
  394.     if (drun->driverId() > 0 &&
  395. (drun->deviceType() == CdDevice::CD_R ||
  396.  drun->deviceType() == CdDevice::CD_RW)) {
  397.       appendTableEntry(drun);
  398.     }
  399.   }
  400.   list_->thaw();
  401.   if (list_->rows() > 0) {
  402.     list_->columns_autosize();
  403.     list_->moveto(0, 0, 0.0, 0.0);
  404.     // select first selectable device
  405.     for (i = 0; i < list_->rows(); i++) {
  406.       if (list_->get_selectable(i)) {
  407. list_->cause_select_row(i, 0);
  408. break;
  409.       }
  410.     }
  411.   }
  412. }
  413. void RecordDialog::importStatus()
  414. {
  415.   int i;
  416.   DeviceData *data;
  417.   CdDevice *dev;
  418.   for (i = 0; i < list_->rows(); i++) {
  419.     if ((data = (DeviceData*)list_->get_row_data(i)) != NULL &&
  420. (dev = CdDevice::find(data->bus, data->id, data->lun)) != NULL) {
  421.       if (dev->status() == CdDevice::DEV_READY) {
  422. list_->set_selectable(i, true);
  423.       }
  424.       else {
  425. list_->cause_unselect_row(i, 0);
  426. list_->set_selectable(i, false);
  427.       }
  428.       list_->set_text(i, 5, string(CdDevice::status2string(dev->status())));
  429.     }
  430.   }
  431.   list_->columns_autosize();
  432. }
  433. void RecordDialog::setSpeed(int s)
  434. {
  435.   if (s >= 0 && s <= MAX_SPEED_ID)
  436.     speed_ = s;
  437. }