File indexing completed on 2024-05-12 04:51:08

0001 /*
0002     SPDX-FileCopyrightText: 1998-2008 Sebastian Trueg <trueg@k3b.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "k3bmovixdocpreparer.h"
0008 #include "k3bmovixdoc.h"
0009 #include "k3bmovixprogram.h"
0010 #include "k3bmovixfileitem.h"
0011 #include "k3bcore.h"
0012 #include "k3bdiritem.h"
0013 #include "k3bfileitem.h"
0014 #include "k3bbootitem.h"
0015 #include "k3bexternalbinmanager.h"
0016 #include "k3bisoimager.h"
0017 #include "k3b_i18n.h"
0018 
0019 #include <KIO/Global>
0020 
0021 #include <QDebug>
0022 #include <QDir>
0023 #include <QStack>
0024 #include <QTemporaryFile>
0025 #include <QTextStream>
0026 
0027 
0028 class K3b::MovixDocPreparer::Private
0029 {
0030 public:
0031     Private()
0032         : doc(0),
0033           playlistFile(0),
0034           isolinuxConfigFile(0),
0035           movixRcFile(0),
0036           isolinuxDir(0),
0037           movixDir(0),
0038           mplayerDir(0),
0039           playlistFileItem(0),
0040           structuresCreated(false) {
0041     }
0042 
0043     K3b::MovixDoc* doc;
0044     const K3b::MovixBin* eMovixBin;
0045 
0046     QTemporaryFile* playlistFile;
0047     QTemporaryFile* isolinuxConfigFile;
0048     QTemporaryFile* movixRcFile;
0049 
0050     K3b::DirItem* isolinuxDir;
0051     K3b::DirItem* movixDir;
0052     K3b::DirItem* mplayerDir;
0053     K3b::FileItem* playlistFileItem;
0054 
0055     QStack<K3b::DataItem*> newMovixItems;
0056 
0057     bool structuresCreated;
0058 };
0059 
0060 
0061 K3b::MovixDocPreparer::MovixDocPreparer( K3b::MovixDoc* doc, K3b::JobHandler* jh, QObject* parent )
0062     : K3b::Job( jh, parent )
0063 {
0064     d = new Private();
0065     d->doc = doc;
0066 }
0067 
0068 
0069 K3b::MovixDocPreparer::~MovixDocPreparer()
0070 {
0071     removeMovixStructures();
0072     delete d;
0073 }
0074 
0075 
0076 K3b::MovixDoc* K3b::MovixDocPreparer::doc() const
0077 {
0078     return d->doc;
0079 }
0080 
0081 
0082 void K3b::MovixDocPreparer::start()
0083 {
0084     qDebug();
0085     jobStarted();
0086 
0087     bool success = true;
0088     if( d->structuresCreated )
0089         removeMovixStructures();
0090     else
0091         success = createMovixStructures();
0092 
0093     jobFinished(success);
0094 }
0095 
0096 
0097 void K3b::MovixDocPreparer::cancel()
0098 {
0099     // do nothing...
0100 }
0101 
0102 
0103 bool K3b::MovixDocPreparer::createMovixStructures()
0104 {
0105     qDebug();
0106     removeMovixStructures();
0107 
0108     if( doc() ) {
0109         doc()->setMultiSessionMode( K3b::DataDoc::NONE );
0110         doc()->prepareFilenames();
0111     }
0112 
0113     d->eMovixBin = dynamic_cast<const K3b::MovixBin*>( k3bcore->externalBinManager()->binObject("eMovix") );
0114     if( d->eMovixBin ) {
0115         bool success = false;
0116         if( d->eMovixBin->version() >= K3b::Version( 0, 9, 0 ) )
0117             success = addMovixFilesNew();
0118         else
0119             success = addMovixFiles();
0120 
0121         d->structuresCreated = success;
0122         return success;
0123     }
0124     else {
0125         emit infoMessage( i18n("Could not find a valid eMovix installation."), MessageError );
0126         return false;
0127     }
0128 }
0129 
0130 
0131 void K3b::MovixDocPreparer::removeMovixStructures()
0132 {
0133     qDebug();
0134     // remove movix files from doc
0135     // the dataitems do the cleanup in the doc
0136     delete d->movixDir;
0137     delete d->isolinuxDir;
0138     delete d->mplayerDir;
0139     delete d->playlistFileItem;
0140 
0141     d->movixDir = 0;
0142     d->isolinuxDir = 0;
0143     d->mplayerDir = 0;
0144     d->playlistFileItem = 0;
0145 
0146     while( !d->newMovixItems.empty() ) {
0147         delete d->newMovixItems.pop();
0148     }
0149 
0150     // remove all the temp files
0151     delete d->playlistFile;
0152     delete d->isolinuxConfigFile;
0153     delete d->movixRcFile;
0154 
0155     d->playlistFile = 0;
0156     d->isolinuxConfigFile = 0;
0157     d->movixRcFile = 0;
0158 
0159     d->structuresCreated = false;
0160 }
0161 
0162 
0163 bool K3b::MovixDocPreparer::writePlaylistFile()
0164 {
0165     delete d->playlistFile;
0166     d->playlistFile = new QTemporaryFile();
0167     d->playlistFile->open();
0168 
0169     QTextStream s( d->playlistFile );
0170 
0171     QList<K3b::MovixFileItem*> movixFileItems = d->doc->movixFileItems();
0172 
0173     Q_FOREACH( K3b::MovixFileItem* item, movixFileItems ) {
0174         s << "/cdrom/";
0175         s << item->writtenName();
0176         s << Qt::endl;
0177     }
0178 
0179     d->playlistFile->close();
0180     return true;
0181 }
0182 
0183 
0184 bool K3b::MovixDocPreparer::writeIsolinuxConfigFile( const QString& originalPath )
0185 {
0186     delete d->isolinuxConfigFile;
0187     d->isolinuxConfigFile = new QTemporaryFile();
0188     d->isolinuxConfigFile->open();
0189 
0190     QTextStream s( d->isolinuxConfigFile );
0191 
0192     // now open the default isolinux.cfg and copy everything except the first line which contains
0193     // the default boot label
0194     QFile f( originalPath );
0195     if( f.open( QIODevice::ReadOnly ) ) {
0196 
0197         QTextStream isolinuxConfigOrig( &f );
0198 
0199         if(  d->doc->defaultBootLabel() != i18n("default") ) {
0200             isolinuxConfigOrig.readLine(); // skip first line
0201             s << "default " << d->doc->defaultBootLabel()  << Qt::endl;
0202         }
0203 
0204         QString line = isolinuxConfigOrig.readLine();
0205         while( !line.isNull() ) {
0206             s << line << Qt::endl;
0207             line = isolinuxConfigOrig.readLine();
0208         }
0209 
0210         d->isolinuxConfigFile->close();
0211         return true;
0212     }
0213     else
0214         return false;
0215 }
0216 
0217 
0218 bool K3b::MovixDocPreparer::writeMovixRcFile()
0219 {
0220     delete d->movixRcFile;
0221     d->movixRcFile = new QTemporaryFile();
0222     d->movixRcFile->open();
0223 
0224     QTextStream s( d->movixRcFile );
0225 
0226     if( !d->doc->additionalMPlayerOptions().isEmpty() )
0227         s << "extra-mplayer-options=" << d->doc->additionalMPlayerOptions() << Qt::endl;
0228     if( !d->doc->unwantedMPlayerOptions().isEmpty() )
0229         s << "unwanted-mplayer-options=" << d->doc->unwantedMPlayerOptions() << Qt::endl;
0230     s << "loop=" << d->doc->loopPlaylist() << Qt::endl;
0231     if( d->doc->shutdown() )
0232         s << "shut=y" << Qt::endl;
0233     if( d->doc->reboot() )
0234         s << "reboot=y" << Qt::endl;
0235     if( d->doc->ejectDisk() )
0236         s << "eject=y" << Qt::endl;
0237     if( d->doc->randomPlay() )
0238         s << "random=y" << Qt::endl;
0239     if( d->doc->noDma() )
0240         s << "dma=n" << Qt::endl;
0241 
0242     d->movixRcFile->close();
0243     return true;
0244 }
0245 
0246 
0247 bool K3b::MovixDocPreparer::addMovixFiles()
0248 {
0249     // first of all we create the directories
0250     d->isolinuxDir = new K3b::DirItem( "isolinux" );
0251     d->movixDir = new K3b::DirItem( "movix" );
0252     if (d->doc == Q_NULLPTR)
0253         return false;
0254     d->doc->root()->addDataItem( d->isolinuxDir );
0255     d->doc->root()->addDataItem( d->movixDir );
0256     K3b::DirItem* kernelDir = d->doc->addEmptyDir( "kernel", d->isolinuxDir );
0257 
0258     // add the linux kernel
0259     kernelDir->addDataItem( new K3b::FileItem( d->eMovixBin->path() + "/isolinux/kernel/vmlinuz", *d->doc ) );
0260 
0261     // add the boot image
0262     K3b::BootItem* bootItem = d->doc->createBootItem( d->eMovixBin->path() + "/isolinux/isolinux.bin",
0263                                                     d->isolinuxDir );
0264     bootItem->setImageType( K3b::BootItem::NONE );
0265     bootItem->setLoadSize( 4 );
0266     bootItem->setBootInfoTable(true);
0267 
0268     // some sort weights as defined in isolinux
0269     d->isolinuxDir->setSortWeight( 100 );
0270     kernelDir->setSortWeight( 50 );
0271     bootItem->setSortWeight( 200 );
0272 
0273     // rename the boot catalog file
0274     d->doc->bootCataloge()->setK3bName( "isolinux.boot" );
0275 
0276     // the following sucks! Redesign it!
0277 
0278     // add all the isolinux files
0279     QStringList isolinuxFiles = d->eMovixBin->isolinuxFiles();
0280     isolinuxFiles.removeOne( "isolinux.bin" );
0281     isolinuxFiles.removeOne( "isolinux.cfg" );
0282     isolinuxFiles.removeOne( "kernel/vmlinuz" );
0283     for( QStringList::const_iterator it = isolinuxFiles.constBegin();
0284          it != isolinuxFiles.constEnd(); ++it ) {
0285         QString path = d->eMovixBin->path() + "/isolinux/" + *it;
0286         d->isolinuxDir->addDataItem( new K3b::FileItem( path, *d->doc ) );
0287     }
0288 
0289     const QStringList& movixFiles = d->eMovixBin->movixFiles();
0290     for( QStringList::const_iterator it = movixFiles.constBegin();
0291          it != movixFiles.constEnd(); ++it ) {
0292         QString path = d->eMovixBin->path() + "/movix/" + *it;
0293         d->movixDir->addDataItem( new K3b::FileItem( path, *d->doc ) );
0294     }
0295 
0296     // add doku files
0297     QString path = d->eMovixBin->languageDir( d->doc->bootMessageLanguage() );
0298     QDir dir(path);
0299     QStringList helpFiles = dir.entryList(QDir::Files);
0300     for( QStringList::const_iterator it = helpFiles.constBegin();
0301          it != helpFiles.constEnd(); ++it ) {
0302         // some emovix installations include backup-files, no one's perfect ;)
0303         if( !(*it).endsWith( '~' ) )
0304             d->isolinuxDir->addDataItem( new K3b::FileItem( path + '/' + *it, *d->doc ) );
0305     }
0306 
0307 
0308     // add subtitle font dir
0309     if( !d->doc->subtitleFontset().isEmpty() &&
0310         d->doc->subtitleFontset() != i18n("none") ) {
0311         d->mplayerDir = new K3b::DirItem( "mplayer" );
0312         d->doc->root()->addDataItem( d->mplayerDir );
0313 
0314         QString fontPath = d->eMovixBin->subtitleFontDir( d->doc->subtitleFontset() );
0315         QFileInfo fontType( fontPath );
0316         if( fontType.isDir() ) {
0317             K3b::DirItem* fontDir = new K3b::DirItem( "font" );
0318             d->mplayerDir->addDataItem( fontDir );
0319             QDir dir( fontPath );
0320             QStringList fontFiles = dir.entryList( QDir::Files );
0321             for( QStringList::const_iterator it = fontFiles.constBegin();
0322                  it != fontFiles.constEnd(); ++it ) {
0323                 fontDir->addDataItem( new K3b::FileItem( fontPath + '/' + *it, *d->doc ) );
0324             }
0325         }
0326         else {
0327             // just a ttf file
0328             // needs to be named: subfont.ttf and needs to be placed in mplayer/
0329             // instead of mplayer/font
0330             d->mplayerDir->addDataItem( new K3b::FileItem( fontPath, *d->doc, "subfont.ttf" ) );
0331         }
0332     }
0333 
0334 
0335     // add movix-config-file and boot-config file
0336     if( writeMovixRcFile() &&
0337         writeIsolinuxConfigFile( d->eMovixBin->path() + "/isolinux/isolinux.cfg" ) &&
0338         writePlaylistFile() ) {
0339 
0340         d->movixDir->addDataItem( new K3b::FileItem( d->movixRcFile->fileName(), *d->doc, "movixrc" ) );
0341         d->isolinuxDir->addDataItem( new K3b::FileItem( d->isolinuxConfigFile->fileName(), *d->doc, "isolinux.cfg" ) );
0342         d->playlistFileItem = new K3b::FileItem( d->playlistFile->fileName(), *d->doc, "movix.list" );
0343         d->doc->root()->addDataItem( d->playlistFileItem );
0344 
0345         return true;
0346     }
0347     else
0348         return false;
0349 }
0350 
0351 
0352 bool K3b::MovixDocPreparer::addMovixFilesNew()
0353 {
0354     // 1. get a list of files from the movixbin
0355     // 2. create file items (replace isolinux.cfg with the one created above)
0356     // 3. add movixrc and movix.list files
0357     // 4. set weights for isolinux files
0358 
0359     if (d->doc == Q_NULLPTR)
0360         return false;
0361     // FIXME: use the settings from the doc
0362     const QStringList files = d->eMovixBin->files( d->doc->keyboardLayout(),
0363                                              d->doc->subtitleFontset(),
0364                                              d->doc->audioBackground(),
0365                                              d->doc->bootMessageLanguage(),
0366                                              QStringList() << "all" /*d->doc->codecs()*/ ); // for now we simply don't allow selection
0367 
0368     for( QStringList::ConstIterator it = files.constBegin(); it != files.constEnd(); ++it ) {
0369         QString docPath = (*it).section( ' ', 0, 0 );
0370         QString filePath = (*it).section( ' ', 1, 1 );
0371         QString fileName = filePath.section( '/', -1 );
0372 
0373         if( fileName == "isolinux.cfg" ) {
0374             // replace the local file with our modified one
0375             if( writeIsolinuxConfigFile( filePath ) )
0376                 createItem( d->isolinuxConfigFile->fileName(), docPath )->setK3bName( "isolinux.cfg" );
0377             else
0378                 return false;
0379         }
0380         else if( fileName == "isolinux.bin" ) {
0381             // create boot item (no need to remember this since it's in a dir which will be removed
0382             // anyway)
0383             K3b::BootItem* bootItem = d->doc->createBootItem( filePath, createDir(docPath) );
0384             bootItem->setImageType( K3b::BootItem::NONE );
0385             bootItem->setLoadSize( 4 );
0386             bootItem->setBootInfoTable(true);
0387 
0388             // set the proper sort weight
0389             bootItem->setSortWeight( 200 );
0390             bootItem->parent()->setSortWeight( 100 );
0391         }
0392         else if( fileName != "movixrc" ) { // we create our own movixrc
0393             K3b::FileItem* item = createItem( filePath, docPath );
0394 
0395             // Truetype subtitle fonts needs to be named subfont.ttf
0396             if( fileName == d->doc->subtitleFontset() + ".ttf" ) {
0397                 item->setK3bName( "subfont.ttf" );
0398             }
0399             else if( fileName == "vmlinuz" )
0400                 item->setSortWeight( 50 );
0401         }
0402     }
0403 
0404     // Some distributions (such as Gentoo for example) do use the win32codecs package instead of the
0405     // eMovix supplied codecs. These codecs are not picked up by the movix-conf script
0406     K3b::DirItem* codecDir = dynamic_cast<K3b::DirItem*>( d->doc->root()->findByPath( "/eMoviX/codecs" ) );
0407     if( !codecDir || codecDir->isEmpty() ) {
0408         QDir localCodecDir( d->eMovixBin->movixDataDir() + "/codecs" );
0409         if( localCodecDir.exists() ) {
0410             QStringList codecFiles = localCodecDir.entryList( QDir::Files );
0411             for( QStringList::const_iterator it = codecFiles.constBegin(); it != codecFiles.constEnd(); ++it )
0412                 createItem( localCodecDir.path() + '/' + *it, "/eMoviX/codecs" );
0413         }
0414     }
0415 
0416     if( writePlaylistFile() && writeMovixRcFile() ) {
0417         // add the two items that are not listed by the script
0418         createItem( d->movixRcFile->fileName(), "/eMoviX/movix" )->setK3bName( "movixrc" );
0419         createItem( d->playlistFile->fileName(), "/" )->setK3bName( "movix.list" );
0420         return true;
0421     }
0422     else
0423         return false;
0424 }
0425 
0426 
0427 K3b::FileItem* K3b::MovixDocPreparer::createItem( const QString& localPath, const QString& docPath )
0428 {
0429     // make sure the path in the doc exists
0430     K3b::DirItem* dir = createDir( docPath );
0431 
0432     // create the file in dir
0433     K3b::FileItem* item = new K3b::FileItem( localPath, *d->doc );
0434     dir->addDataItem( item );
0435 
0436     // remember the item to remove it because the dir cannot be removed
0437     if( dir == d->doc->root() )
0438         d->newMovixItems.push( item );
0439 
0440     return item;
0441 }
0442 
0443 
0444 K3b::DirItem* K3b::MovixDocPreparer::createDir( const QString& docPath )
0445 {
0446     QStringList docPathSections = docPath.split( '/', Qt::SkipEmptyParts );
0447     K3b::DirItem* dir = d->doc->root();
0448     for( QStringList::ConstIterator it = docPathSections.constBegin(); it != docPathSections.constEnd(); ++it ) {
0449         K3b::DataItem* next = dir->find( *it );
0450         if( !next ) {
0451             DirItem* newDir = new K3b::DirItem( *it );
0452             dir->addDataItem( newDir );
0453             dir = newDir;
0454         } else if( next->isDir() ) {
0455             dir = static_cast<K3b::DirItem*>( next );
0456         } else {
0457             qCritical() << "(K3b::MovixDocPreparer) found non-dir item where a dir was needed." << Qt::endl;
0458             return 0;
0459         }
0460     }
0461 
0462     // remember the dir to remove it
0463     if( dir != d->doc->root() ) {
0464         K3b::DirItem* delDir = dir;
0465         while( delDir->parent() != d->doc->root() )
0466             delDir = delDir->parent();
0467         if( d->newMovixItems.lastIndexOf( delDir ) == -1 )
0468             d->newMovixItems.push( delDir );
0469     }
0470 
0471     return dir;
0472 }
0473 
0474 #include "moc_k3bmovixdocpreparer.cpp"