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"