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"