freebsd-ports/sysutils/k3b-kde4/files/patch-src-core-device-k3bdevice.cpp
Will Andrews 2a59b4a154 Add k3b 0.10.2, a CD/DVD recording GUI for KDE.
PR:		59287
Submitted by:	Heiner Eichmann <h.eichmann@gmx.de>
2003-11-20 13:03:02 +00:00

912 lines
30 KiB
C++

--- src/core/device/k3bdevice.cpp.orig Thu Oct 30 11:53:35 2003
+++ src/core/device/k3bdevice.cpp Sat Nov 8 12:15:01 2003
@@ -32,7 +32,9 @@
#include <sys/ioctl.h>
#include <fstab.h>
+#ifndef __FreeBSD__
#include <mntent.h>
+#endif
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
@@ -40,6 +42,7 @@
#include <errno.h>
#include <sys/stat.h>
+#ifndef __FreeBSD__
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,70)
typedef unsigned char u8;
@@ -48,6 +51,18 @@
#include <linux/cdrom.h>
#define __STRICT_ANSI__
#include <linux/major.h>
+#else
+#include <sys/cdio.h>
+#include <sys/dvdio.h>
+#include <ktempfile.h>
+#define __BYTE_ORDER BYTE_ORDER
+#define __BIG_ENDIAN BIG_ENDIAN
+//#define CDROMEJECT CDIOCEJECT
+//#define CDROMCLOSETRAY CDIOCCLOSE
+#define CD_FRAMESIZE_RAW 2352
+#include <cam/scsi/scsi_message.h>
+int bsd_open_close_device(int bus, int target, int lun, bool eject);
+#endif
@@ -167,6 +182,7 @@
{
kdDebug() << "(K3bCdDevice) " << blockDeviceName() << ": init()" << endl;
+#ifndef __FreeBSD__
if(open() < 0)
return false;
@@ -175,10 +191,18 @@
// we also query the mode page 2A and use the cdrom.h stuff to get as much information as possible
//
+ // On BSD the device capabilities are already set by the devicemanager. So this code may
+ // find more capabilities -- if it works
d->deviceType = 0;
+#endif
d->supportedProfiles = 0;
+#ifndef __FreeBSD__
ScsiCommand cmd( open() );
+#else
+ ScsiCommand cmd(m_passDevice);
+ d->deviceType |= CDROM;
+#endif
unsigned char header[8];
::memset( header, 0, 8 );
cmd[0] = 0x46; // GET CONFIGURATION
@@ -580,8 +604,16 @@
int mm_cap_len = 0;
if( modeSense( &mm_cap_buffer, mm_cap_len, 0x2A ) ) {
mm_cap_page_2A* mm_p = (mm_cap_page_2A*)(mm_cap_buffer+8);
- if( mm_p->BUF ) d->burnfree = true;
- if( mm_p->cd_rw_write ) d->deviceType |= CDRW;
+ if( mm_p->BUF )
+ {
+ kdDebug() << "(K3bCdDevice) ModeSense: burnfree." << endl;
+ d->burnfree = true;
+ }
+ if( mm_p->cd_rw_write )
+ {
+ kdDebug() << "(K3bCdDevice) ModeSense: CDRW." << endl;
+ d->deviceType |= CDRW;
+ }
m_maxWriteSpeed = (int)( from2Byte(mm_p->max_write_speed) * 1024.0 / ( 2352.0 * 75.0 ) );
m_maxReadSpeed = (int)( from2Byte(mm_p->max_read_speed) * 1024.0 / ( 2352.0 * 75.0 ) );
@@ -592,6 +624,7 @@
}
+#ifndef __FreeBSD__
//
// This is the backup if the drive does not support the GET CONFIGURATION command
@@ -619,6 +652,7 @@
if (drivetype & CDC_DVD)
d->deviceType |= DVD;
+#endif
if( writesCd() )
checkWriteModes();
@@ -642,10 +676,11 @@
m_version = QString::fromLocal8Bit( (char*)(inq+32), 4 ).stripWhiteSpace();
}
+#ifndef __FreeBSD__
close();
+#endif
d->interfaceType = interfaceType();
-
return furtherInit();
}
@@ -649,6 +684,23 @@
return furtherInit();
}
+void K3bCdDevice::CdDevice::guessProfiles()
+{
+ if (!d->supportedProfiles)
+ {
+ kdDebug() << "(K3bCdDevice): no profiles found; setting them from device type = " << d->deviceType << endl;
+ if (d->deviceType & CDROM) d->supportedProfiles |= MEDIA_CD_ROM;
+ if (d->deviceType & CDR) d->supportedProfiles |= MEDIA_CD_R;
+ if (d->deviceType & CDRW) d->supportedProfiles |= MEDIA_CD_RW;
+ if (d->deviceType & DVDR) d->supportedProfiles |= MEDIA_DVD_R_SEQ;
+ if (d->deviceType & DVDRAM) d->supportedProfiles |= MEDIA_DVD_RAM;
+ if (d->deviceType & DVD) d->supportedProfiles |= MEDIA_DVD_ROM;
+ if (d->deviceType & DVDRW) d->supportedProfiles |= MEDIA_DVD_RW_OVWR | MEDIA_DVD_RW_SEQ;// ???
+ if (d->deviceType & DVDPR) d->supportedProfiles |= MEDIA_DVD_PLUS_R;
+ if (d->deviceType & DVDPRW) d->supportedProfiles |= MEDIA_DVD_PLUS_RW;
+ }
+// case 0x11: d->supportedProfiles |= MEDIA_DVD_R_SEQ;
+}
bool K3bCdDevice::CdDevice::furtherInit()
{
@@ -658,6 +710,7 @@
K3bCdDevice::CdDevice::interface K3bCdDevice::CdDevice::interfaceType()
{
+#ifndef __FreeBSD__
if (d->interfaceType == OTHER)
{
// if the device is already opened we do not close it
@@ -680,6 +733,9 @@
if( needToClose )
close();
}
+#else
+ d->interfaceType = SCSI;
+#endif
return d->interfaceType;
}
@@ -826,7 +882,11 @@
unsigned char dvdheader[20];
::memset( dvdheader, 0, 20 );
+#ifndef __FreeBSD__
ScsiCommand cmd( open() );
+#else
+ ScsiCommand cmd(m_passDevice);
+#endif
cmd[0] = 0xad; // GPCMD_READ_DVD_STRUCTURE;
cmd[9] = 20;
if( cmd.transport( TR_DIR_READ, dvdheader, 20 ) ) {
@@ -846,6 +906,7 @@
int K3bCdDevice::CdDevice::isReady() const
{
+#ifndef __FreeBSD__
// if the device is already opened we do not close it
// to allow fast multible method calls in a row
bool needToClose = !isOpen();
@@ -905,6 +966,10 @@
}
else
return 2;
+#else
+ ((CdDevice *)this)->refreshDeviceData();
+ return m_driveReady;
+#endif
}
@@ -941,6 +1006,7 @@
delete [] data;
}
else {
+#ifndef __FreeBSD__
kdDebug() << "(K3bCdDevice::CdDevice) " << blockDeviceName()
<< ": READ DISC INFORMATION failed. falling back to cdrom.h" << endl;
int drive_status = ::ioctl(d->deviceFd,CDROM_DRIVE_STATUS);
@@ -953,6 +1019,10 @@
kdDebug() << "(K3bCdDevice::CdDevice) " << blockDeviceName() << ": No disk in drive" << endl;
ret = NO_DISK;
}
+#else
+ ((CdDevice *)this)->refreshDeviceData();
+ ret = m_deviceStatus;
+#endif
}
if( needToClose )
@@ -1013,7 +1083,11 @@
unsigned char header[2];
::memset( header, 0, 2 );
+#ifndef __FreeBSD__
ScsiCommand cmd( open() );
+#else
+ ScsiCommand cmd(m_passDevice);
+#endif
cmd[0] = 0x51; // READ DISC INFORMATION
cmd[8] = 2;
@@ -1199,6 +1273,7 @@
bool readSuccess = true;
if( !readSectorsRaw( data, lba, 1 ) ) {
+#ifndef __FreeBSD__
kdDebug() << "(K3bCdDevice::CdDevice) " << blockDeviceName()
<< ": MMC RAW READ failed. falling back to cdrom.h." << endl;
@@ -1209,8 +1284,11 @@
if( ::ioctl(d->deviceFd,CDROMREADRAW,data) == -1 ) {
kdDebug() << "(K3bCdDevice::CdDevice) " << blockDeviceName()
<< ": could not get track header, (lba " << lba << ") ! " << strerror(errno) << endl;
+#endif
readSuccess = false;
+#ifndef __FreeBSD__
}
+#endif
}
if( readSuccess ) {
@@ -1556,7 +1634,7 @@
bool success = true;
toc.clear();
-
+#ifndef __FreeBSD__
struct cdrom_tochdr tochdr;
struct cdrom_tocentry tocentry;
@@ -1642,6 +1720,10 @@
else
success = false;
+#else
+ ((CdDevice *)this)->refreshDeviceData();
+ toc = m_toc;
+#endif
return success;
}
@@ -1653,7 +1735,7 @@
bool needToClose = !isOpen();
bool success = false;
-
+#ifndef __FreeBSD__
if( open() != -1 ) {
//
// we probaly need to fixup the toc for multisession mixed-mode cds
@@ -1681,7 +1763,7 @@
kdDebug() << "(K3bCdDevice::CdDevice) CDROMMULTISESSION failed." << endl;
}
}
-
+#endif
if( needToClose )
close();
@@ -1692,17 +1774,25 @@
bool K3bCdDevice::CdDevice::block( bool b ) const
{
if( open() != -1 ) {
+#ifndef __FreeBSD__
ScsiCommand cmd( open() );
+#else
+ ScsiCommand cmd(m_passDevice);
+#endif
cmd[0] = 0x1E; // ALLOW MEDIA REMOVAL
cmd[4] = b ? 0x1 : 0x0;
int r = cmd.transport();
if( r ) {
kdDebug() << "(K3bCdDevice::CdDevice) MMC ALLOW MEDIA REMOVAL failed. Falling back to cdrom.h." << endl;
+#ifndef __FreeBSD__
r = ::ioctl(d->deviceFd,CDROM_LOCKDOOR, b ? 1 : 0 );
+#else
+ r = ::ioctl(d->deviceFd,b ? CDIOCPREVENT : CDIOCALLOW);
+#endif
}
if( r )
- kdDebug() << "(K3bCdDevice) Cannot block/unblock device " << devicename() << endl;
+ kdDebug() << "(K3bCdDevice) Cannot block/unblock device " << devicename() << ", errno: " << errno << endl;
close();
return ( r == 0 );
@@ -1724,22 +1814,36 @@
return e;
}
+#ifndef __FreeBSD__
else
return false;
+#else
+ ((CdDevice *)this)->refreshDeviceData();
+ return m_rewritableCd;
+#endif
}
bool K3bCdDevice::CdDevice::eject() const
{
block(false);
+#ifndef __FreeBSD__
if( open() != -1 ) {
ScsiCommand cmd( open() );
+#else
+ if( true ) {
+ ScsiCommand cmd(m_passDevice);
+#endif
cmd[0] = 0x1B; // START/STOP UNIT
cmd[4] = 0x2; // LoEj = 1, Start = 0
int r = cmd.transport();
if( r ) {
kdDebug() << "(K3bCdDevice::CdDevice) MMC START/STOP UNIT failed. Falling back to cdrom.h." << endl;
+#ifndef __FreeBSD__
r = ::ioctl( d->deviceFd, CDROMEJECT );
+#else
+ r = bsd_open_close_device(m_bus, m_target, m_lun, true);
+#endif
}
close();
@@ -1752,14 +1856,23 @@
bool K3bCdDevice::CdDevice::load() const
{
+#ifndef __FreeBSD__
if( open() != -1 ) {
ScsiCommand cmd( open() );
+#else
+ if( true ) {
+ ScsiCommand cmd(m_passDevice);
+#endif
cmd[0] = 0x1B; // START/STOP UNIT
cmd[4] = 0x3; // LoEj = 1, Start = 1
int r = cmd.transport();
if( r ) {
kdDebug() << "(K3bCdDevice::CdDevice) MMC START/STOP UNIT failed. Falling back to cdrom.h." << endl;
+#ifndef __FreeBSD__
r = ::ioctl( d->deviceFd, CDROMCLOSETRAY );
+#else
+ r = bsd_open_close_device(m_bus, m_target, m_lun, false);
+#endif
}
close();
return (r == 0);
@@ -1793,7 +1906,7 @@
d->deviceFd = openDevice( QFile::encodeName(devicename()) );
if (d->deviceFd < 0)
{
- kdDebug() << "(K3bCdDevice) Error: could not open device." << endl;
+ kdDebug() << "(K3bCdDevice) Error: could not open device: " << QFile::encodeName(devicename()) << endl;
d->deviceFd = -1;
}
@@ -1915,7 +2028,11 @@
unsigned char profileBuf[8];
::memset( profileBuf, 0, 8 );
+#ifndef __FreeBSD__
ScsiCommand cmd( open() );
+#else
+ ScsiCommand cmd(m_passDevice);
+#endif
cmd[0] = 0x46; // GET CONFIGURATION
cmd[1] = 1;
cmd[8] = 8;
@@ -1974,7 +2091,11 @@
}
inf.m_currentProfile = profile;
+#ifndef __FreeBSD__
ScsiCommand cmd( open() );
+#else
+ ScsiCommand cmd(m_passDevice);
+#endif
if( inf.diskState() != STATE_NO_MEDIA ) {
@@ -2037,6 +2158,33 @@
delete [] data;
}
+#ifdef __FreeBSD__
+ else
+ {
+ ((CdDevice *)this)->refreshDeviceData();
+ inf.m_rewritable = m_rewritableCd;
+ inf.m_numSessions = m_toc.size();
+ inf.m_capacity = m_discSize;
+ inf.m_remaining = m_remainingSize;
+ inf.m_diskState = STATE_UNKNOWN;
+ inf.m_lastSessionState = STATE_UNKNOWN;
+ if (m_deviceStatus == EMPTY)
+ {
+ inf.m_diskState = STATE_EMPTY;
+ inf.m_lastSessionState = STATE_EMPTY;
+ }
+ else if (m_deviceStatus == APPENDABLE)
+ {
+ inf.m_diskState = STATE_INCOMPLETE;
+ inf.m_lastSessionState = STATE_INCOMPLETE;
+ }
+ else if (m_deviceStatus == COMPLETE)
+ {
+ inf.m_diskState = STATE_COMPLETE;
+ inf.m_lastSessionState = STATE_COMPLETE;
+ }
+ }
+#endif
//
// Now we determine the size:
@@ -2085,7 +2233,7 @@
if( cmd.transport( TR_DIR_READ, trackHeader, 32 ) ) {
kdDebug() << "(K3bCdDevice) READ_TRACK_INFORMATION failed." << endl;
kdDebug() << "(K3bCdDevice) getting disk size via toc." << endl;
-
+#ifndef __FreeBSD__
// TODO: use readToc!
struct cdrom_tocentry tocentry;
@@ -2097,6 +2245,11 @@
inf.m_capacity = tocentry.cdte_addr.lba;
inf.m_capacity -= 1; // we need the last sector of the last track, not the first from the lead-out
}
+#else
+ ((CdDevice *)this)->refreshDeviceData();
+ inf.m_capacity = m_discSize;
+ inf.m_capacity -= 1;
+#endif
}
else {
// not sure about this....
@@ -2160,7 +2313,11 @@
unsigned char dvdheader[20];
::memset( dvdheader, 0, 20 );
+#ifndef __FreeBSD__
ScsiCommand cmd( open() );
+#else
+ ScsiCommand cmd(m_passDevice);
+#endif
cmd[0] = 0xad; // GPCMD_READ_DVD_STRUCTURE;
cmd[9] = 20;
if( cmd.transport( TR_DIR_READ, dvdheader, 20 ) ) {
@@ -2199,7 +2356,11 @@
bool success = true;
+#ifndef __FreeBSD__
ScsiCommand cmd( open() );
+#else
+ ScsiCommand cmd(m_passDevice);
+#endif
cmd[0] = 0x25; // READ CAPACITY
unsigned char buf[8];
::memset( buf, 0, 8 );
@@ -2236,7 +2397,11 @@
unsigned char header[4]; // for reading the size of the returned data
::memset( header, 0, 4 );
+#ifndef __FreeBSD__
ScsiCommand cmd( open() );
+#else
+ ScsiCommand cmd(m_passDevice);
+#endif
cmd[0] = 0x23; // GPCMD_READ_FORMAT_CAPACITIES;
cmd[8] = 4;
if( cmd.transport( TR_DIR_READ, header, 4 ) == 0 ) {
@@ -2324,7 +2489,11 @@
unsigned char header[8];
::memset( header, 0, 8 );
+#ifndef __FreeBSD__
ScsiCommand cmd( open() );
+#else
+ ScsiCommand cmd(m_passDevice);
+#endif
cmd[0] = 0x5A; // MODE SENSE
cmd[1] = 0x08; // Disable Block Descriptors
cmd[2] = page;
@@ -2362,7 +2531,11 @@
bool ret = false;
+#ifndef __FreeBSD__
ScsiCommand cmd( open() );
+#else
+ ScsiCommand cmd(m_passDevice);
+#endif
cmd[0] = 0x55; // MODE SELECT
cmd[1] = ( sp ? 1 : 0 ) | ( pf ? 0x10 : 0 );
cmd[7] = pageLen>>8;
@@ -2486,7 +2659,11 @@
unsigned char header[2];
::memset( header, 0, 2 );
+#ifndef __FreeBSD__
ScsiCommand cmd( open() );
+#else
+ ScsiCommand cmd(m_passDevice);
+#endif
cmd[0] = 0x43; // READ TOC/PMA/ATIP
cmd[1] = ( time ? 0x2 : 0x0 );
cmd[2] = format & 0x0F;
@@ -2536,7 +2713,11 @@
unsigned char header[8];
::memset( header, 0, 8 );
+#ifndef __FreeBSD__
ScsiCommand cmd( open() );
+#else
+ ScsiCommand cmd(m_passDevice);
+#endif
cmd[0] = 0xbd; // MECHANISM STATUS
cmd[8] = 8; // first we read the header
if( cmd.transport( TR_DIR_READ, header, 8 ) == 0 ) {
@@ -2640,7 +2821,11 @@
::memset( data, 0, dataLen );
+#ifndef __FreeBSD__
ScsiCommand cmd( open() );
+#else
+ ScsiCommand cmd(m_passDevice);
+#endif
cmd[0] = 0xbe; // READ CD
cmd[1] = (sectorType<<2 & 0x1c) | ( dap ? 0x2 : 0x0 );
cmd[2] = startAdress>>24;
@@ -2668,3 +2853,363 @@
return ret;
}
+#ifdef __FreeBSD__
+void K3bDevice::CdDevice::refreshDeviceData()
+{
+ // was it called within the last 3 seconds?
+ QDateTime now = QDateTime::currentDateTime();
+ if (m_lastRefresh.isValid() && m_lastRefresh.secsTo(now) < 3)
+ return; // yes: use previous values
+
+ m_driveReady = 0;
+ m_rewritableCd = 0;
+ m_discSize = 0;
+ m_remainingSize = 0;
+ m_deviceStatus = NO_INFO;
+ m_toc.clear();
+
+ KTempFile tmpfile;
+ tmpfile.setAutoDelete(true);
+
+ // call cdrecord -toc to get the toc and to detect empty disks
+ QString call = "/bin/sh -c \"cdrecord -toc " + QString("dev=%1").arg( busTargetLun() ) + " > " + tmpfile.name() + " 2>&1 \"";
+ kdDebug() << "(K3bCdDevice) Reading Toc : " << call << endl;
+ system(call.latin1());
+
+ // read tmp file line by line
+ K3bTrack lastTrack;
+ bool firstEntry = true;
+ QFile tmp (tmpfile.name());
+ if ( tmp.open( IO_ReadOnly ) )
+ {
+ QTextStream stream( &tmp );
+ bool done = false;
+ while ( !stream.eof() )
+ {
+ QString str = stream.readLine();
+ kdDebug() << "(K3bCdDevice): " << str << endl;
+ if (done)
+ continue;
+ // no disk inserted?
+ if ( str.startsWith( "cdrecord: No disk" ) )
+ {
+ m_driveReady = NO_DISK;
+ kdDebug() << "(K3bCdDevice) No Toc Data!" << endl;
+ // close and delete tmp file
+ tmp.close();
+ done = true;
+ continue;
+ }
+ // emoty disk inserted?
+ else if (str.startsWith("cdrecord: Cannot read TOC header"))
+ {
+ kdDebug() << "(K3bCdDevice) cd is empty" << endl;
+ m_driveReady = EMPTY;
+ }
+ // track data available?
+ if( str.startsWith("track:") )
+ {
+ // cdrecord produces the following outout:
+ // <tracknumber> lba: <startSector> (<...>) <startTime> adr: 1 control: <trackType> mode: <trackMode>
+ // the last tracknumber will always be "lout", the leadout of the cd which we only use to determine the
+ // length of the last track
+
+ // we just want the startSector, the trackType, and the trackMode
+ int start = 6; // skip the "track:"
+ start = str.find(":", start )+1;
+ int end = str.find( "(", start );
+
+ bool ok;
+ int startSec = str.mid( start, end-start ).toInt(&ok);
+ if( ok )
+ {
+ start = str.find( "control:", start )+8; // skip the "control:"
+ end = str.find("mode:", start );
+ int control = str.mid( start, end-start ).toInt(&ok);
+ if( ok )
+ {
+ start = end + 6;
+ int mode = str.mid( start ).toInt(&ok);
+ if( ok )
+ {
+ // all values have been determined
+ // since we need the start of the next track to determine the length we save the values
+ // in lastTrack and append the current lastTrack to the toc
+
+ if( !firstEntry )
+ {
+ m_toc.append( K3bTrack( lastTrack.firstSector(), startSec-1, lastTrack.type(), lastTrack.mode() ) );
+ kdDebug() << "(K3bCDDevice) Found track: first sector: " << lastTrack.firstSector().toString()
+ << ", last sector: " << startSec-1 << ", type: " << lastTrack.type()
+ << ", mode: " << lastTrack.mode() << endl;
+ if (m_deviceStatus == EMPTY)
+ m_deviceStatus = APPENDABLE;
+ if( lastTrack.mode() == K3bTrack::MODE1 )
+ m_deviceStatus = COMPLETE;
+ }
+ // now this is the meaning of control and mode:
+ // control (combination of the following)
+ // 0x01 - Audio with preemp
+ // 0x02 - Audio copy permitted
+ // 0x04 - Data track
+ // 0x08 - 4 channel audio
+
+ // mode (only for data tracks)
+ // 1 - Mode 1
+ // 2 - Mode 2
+
+ int trackType = 0;
+ int trackMode = K3bTrack::UNKNOWN;
+ if( control & 0x04 )
+ {
+ trackType = K3bTrack::DATA;
+ if( mode == 1 )
+ trackMode = K3bTrack::MODE1;
+ else if( mode == 2 )
+ trackMode = K3bTrack::MODE2;
+ }
+ else
+ trackType = K3bTrack::AUDIO;
+
+ lastTrack = K3bTrack( startSec, startSec, trackType, trackMode );
+ firstEntry = false;
+ }
+ else
+ {
+ kdDebug() << "(K3bCdDevice) Could not parse mode of track: " << str.mid( start ) << endl;
+ }
+ }
+ else
+ {
+ kdDebug() << "(K3bCdDevice) Could not parse control of track: " << str.mid( start, end-start ) << endl;
+ }
+ }
+ else
+ {
+ kdDebug() << "(K3bCdDevice) Could not parse start sector of track: " << str.mid( start, end-start) << endl;
+ }
+ }
+
+ }
+ // close and delete tmp file
+ tmp.close();
+
+ }
+ // skip further tests if there is no disk
+ if (m_driveReady != NO_DISK && m_driveReady != NO_INFO)
+ {
+
+ KTempFile tmpfile2;
+ tmpfile2.setAutoDelete(true);
+
+ // call cdrdao disk-info to get disk capacities, device status, and dsik type
+ call = "/bin/sh -c \"cdrdao disk-info --device " + QString("%1").arg( busTargetLun() ) + " --driver " + cdrdaoDriver() + " > " + tmpfile2.name() + " 2>&1 \"";
+ kdDebug() << "(K3bCdDevice) Reading remaining disk size : " << call << endl;
+ system(call.latin1());
+
+ // read tmp file line by line
+ QFile tmp2(tmpfile2.name());
+ if ( tmp2.open( IO_ReadOnly ) )
+ {
+ QTextStream stream( &tmp2 );
+ while ( !stream.eof() )
+ {
+ QString str = stream.readLine();
+ kdDebug() << "(K3bCdDevice): " << str << endl;
+
+ // remaining capacity available?
+ if ( str.contains( "Remaining Capacity :" ) )
+ {
+ // cdrdao produces the following outout:
+ // <remaining time> ( <remaining blocks> blocks, <remaining size> MB)
+
+ int start = str.find("(" )+1;
+ int end = str.find( " ", start );
+
+ bool ok;
+ int remaining = str.mid( start, end-start ).toInt(&ok);
+ if( ok )
+ {
+ m_remainingSize = remaining-1;
+ }
+ else
+ kdDebug() << "(K3bCdDevice) Could not parse remaining time: " << str.mid( start, end-start) << endl;
+ }
+
+ // total capacity available?
+ else if ( str.contains( "Total Capacity :" ) )
+ {
+ // cdrdao produces the following outout:
+ // <time> ( <blocks> blocks, <size> MB)
+
+ int start = str.find("(" )+1;
+ int end = str.find( " ", start );
+
+ bool ok;
+ int total = str.mid( start, end-start ).toInt(&ok);
+ if( ok )
+ {
+ m_discSize = total-1;
+ }
+ else
+ kdDebug() << "(K3bCdDevice) Could not parse total time: " << str.mid( start, end-start) << endl;
+ }
+
+ // is it an empty CD?
+ else if (str.startsWith("CD-R empty : yes"))
+ {
+ m_deviceStatus = EMPTY;
+ kdDebug() << "(K3bCdDevice) device status: empty" << endl;
+ }
+
+ // is the last session closed?
+ else if (str.startsWith("Appendable : no"))
+ {
+ m_deviceStatus = COMPLETE;
+ kdDebug() << "(K3bCdDevice) device status: complete" << endl;
+ }
+
+ // is the last session open?
+ else if (str.startsWith("Appendable : yes"))
+ {
+ m_deviceStatus = APPENDABLE;
+ kdDebug() << "(K3bCdDevice) device status: appendable" << endl;
+ }
+
+ // is it a cd-rw?
+ else if (str.startsWith("CD-RW : yes"))
+ {
+ kdDebug() << "(K3bCdDevice) cd is erasable" << endl;
+ m_rewritableCd = 1;
+ }
+
+ }
+ // close and delete tmp2 file
+ tmp2.close();
+ }
+
+ if (m_discSize.toString() == "00:00:00") // cdrdao failed somehow
+ {
+
+ KTempFile tmpfile3;
+ tmpfile3.setAutoDelete(true);
+
+ //create call
+ QString call = "/bin/sh -c \"cdrecord -atip " + QString("dev=%1").arg( busTargetLun() ) + " > " + tmpfile3.name() + " 2>&1 \"";
+ kdDebug() << "(K3bCdDevice) Reading disk size : " << call << endl;
+ system(call.latin1());
+
+ // read tmp file line by line
+ K3bTrack lastTrack;
+ QFile tmp3(tmpfile3.name());
+ if ( tmp3.open( IO_ReadOnly ) )
+ {
+ QTextStream stream( &tmp3 );
+ while ( !stream.eof() )
+ {
+ QString str = stream.readLine();
+ if (str.startsWith(" Is erasable"))
+ {
+ m_rewritableCd = 1;
+ }
+ else if( str.startsWith(" ATIP start of lead out:") )
+ {
+ // cdrecord produces the following outout:
+ // <tracknumber> lba: <startSector> (<...>) <startTime> adr: 1 control: <trackType> mode: <trackMode>
+ // the last tracknumber will always be "lout", the leadout of the cd which we only use to determine the
+ // length of the last track
+
+ // we just want the startSector, the trackType, and the trackMode
+ int start = 6; // skip the "track:"
+ start = str.find(":", start )+1;
+ int end = str.find( "(", start )-1;
+
+ bool ok;
+ int leadOut = str.mid( start, end-start ).toInt(&ok);
+ if( ok )
+ m_discSize = leadOut;
+ else
+ kdDebug() << "(K3bCdDevice) Could not parse lead out: " << str.mid( start, end-start) << endl;
+ }
+
+ }
+ // close and delete tmp3 file
+ tmp3.close();
+ }
+ }
+
+ }
+
+ // print out cd data
+ kdDebug() << "(K3bCdDevice) disk size: " << m_discSize.toString() << endl;
+ kdDebug() << "(K3bCdDevice) remaining size: " << m_remainingSize.toString() << endl;
+ kdDebug() << "(K3bCdDevice) total size: " << m_discSize.toString() << endl;
+ kdDebug() << "(K3bCdDevice) drive ready: " << m_driveReady << endl;
+
+ if (m_deviceStatus == EMPTY)
+ kdDebug() << "(K3bCdDevice) device status: empty" << endl;
+ else if (m_deviceStatus == APPENDABLE)
+ kdDebug() << "(K3bCdDevice) device status: appendable" << endl;
+ else if (m_deviceStatus == COMPLETE)
+ kdDebug() << "(K3bCdDevice) device status: complete" << endl;
+ else if (m_deviceStatus == NO_DISK)
+ kdDebug() << "(K3bCdDevice) device status: no disk" << endl;
+ else if (m_deviceStatus == NO_INFO)
+ kdDebug() << "(K3bCdDevice) device status: no info" << endl;
+ if (m_rewritableCd)
+ kdDebug() << "(K3bCdDevice) cd is erasable" << endl;
+ else
+ kdDebug() << "(K3bCdDevice) cd is not erasable" << endl;
+
+ // reset timer
+ m_lastRefresh = QDateTime::currentDateTime();
+}
+
+void K3bDevice::CdDevice::addDeviceType(DeviceType type)
+{
+ d->deviceType |= type;
+}
+
+int bsd_open_close_device(int bus, int target, int lun, bool eject)
+{
+ union ccb *ccb;
+ int error = 0;
+ struct cam_device *cam_dev = cam_open_btl(bus, target, lun, O_RDWR, NULL);
+ ccb = cam_getccb(cam_dev);
+ bool startstop = false;
+ scsi_start_stop(&ccb->csio, 1, NULL, startstop ? MSG_SIMPLE_Q_TAG :MSG_ORDERED_Q_TAG, startstop,
+ eject, 0, SSD_FULL_SIZE, 120000);
+ ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
+ if (cam_send_ccb(cam_dev, ccb) < 0) {
+ perror("error sending start unit");
+
+ cam_freeccb(ccb);
+ return(1);
+ }
+
+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
+ if (startstop)
+ {
+ kdDebug() << "(K3bCdDevice) bsd_open_close_device: Unit started successfully" << endl;
+ if (eject)
+ kdDebug() << "(K3bCdDevice) bsd_open_close_device: Media loaded" << endl;
+ }
+ else
+ {
+ kdDebug() << "(K3bCdDevice) bsd_open_close_device: Unit stopped successfully" << endl;
+ if (eject)
+ kdDebug() << "(K3bCdDevice) bsd_open_close_device: Media ejected" << endl;
+ }
+ else
+ {
+ error = 1;
+ if (startstop)
+ kdDebug() << "(K3bCdDevice) bsd_open_close_device: Error received from start unit command" << endl;
+ else
+ kdDebug() << "(K3bCdDevice) bsd_open_close_device: Error received from stop unit command" << endl;
+ }
+ cam_freeccb(ccb);
+ return error;
+}
+
+#endif