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

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: CdDevice.cc,v $
  21.  * Revision 1.1  1999/09/03 16:05:14  mueller
  22.  * Initial revision
  23.  *
  24.  */
  25. static char rcsid[] = "$Id: CdDevice.cc,v 1.1 1999/09/03 16:05:14 mueller Exp mueller $";
  26. #include <sys/time.h>
  27. #include <sys/types.h>
  28. #include <stddef.h>
  29. #include <stdio.h>
  30. #include <unistd.h>
  31. #include <malloc.h>
  32. #include <errno.h>
  33. #include <string.h>
  34. #include <ctype.h>
  35. #include <assert.h>
  36. #include "TocEdit.h"
  37. #include "CdDevice.h"
  38. #include "ProcessMonitor.h"
  39. #include "xcdrdao.h"
  40. #include "guiUpdate.h"
  41. #include "RecordProgressDialog.h"
  42. #include "Settings.h"
  43. #include "remote.h"
  44. #include "ScsiIf.h"
  45. #include "CdrDriver.h"
  46. #include "util.h"
  47. #include "Toc.h"
  48. #define DRIVER_IDS 12
  49. CdDevice *CdDevice::DEVICE_LIST_ = NULL;
  50. char *CdDevice::DRIVER_NAMES_[DRIVER_IDS] = {
  51.   "Undefined",
  52.   "cdd2600",
  53.   "generic-mmc",
  54.   "generic-mmc-raw",
  55.   "plextor",
  56.   "plextor-scan",
  57.   "ricoh-mp6200",
  58.   "sony-cdu920",
  59.   "sony-cdu948",
  60.   "taiyo-yuden",
  61.   "teac-cdr55",
  62.   "yamaha-cdr10x"
  63. };
  64.   
  65. CdDevice::CdDevice(int bus, int id, int lun, const char *vendor,
  66.    const char *product)
  67. {
  68.   bus_ = bus;
  69.   id_ = id;
  70.   lun_ = lun;
  71.   vendor_ = strdupCC(vendor);
  72.   product_ = strdupCC(product);
  73.   
  74.   driverId_ = 0; // undefined
  75.   options_ = 0;
  76.   specialDevice_ = NULL;
  77.   deviceType_ = CD_R;
  78.   manuallyConfigured_ = 0;
  79.   status_ = DEV_UNKNOWN;
  80.   exitStatus_ = 0;
  81.   progressStatusChanged_ = 0;
  82.   progressStatus_ = 0;
  83.   progressTrack_ = 0;
  84.   progressTotal_ = 0;
  85.   progressBufferFill_ = 0;
  86.   process_ = NULL;
  87.   scsiIf_ = NULL;
  88.   scsiIfInitFailed_ = 0;
  89.   next_ = NULL;
  90.   autoSelectDriver();
  91. }
  92. CdDevice::~CdDevice()
  93. {
  94.   delete[] vendor_;
  95.   vendor_ = NULL;
  96.   delete[] product_;
  97.   product_ = NULL;
  98.   delete[] specialDevice_;
  99.   specialDevice_ = NULL;
  100.   delete scsiIf_;
  101.   scsiIf_ = NULL;
  102. }
  103. char *CdDevice::settingString() const
  104. {
  105.   char buf[100];
  106.   string s;
  107.   sprintf(buf, "%d,%d,%d,'", bus_, id_, lun_);
  108.   s += buf;
  109.   s += vendor_;
  110.   s += "','";
  111.   s += product_;
  112.   s += "',";
  113.   switch (deviceType_) {
  114.   case CD_R:
  115.     s += "CD_R";
  116.     break;
  117.   case CD_RW:
  118.     s += "CD_RW";
  119.     break;
  120.   case CD_ROM:
  121.     s+= "CD_ROM";
  122.     break;
  123.   }
  124.   s += ",";
  125.   s += driverName(driverId_);
  126.   s += ",";
  127.   sprintf(buf, "0x%lx,", options_);
  128.   s += buf;
  129.   s += "'";
  130.   if (specialDevice_ != NULL)
  131.     s += specialDevice_;
  132.   s += "'";
  133.   return strdupCC(s.c_str());
  134. }
  135. int CdDevice::bus() const
  136. {
  137.   return bus_;
  138. }
  139. int CdDevice::id() const
  140. {
  141.   return id_;
  142. }
  143. int CdDevice::lun() const
  144. {
  145.   return lun_;
  146. }
  147. const char *CdDevice::vendor() const
  148. {
  149.   return vendor_;
  150. }
  151. const char *CdDevice::product() const
  152. {
  153.   return product_;
  154. }
  155. int CdDevice::driverId() const
  156. {
  157.   return driverId_;
  158. }
  159. void CdDevice::driverId(int id)
  160. {
  161.   if (id >= 0 && id < DRIVER_IDS) 
  162.     driverId_ = id;
  163. }
  164. const char *CdDevice::specialDevice() const
  165. {
  166.   return specialDevice_;
  167. }
  168. void CdDevice::specialDevice(const char *s)
  169. {
  170.   delete[] specialDevice_;
  171.   if (s == NULL || *s == 0)
  172.     specialDevice_ = NULL;
  173.   else
  174.     specialDevice_ = strdupCC(s);
  175.   // remove existing SCSI interface class, it will be recreated with
  176.   // respect to special device setting automatically later
  177.   delete scsiIf_;
  178.   scsiIf_ = NULL;
  179.   scsiIfInitFailed_ = 0;
  180.   status_ = DEV_UNKNOWN;
  181. }
  182. int CdDevice::manuallyConfigured() const
  183. {
  184.   return manuallyConfigured_;
  185. }
  186. void CdDevice::manuallyConfigured(int f)
  187. {
  188.   manuallyConfigured_ = (f != 0) ? 1 : 0;
  189. }
  190. CdDevice::Status CdDevice::status() const
  191. {
  192.   return status_;
  193. }
  194. void CdDevice::status(Status s)
  195. {
  196.   status_ = s;
  197. }
  198. int CdDevice::exitStatus() const
  199. {
  200.   return exitStatus_;
  201. }
  202. int CdDevice::autoSelectDriver()
  203. {
  204.   unsigned long options = 0;
  205.   const char *driverName;
  206.   driverName = CdrDriver::selectDriver(1, vendor_, product_, &options);
  207.   if (driverName == NULL) {
  208.     // select read driver 
  209.     driverName = CdrDriver::selectDriver(0, vendor_, product_, &options);
  210.     if (driverName != NULL)
  211.       deviceType_ = CD_ROM;
  212.   }
  213.   if (driverName != NULL) {
  214.     driverId_ = driverName2Id(driverName);
  215.     options_ = options;
  216.     return 1;
  217.   }
  218.   else {
  219.     driverId_ = 0;
  220.     options_ = 0;
  221.     return 0;
  222.   }
  223. }
  224. int CdDevice::updateStatus()
  225. {
  226.   Status newStatus = status_;
  227.   if (process_ != NULL) {
  228.     if (process_->exited()) {
  229.       newStatus = DEV_UNKNOWN;
  230.       exitStatus_ = process_->exitStatus();
  231.       progressStatusChanged_ = 1;
  232.       PROCESS_MONITOR->remove(process_);
  233.       process_ = NULL;
  234.     }
  235.   }
  236.   if (status_ == DEV_READY || status_ == DEV_BUSY || status_ == DEV_NO_DISK ||
  237.       status_ == DEV_UNKNOWN) {
  238.     if (scsiIf_ == NULL)
  239.       createScsiIf();
  240.     if (scsiIf_ != NULL) {
  241.       switch (scsiIf_->testUnitReady()) {
  242.       case 0:
  243. newStatus = DEV_READY;
  244. break;
  245.       case 1:
  246. newStatus = DEV_BUSY;
  247. break;
  248.       case 2:
  249. newStatus = DEV_NO_DISK;
  250. break;
  251.       case 3:
  252. newStatus = DEV_FAULT;
  253. break;
  254.       }
  255.     }
  256.     else {
  257.       newStatus = DEV_FAULT;
  258.     }
  259.   }
  260.   if (newStatus != status_) {
  261.     status_ = newStatus;
  262.     return 1;
  263.   }
  264.   
  265.   return 0;
  266. }
  267. int CdDevice::updateProgress()
  268. {
  269.   static char msgSync[4] = { 0xff, 0x00, 0xff, 0x00 };
  270.   int fd;
  271.   fd_set fds;
  272.   int state = 0;
  273.   char buf[10];
  274.   DaoWritingProgress msg;
  275.   struct timeval timeout = { 0, 0 };
  276.   //message(0, "Rcvd msg");
  277.   if (process_ == NULL || (fd = process_->commFd()) < 0)
  278.     return 0;
  279.   FD_ZERO(&fds);
  280.   FD_SET(fd, &fds);
  281.   while (select(fd + 1, &fds, NULL, NULL, &timeout) > 0 &&
  282.  FD_ISSET(fd, &fds)) {
  283.     FD_ZERO(&fds);
  284.     FD_SET(fd, &fds);
  285.     state = 0;
  286.     while (state < 4) {
  287.       if (read(fd, buf, 1) != 1) {
  288. //message(-2, "Reading of msg sync failed.");
  289. return (progressStatusChanged_ != 0) ? 1 : 0;
  290.       }
  291.       if (buf[0] == msgSync[state]) {
  292. state++;
  293.       }
  294.       else {
  295. state = 0;
  296. if (buf[0] == msgSync[state]) {
  297.   state++;
  298. }
  299.       }
  300.     }
  301.     if (read(fd, (char *)&msg, sizeof(msg)) == sizeof(msg)) {
  302.       /*
  303. message(0, "progress: %d %d %d %d", msg.status, msg.track,
  304. msg.totalProgress, msg.bufferFillRate);
  305. */
  306.       if (msg.status >= 1 && msg.status <= 3 &&
  307.   msg.track >= 0 && msg.track <= 0xaa &&
  308.   msg.totalProgress >= 0 && msg.totalProgress <= 1000 &&
  309.   msg.bufferFillRate >= 0 && msg.bufferFillRate <= 100) {
  310. progressStatus_ = msg.status;
  311. progressTrack_ = msg.track;
  312. progressTotal_ = msg.totalProgress;
  313. progressBufferFill_ = msg.bufferFillRate;
  314. progressStatusChanged_ = 1;
  315.       }
  316.     }
  317.     else {
  318.       message(-1, "Reading of msg failed.");
  319.     }
  320.   }
  321.   return (progressStatusChanged_ != 0) ? 1 : 0;
  322. }
  323. CdDevice::DeviceType CdDevice::deviceType() const
  324. {
  325.   return deviceType_;
  326. }
  327. void CdDevice::deviceType(DeviceType t)
  328. {
  329.   deviceType_ = t;
  330. }
  331. unsigned long CdDevice::driverOptions() const
  332. {
  333.   return options_;
  334. }
  335. void CdDevice::driverOptions(unsigned long o)
  336. {
  337.   options_ = o;
  338. }
  339. // Starts a 'cdrdao' for recording given toc.
  340. // Return: 0: OK, process succesfully launched
  341. //         1: error occured
  342. int CdDevice::recordDao(TocEdit *tocEdit, int simulate, int multiSession,
  343. int speed, int eject, int reload)
  344. {
  345.   char *tocFileName;
  346.   char *args[20];
  347.   int n = 0;
  348.   char devname[30];
  349.   char drivername[50];
  350.   char speedbuf[20];
  351.   char *execName;
  352.   const char *s;
  353.   if (status_ != DEV_READY || process_ != NULL)
  354.     return 1;
  355.   if ((tocFileName = tempnam(NULL, "toc")) == NULL) {
  356.     message(-2, "Cannot create temporary toc-file: %s", strerror(errno));
  357.     return 1;
  358.   }
  359.   if (tocEdit->toc()->write(tocFileName) != 0) {
  360.     message(-2, "Cannot write temporary toc-file.");
  361.     return 1;
  362.   }
  363.   if ((s = SETTINGS->getString(SET_CDRDAO_PATH)) != NULL)
  364.     execName = strdupCC(s);
  365.   else
  366.     execName = strdupCC("cdrdao");
  367.   args[n++] = execName;
  368.   if (simulate)
  369.     args[n++] = "simulate";
  370.   else
  371.     args[n++] = "write";
  372.   args[n++] = "--remote";
  373.   args[n++] = "-v0";
  374.   if (multiSession)
  375.     args[n++] = "--multi";
  376.   if (speed > 0) {
  377.     sprintf(speedbuf, "%d", speed);
  378.     args[n++] = "--speed";
  379.     args[n++] = speedbuf;
  380.   }
  381.   if (eject)
  382.     args[n++] = "--eject";
  383.   if (reload)
  384.     args[n++] = "--reload";
  385.   args[n++] = "--device";
  386.   if (specialDevice_ != NULL && *specialDevice_ != 0) {
  387.     args[n++] = specialDevice_;
  388.   }
  389.   else {
  390.     sprintf(devname, "%d,%d,%d", bus_, id_, lun_);
  391.     args[n++] = devname;
  392.   }
  393.   if (driverId_ > 0) {
  394.     sprintf(drivername, "%s:0x%lx", driverName(driverId_), options_);
  395.     args[n++] = "--driver";
  396.     args[n++] = drivername;
  397.   }
  398.   args[n++] = tocFileName;
  399.   args[n++] = NULL;
  400.   
  401.   assert(n <= 20);
  402.   
  403.   int i;
  404.   message(0, "Starting: ");
  405.   for (i = 0; i < n - 1; i++)
  406.     message(0, "%s ", args[i]);
  407.   message(0, "");
  408.   RECORD_PROGRESS_POOL->start(this, tocEdit);
  409.   // Remove the SCSI interface of this device to avoid problems with double
  410.   // usage of device nodes.
  411.   delete scsiIf_;
  412.   scsiIf_ = NULL;
  413.   process_ = PROCESS_MONITOR->start(execName, args);
  414.   delete[] execName;
  415.   if (process_ != NULL) {
  416.     status_ = DEV_RECORDING;
  417.     free(tocFileName);
  418.     /*
  419.     if (process_->commFd() >= 0) {
  420.       connect_to_method(Gtk_Main::instance()->input(process_->commFd(),
  421.     GDK_INPUT_READ),
  422. this, &CdDevice::updateProgress);
  423.     }
  424.     */
  425.     return 0;
  426.   }
  427.   else {
  428.     unlink(tocFileName);
  429.     free(tocFileName);
  430.     return 1;
  431.   }
  432. }
  433. void CdDevice::abortDaoRecording()
  434. {
  435.   if (process_ != NULL && !process_->exited()) {
  436.     PROCESS_MONITOR->stop(process_);
  437.   }
  438. }
  439. int CdDevice::progressStatusChanged()
  440. {
  441.   if (progressStatusChanged_) {
  442.     progressStatusChanged_ = 0;
  443.     return 1;
  444.   }
  445.   return 0;
  446. }
  447. void CdDevice::recordProgress(int *status, int *track, int *totalProgress,
  448.       int *bufferFill) const
  449. {
  450.   *status = progressStatus_;
  451.   *track = progressTrack_;
  452.   *totalProgress = progressTotal_;
  453.   *bufferFill = progressBufferFill_;
  454. }
  455. void CdDevice::createScsiIf()
  456. {
  457.   char buf[100];
  458.   if (scsiIfInitFailed_)
  459.     return;
  460.   delete scsiIf_;
  461.   if (specialDevice_ != NULL && *specialDevice_ != 0) {
  462.     scsiIf_ = new ScsiIf(specialDevice_);
  463.   }
  464.   else {
  465.     sprintf(buf, "%d,%d,%d", bus_, id_, lun_);
  466.     scsiIf_ = new ScsiIf(buf);
  467.   }
  468.   if (scsiIf_->init() != 0) {
  469.     delete scsiIf_;
  470.     scsiIf_ = NULL;
  471.     scsiIfInitFailed_ = 1;
  472.   }
  473. }
  474. int CdDevice::driverName2Id(const char *driverName)
  475. {
  476.   int i;
  477.   for (i = 1; i < DRIVER_IDS; i++) {
  478.     if (strcmp(DRIVER_NAMES_[i], driverName) == 0)
  479.       return i;
  480.   }
  481.   return 0;
  482. }
  483. int CdDevice::maxDriverId()
  484. {
  485.   return DRIVER_IDS - 1;
  486. }
  487. const char *CdDevice::driverName(int id)
  488. {
  489.   if (id >= 0 && id < DRIVER_IDS) {
  490.     return DRIVER_NAMES_[id];
  491.   }
  492.   else {
  493.     return "Undefined";
  494.   }
  495. }
  496. const char *CdDevice::status2string(Status s)
  497. {
  498.   char *ret = NULL;
  499.   switch (s) {
  500.   case DEV_READY:
  501.     ret = "Ready";
  502.     break;
  503.   case DEV_RECORDING:
  504.     ret = "Recording";
  505.     break;
  506.   case DEV_BLANKING:
  507.     ret = "Blanking";
  508.     break;
  509.   case DEV_BUSY:
  510.     ret = "Busy";
  511.     break;
  512.   case DEV_NO_DISK:
  513.     ret = "No disk";
  514.     break;
  515.   case DEV_FAULT:
  516.     ret = "Not available";
  517.     break;
  518.   case DEV_UNKNOWN:
  519.     ret = "Unknown";
  520.     break;
  521.   }
  522.   return ret;
  523. }
  524. const char *CdDevice::deviceType2string(DeviceType t)
  525. {
  526.   char *ret = NULL;
  527.   switch (t) {
  528.   case CD_R:
  529.     ret = "CD-R";
  530.     break;
  531.   case CD_RW:
  532.     ret = "CD-RW";
  533.     break;
  534.   case CD_ROM:
  535.     ret = "CD-ROM";
  536.     break;
  537.   }
  538.   return ret;
  539. }
  540. CdDevice *CdDevice::add(int bus, int id, int lun, const char *vendor,
  541. const char *product)
  542. {
  543.   CdDevice *run, *pred, *ent;
  544.   for (pred = NULL, run = DEVICE_LIST_; run != NULL;
  545.        pred = run, run = run->next_) {
  546.     if (bus < run->bus() ||
  547. (bus == run->bus() && id < run->id()) ||
  548. (bus == run->bus() && id == run->id() && lun < run->lun())) {
  549.       break;
  550.     }
  551.     else if (bus == run->bus() && id == run->id() && lun == run->lun()) {
  552.       return run;
  553.     }
  554.   }
  555.   ent = new CdDevice(bus, id, lun, vendor, product);
  556.   if (pred != NULL) {
  557.     ent->next_ = pred->next_;
  558.     pred->next_ = ent;
  559.   }
  560.   else {
  561.     ent->next_ = DEVICE_LIST_;
  562.     DEVICE_LIST_ = ent;
  563.   }
  564.   return ent;
  565. }
  566. static char *nextToken(char *&p)
  567. {
  568.   char *val = NULL;
  569.   if (p == NULL || *p == 0)
  570.     return NULL;
  571.   while (*p != 0 && isspace(*p))
  572.     p++;
  573.   if (*p == 0)
  574.     return NULL;
  575.   if (*p == ''') {
  576.     p++;
  577.     val = p;
  578.     while (*p != 0 && *p != ''')
  579.       p++;
  580.     if (*p == 0) {
  581.       // error, no matching ' found
  582.       return NULL;
  583.     }
  584.     else {
  585.       *p++ = 0;
  586.       
  587.       // skip over ,
  588.       while (*p != 0 && *p != ',')
  589. p++;
  590.       if (*p == ',')
  591. p++;
  592.     }
  593.   }
  594.   else {
  595.     val = p;
  596.     while (*p != 0 && *p != ',')
  597.       p++;
  598.    
  599.     if (*p == ',')
  600.       *p++ = 0;
  601.   }
  602.   return val;
  603. }
  604. static CdDevice *addImpl(char *s)
  605. {
  606.   char *p;
  607.   int bus, id, lun;
  608.   int driverId;
  609.   string vendor;
  610.   string model;
  611.   string device;
  612.   unsigned long options;
  613.   char *val;
  614.   CdDevice::DeviceType type;
  615.   CdDevice *dev;
  616.   p = s;
  617.   if ((val = nextToken(p)) == NULL)
  618.     return NULL;
  619.   bus = atoi(val);
  620.   if ((val = nextToken(p)) == NULL)
  621.     return NULL;
  622.   id = atoi(val);
  623.   if ((val = nextToken(p)) == NULL)
  624.     return NULL;
  625.   lun = atoi(val);
  626.   if ((val = nextToken(p)) == NULL)
  627.     return NULL;
  628.   vendor = val;
  629.   if ((val = nextToken(p)) == NULL)
  630.     return NULL;
  631.   model = val;
  632.   if ((val = nextToken(p)) == NULL)
  633.     return NULL;
  634.   if (strcasecmp(val, "CD_R") == 0)
  635.     type = CdDevice::CD_R;
  636.   else if (strcasecmp(val, "CD_RW") == 0)
  637.     type = CdDevice::CD_RW;
  638.   else if (strcasecmp(val, "CD_ROM") == 0)
  639.     type = CdDevice::CD_ROM;
  640.   else
  641.     type = CdDevice::CD_R;
  642.   if ((val = nextToken(p)) == NULL)
  643.     return NULL;
  644.   driverId = CdDevice::driverName2Id(val);
  645.   if ((val = nextToken(p)) == NULL)
  646.     return NULL;
  647.   options = strtoul(val, NULL, 0);
  648.   if ((val = nextToken(p)) == NULL)
  649.     return NULL;
  650.   device = val;
  651.   dev = CdDevice::add(bus, id, lun, vendor.c_str(), model.c_str());
  652.   dev->driverId(driverId);
  653.   dev->deviceType(type);
  654.   dev->driverOptions(options);
  655.   dev->specialDevice(device.c_str());
  656.   
  657.   return dev;
  658. }
  659. CdDevice *CdDevice::add(const char *setting)
  660. {
  661.   char *s = strdupCC(setting);
  662.   CdDevice *dev = addImpl(s);
  663.   delete[] s;
  664.   return dev;
  665. }
  666. CdDevice *CdDevice::find(int bus, int id, int lun)
  667. {
  668.   CdDevice *run;
  669.   for (run = DEVICE_LIST_; run != NULL; run = run->next_) {
  670.     if (bus == run->bus() && id == run->id() && lun == run->lun()) {
  671.       return run;
  672.     }
  673.   }
  674.   return NULL;
  675. }
  676.   
  677. void CdDevice::scan()
  678. {
  679.   int i, len;
  680.   ScsiIf::ScanData *sdata = ScsiIf::scan(&len);
  681.   if (sdata == NULL)
  682.     return;
  683.   for (i = 0; i < len; i++)
  684.     CdDevice::add(sdata[i].bus, sdata[i].id, sdata[i].lun, sdata[i].vendor,
  685.   sdata[i].product);
  686.   delete[] sdata;
  687. }
  688. void CdDevice::remove(int bus, int id, int lun)
  689. {
  690.   CdDevice *run, *pred;
  691.   for (pred = NULL, run = DEVICE_LIST_; run != NULL;
  692.        pred = run, run = run->next_) {
  693.     if (bus == run->bus() && id == run->id() && lun == run->lun()) {
  694.       if (run->status() == DEV_RECORDING || run->status() == DEV_BLANKING)
  695. return;
  696.       if (pred != NULL)
  697. pred->next_ = run->next_;
  698.       else
  699. DEVICE_LIST_ = run->next_;
  700.       delete run;
  701.       return;
  702.     }
  703.   }
  704. }
  705. void CdDevice::clear()
  706. {
  707.   CdDevice *next;
  708.   while (DEVICE_LIST_ != NULL) {
  709.     next = DEVICE_LIST_->next_;
  710.     delete DEVICE_LIST_;
  711.     DEVICE_LIST_ = next;
  712.   }
  713. }
  714. CdDevice *CdDevice::first()
  715. {
  716.   return DEVICE_LIST_;
  717. }
  718. CdDevice *CdDevice::next(const CdDevice *run)
  719. {
  720.   if (run != NULL)
  721.     return run->next_;
  722.   else
  723.     return NULL;
  724. }
  725. int CdDevice::count()
  726. {
  727.   CdDevice *run;
  728.   int cnt = 0;
  729.   for (run = DEVICE_LIST_; run != NULL; run = run->next_)
  730.     cnt++;
  731.   return cnt;
  732. }
  733. int CdDevice::updateDeviceStatus()
  734. {
  735.   int newStatus = 0;
  736.   CdDevice *run;
  737.   blockProcessMonitorSignals();
  738.   for (run = DEVICE_LIST_; run != NULL; run = run->next_) {
  739.     if (run->updateStatus())
  740.       newStatus = 1;
  741.   }
  742.   unblockProcessMonitorSignals();
  743.   return newStatus;
  744. }
  745. int CdDevice::updateDeviceProgress()
  746. {
  747.   int progress = 0;
  748.   int fd;
  749.   fd_set fds;
  750.   int maxFd = -1;
  751.   CdDevice *run;
  752.   struct timeval timeout = { 0, 0 };
  753.   blockProcessMonitorSignals();
  754.   FD_ZERO(&fds);
  755.   // collect set of file descriptors for 'select'
  756.   for (run = DEVICE_LIST_; run != NULL; run = run->next_) {
  757.     if (run->process_ != NULL && (fd = run->process_->commFd()) >= 0) {
  758.       FD_SET(fd, &fds);
  759.       if (fd > maxFd)
  760. maxFd = fd;
  761.     }
  762.   }
  763.   if (maxFd < 0) {
  764.     unblockProcessMonitorSignals();
  765.     return 0;
  766.   }
  767.   if (select(maxFd + 1, &fds, NULL, NULL, &timeout) > 0) {
  768.     for (run = DEVICE_LIST_; run != NULL; run = run->next_) {
  769.       if (run->process_ != NULL && (fd = run->process_->commFd()) >= 0) {
  770. if (FD_ISSET(fd, &fds)) {
  771.   if (run->updateProgress())
  772.     progress = 1;
  773. }
  774.       }
  775.     }
  776.   }
  777.   unblockProcessMonitorSignals();
  778.   return progress;
  779. }