File indexing completed on 2024-05-12 04:51:06
0001 /* 0002 SPDX-FileCopyrightText: 1998-2007 Sebastian Trueg <trueg@k3b.org> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #include "k3bmsinfofetcher.h" 0007 0008 #include "k3bexternalbinmanager.h" 0009 #include "k3bdevicemanager.h" 0010 #include "k3bdevicehandler.h" 0011 #include "k3bdevice.h" 0012 #include "k3bcore.h" 0013 #include "k3bglobals.h" 0014 #include "k3biso9660.h" 0015 #include "k3bprocess.h" 0016 #include "k3b_i18n.h" 0017 0018 #include <KProcess> 0019 0020 #include <QDebug> 0021 #include <QStringList> 0022 0023 0024 K3b::MsInfoFetcher::MsInfoFetcher( K3b::JobHandler* jh, QObject* parent ) 0025 : K3b::Job( jh, parent ), 0026 m_process(0), 0027 m_device(0), 0028 m_dvd(false) 0029 { 0030 } 0031 0032 0033 K3b::MsInfoFetcher::~MsInfoFetcher() 0034 { 0035 delete m_process; 0036 } 0037 0038 0039 void K3b::MsInfoFetcher::start() 0040 { 0041 jobStarted(); 0042 0043 emit infoMessage( i18n("Searching previous session"), K3b::Job::MessageInfo ); 0044 0045 if( !k3bcore->externalBinManager()->foundBin( "cdrecord" ) ) { 0046 qDebug() << "(K3b::MsInfoFetcher) could not find cdrecord executable"; 0047 emit infoMessage( i18n("Could not find %1 executable.",QString("cdrecord")), K3b::Job::MessageError ); 0048 jobFinished(false); 0049 return; 0050 } 0051 0052 if( m_device == 0 ) { 0053 qDebug() << "(K3b::MsInfoFetcher) internal error: No device set!"; 0054 jobFinished(false); 0055 return; 0056 } 0057 0058 // 0059 // first we try to determine if it is a dvd. If so we need to 0060 // read the info on our own 0061 // 0062 0063 connect( K3b::Device::sendCommand( K3b::Device::DeviceHandler::CommandDiskInfo, m_device ), 0064 SIGNAL(finished(K3b::Device::DeviceHandler*)), 0065 this, 0066 SLOT(slotMediaDetectionFinished(K3b::Device::DeviceHandler*)) ); 0067 } 0068 0069 0070 void K3b::MsInfoFetcher::getMsInfo() 0071 { 0072 delete m_process; 0073 m_process = new Process(this); 0074 0075 const K3b::ExternalBin* bin = 0; 0076 if( m_dvd ) { 0077 // already handled 0078 } 0079 else { 0080 bin = k3bcore->externalBinManager()->binObject( "cdrecord" ); 0081 0082 if( !bin ) { 0083 emit infoMessage( i18n("Could not find %1 executable.", m_dvd ? QString("dvdrecord") : QString("cdrecord" )), MessageError ); 0084 jobFinished(false); 0085 return; 0086 } 0087 0088 *m_process << bin->path(); 0089 0090 // add the device (e.g. /dev/sg1) 0091 *m_process << QString("dev=") + K3b::externalBinDeviceParameter(m_device, bin); 0092 0093 *m_process << "-msinfo"; 0094 0095 // additional user parameters from config 0096 *m_process << bin->userParameters(); 0097 0098 qDebug() << "***** " << bin->name() << " parameters:\n"; 0099 QStringList args = m_process->program(); 0100 args.removeFirst(); 0101 QString s = args.join(" "); 0102 qDebug() << s << Qt::flush; 0103 emit debuggingOutput( "msinfo command:", s ); 0104 0105 0106 connect( m_process, SIGNAL(finished(int)), 0107 this, SLOT(slotProcessExited()) ); 0108 0109 m_msInfo = QString(); 0110 m_collectedOutput = QString(); 0111 m_canceled = false; 0112 0113 m_process->start( KProcess::OnlyStdoutChannel ); 0114 } 0115 } 0116 0117 0118 void K3b::MsInfoFetcher::slotMediaDetectionFinished( K3b::Device::DeviceHandler* h ) 0119 { 0120 if( h->success() ) { 0121 m_dvd = Device::isDvdMedia( h->diskInfo().mediaType() ); 0122 } 0123 else { 0124 // for now we just default to cd and go on with the detecting 0125 m_dvd = false; 0126 } 0127 0128 if( m_dvd ) { 0129 if( h->diskInfo().mediaType() & (K3b::Device::MEDIA_DVD_PLUS_RW|K3b::Device::MEDIA_DVD_RW_OVWR) ) { 0130 // get info from iso filesystem 0131 K3b::Iso9660 iso( m_device, h->toc().last().firstSector().lba() ); 0132 if( iso.open() ) { 0133 unsigned long long nextSession = iso.primaryDescriptor().volumeSpaceSize; 0134 // pad to closest 32K boundary 0135 nextSession += 15; 0136 nextSession /= 16; 0137 nextSession *= 16; 0138 m_msInfo = QString::asprintf( "16,%llu", nextSession ); 0139 0140 jobFinished( true ); 0141 } 0142 else { 0143 emit infoMessage( i18n("Could not open ISO 9660 filesystem in %1.", 0144 m_device->vendor() + ' ' + m_device->description() ), MessageError ); 0145 jobFinished( false ); 0146 } 0147 } 0148 else { 0149 unsigned int lastSessionStart, nextWritableAdress; 0150 if( m_device->getNextWritableAdress( lastSessionStart, nextWritableAdress ) ) { 0151 m_msInfo = QString::asprintf( "%u,%u", lastSessionStart+16, nextWritableAdress ); 0152 jobFinished( true ); 0153 } 0154 else { 0155 emit infoMessage( i18n("Could not determine next writable address."), MessageError ); 0156 jobFinished( false ); 0157 } 0158 } 0159 } 0160 else // call cdrecord 0161 getMsInfo(); 0162 } 0163 0164 0165 void K3b::MsInfoFetcher::slotProcessExited() 0166 { 0167 if( m_canceled ) 0168 return; 0169 0170 if (m_process->error() == QProcess::FailedToStart) { 0171 emit infoMessage( i18n("Could not start %1", m_process->program().at(0)), K3b::Job::MessageError ); 0172 jobFinished(false); 0173 return; 0174 } 0175 0176 qDebug() << "(K3b::MsInfoFetcher) msinfo fetched"; 0177 0178 m_collectedOutput = QString::fromLocal8Bit( m_process->readAllStandardOutput() ); 0179 0180 emit debuggingOutput( "msinfo", m_collectedOutput ); 0181 0182 // now parse the output 0183 QString firstLine = m_collectedOutput.left( m_collectedOutput.indexOf('\n') ); 0184 QStringList list = firstLine.split( ',' ); 0185 if( list.count() == 2 ) { 0186 bool ok1, ok2; 0187 m_lastSessionStart = list.first().toInt( &ok1 ); 0188 m_nextSessionStart = list[1].toInt( &ok2 ); 0189 if( ok1 && ok2 ) 0190 m_msInfo = firstLine.trimmed(); 0191 else 0192 m_msInfo = QString(); 0193 } 0194 else { 0195 m_msInfo = QString(); 0196 } 0197 0198 qDebug() << "(K3b::MsInfoFetcher) msinfo parsed: " << m_msInfo; 0199 0200 if( m_msInfo.isEmpty() ) { 0201 emit infoMessage( i18n("Could not retrieve multisession information from disk."), K3b::Job::MessageError ); 0202 emit infoMessage( i18n("The disk is either empty or not appendable."), K3b::Job::MessageError ); 0203 jobFinished(false); 0204 } 0205 else { 0206 jobFinished(true); 0207 } 0208 } 0209 0210 0211 void K3b::MsInfoFetcher::cancel() 0212 { 0213 // FIXME: this does not work if the devicehandler is running 0214 0215 if( m_process ) 0216 if( m_process->state() != QProcess::NotRunning) { 0217 m_canceled = true; 0218 m_process->terminate(); 0219 emit canceled(); 0220 jobFinished(false); 0221 } 0222 } 0223 0224 #include "moc_k3bmsinfofetcher.cpp"