void ProjectPackager::finishPack(int exitCode, QProcess::ExitStatus) { RG_DEBUG << "ProjectPackager::finishPack - exit code: " << exitCode; if (exitCode == 0) { delete m_process; } else { puke(tr("<qt><p>Encoding and compressing files failed with exit status %1. Checking %2 for the line that ends with \"exit %1\" may be useful for diagnostic purposes.</p>%3</qt>").arg(exitCode).arg(m_script.fileName()).arg(m_abortText)); return; } m_script.remove(); // remove the original file which is now safely in a package // // Well. Oops. No, m_filename is the .rgp version, so we need to remove // the .rg file that is now safely in a package, which was saved by // RosegardenMainWindow at the start of all this QFileInfo fi(m_filename); QString dirname = fi.path(); QString basename = QString("%1/%2.rg").arg(dirname).arg(fi.baseName()); if (!QFile::remove(basename)) { puke(tr("<qt>Could not remove<br>%1<br><br>%2</qt>").arg(basename).arg(m_abortText)); return; } rmdirRecursive(m_packTmpDirName); accept(); exitCode++; // break point }
void ProjectPackager::reject() { RG_DEBUG << "User pressed cancel"; rmdirRecursive(m_packTmpDirName); QDialog::reject(); }
ReturnStatus FileMetaDAO::delDir(const std::string &path, uint64_t *pDelta) { assert(pDelta); ReturnStatus rs; uint64_t delta = 0; rs = rmdirRecursive(path, pDelta); if (!rs.success()) { ERROR_LOG("path %s, rmdirRecursive() error", path.c_str()); } return rs; }
/////////////////////////// // // // PACKING OPERATIONS // // // /////////////////////////// void ProjectPackager::runPack() { RG_DEBUG << "ProjectPackager::runPack()"; m_info->setText(tr("Packing project...")); // go into spinner mode m_progress->setMaximum(0); QStringList audioFiles = getAudioFiles(); // the base tmp directory where we'll assemble all the files m_packTmpDirName = QString("%1/rosegarden-project-packager-tmp").arg(QDir::homePath()); // the data directory where audio and other files will go QFileInfo fi(m_filename); m_packDataDirName = fi.baseName(); RG_DEBUG << "using tmp data directory: " << m_packTmpDirName << "/" << m_packDataDirName; QDir tmpDir(m_packTmpDirName); // get the original filename saved by RosegardenMainWindow and the name of // the new one we'll be including in the bundle (name isn't changing, path // component changes from one to the other) // QFileInfo::baseName() given /tmp/foo/bar/rat.rgp returns rat // // m_filename comes in already having an .rgp extension, but the file // was saved .rg QString oldName = QString("%1/%2.rg").arg(fi.path()).arg(fi.baseName()); QString newName = QString("%1/%2.rg").arg(m_packTmpDirName).arg(fi.baseName()); // if the tmp directory already exists, just hose it rmdirRecursive(m_packTmpDirName); // make the temporary working directory if (tmpDir.mkdir(m_packTmpDirName)) { } else { puke(tr("<qt><p>Could not create temporary working directory.</p>%1</qt>").arg(m_abortText)); return; } m_info->setText(tr("Copying audio files...")); // leave spinner mode m_progress->setMaximum(100); m_progress->setValue(0); // count total audio files int af = 0; QStringList::const_iterator si; for (si = audioFiles.constBegin(); si != audioFiles.constEnd(); ++si) af++; int afStep = ((af == 0) ? 1 : (100 / af)); // make the data subdir tmpDir.mkdir(m_packDataDirName); // copy the audio files (do not remove the originals!) af = 0; for (si = audioFiles.constBegin(); si != audioFiles.constEnd(); ++si) { // comes in with full path and filename QString srcFile = (*si); QString srcFilePk = QString("%1.pk").arg(srcFile); // needs the filename split away from the path, so we can replace the // path with the new one QFileInfo fi(*si); QString filename = QString("%1.%2").arg(fi.baseName()).arg(fi.completeSuffix()); QString dstFile = QString("%1/%2/%3").arg(m_packTmpDirName).arg(m_packDataDirName).arg(filename); QString dstFilePk = QString("%1.pk").arg(dstFile); RG_DEBUG << "cp " << srcFile << " " << dstFile; RG_DEBUG << "cp " << srcFilePk << " " << dstFilePk; if (!QFile::copy(srcFile, dstFile)) { puke(tr("<qt>Could not copy<br>%1<br> to<br>%2<br><br>Processing aborted.</qt>").arg(srcFile).arg(dstFile)); return; } // Try to copy the .wav.pk file derived from transforming the name of // the .wav file. We don't trap the fail condition for this one and // allow it to fail silently without complaining or aborting. If the // .wav.pk files are missing, they will be generated again as needed. // // Legacy .rgp files ship with improperly named .wav.pk files, from // a bug in the original rosegarden-project-package script. You'd wind // up with an .rgp that contained, for example: // // emergence-rg-0014.wav.pk // RG-AUDIO-0014.wav.pk // // That is why this version of the project packager doesn't screw around // with the original filenames! QFile::copy(srcFilePk, dstFilePk); m_progress->setValue(afStep * ++af); } // deal with adding any extra files QStringList extraFiles; // first, if the composition includes synth plugins, there may be assorted // random audio files, soundfonts, and who knows what else in use by these // plugins // // obtain a list of these files, and rewrite the XML to update the referring // path from its original source to point to our bundled copy instead QString newPath = QString("%1/%2").arg(m_packTmpDirName).arg(m_packDataDirName); extraFiles = getPluginFilesAndRewriteXML(oldName, newPath); // If we do the above here and add it to extraFiles then if the user has any // other extra files to add by hand, it all processes out the same way with // no extra bundling code required (unless we want to flac any random extra // .wav files, and I say no, let's not get that complicated) // Copy the modified .rg file to the working tmp dir RG_DEBUG << "cp " << oldName << " " << newName; // copy m_filename(.rgp) as $tmp/m_filename.rg if (!QFile::copy(oldName, newName)) { puke(tr("<qt>Could not copy<br>%1<br> to<br>%2<br><br>Processing aborted.</qt>").arg(oldName).arg(newName)); return; } QMessageBox::StandardButton reply = QMessageBox::information(this, tr("Rosegarden"), tr("<qt><p>Rosegarden can add any number of extra files you may desire to a project package. For example, you may wish to include an explanatory text file, a soundfont, a bank definition for ZynAddSubFX, or perhaps some cover art.</p><p>Would you like to include any additional files?</p></qt>"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No); while (reply == QMessageBox::Yes) { // it would take some trouble to make the last used paths thing work // here, where we're building a list of files from potentially anywhere, // so we'll just use the open_file path as it was last set elsewhere, // and leave it at that until somebody complains QSettings settings; settings.beginGroup(LastUsedPathsConfigGroup); QString directory = settings.value("open_file", QDir::homePath()).toString(); settings.endGroup(); // must iterate over a copy of the QStringList returned by // (Q)FileDialog::getOpenFileNames for some reason // // NOTE: This still doesn't work. I can only add one filename. // Something broken in the subclass of QFileDialog? Bad code? I'm just // leaving it unresolved for now. One file at a time at least satisfies // the bare minimum requirements QStringList files = FileDialog::getOpenFileNames(this, "Open File", directory, tr("All files") + " (*)", 0, 0); extraFiles << files; //!!! It would be nice to show the list of files already chosen and // added, in some nice little accumulator list widget, but this would // require doing something more complicated than using QMessageBox // static convenience functions, and it's probably just not worth it reply = QMessageBox::information(this, tr("Rosegarden"), tr("<qt><p>Would you like to include any additional files?</p></qt>"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No); } m_info->setText(tr("Copying plugin data and extra files...")); // reset progress bar m_progress->setValue(0); // count total audio files int ef = 0; for (si = extraFiles.constBegin(); si != extraFiles.constEnd(); ++si) ef++; int efStep = ((ef == 0) ? 1 : (100 / ef)); // copy the extra files (do not remove the originals!) // (iterator previously declared) ef = 0; for (si = extraFiles.constBegin(); si != extraFiles.constEnd(); ++si) { // each QStringList item from the FileDialog will include the full path QString srcFile = (*si); // so we cut it up to swap the source dir for the dest dir while leaving // the complete filename stuck on the end QFileInfo efi(*si); QString basename = QString("%1.%2").arg(efi.baseName()).arg(efi.completeSuffix()); QString dstFile = QString("%1/%2/%3").arg(m_packTmpDirName).arg(m_packDataDirName).arg(basename); RG_DEBUG << "cp " << srcFile << " " << dstFile; if (!QFile::copy(srcFile, dstFile)) { puke(tr("<qt>Could not copy<br>%1<br> to<br>%2<br><br>Processing aborted.</qt>").arg(srcFile).arg(dstFile)); return; } m_progress->setValue(efStep * ++ef); } // and now we have everything discovered, uncovered, added, smothered, // scattered and splattered, and we're ready to pack the files and // get the hell out of here! startAudioEncoder(audioFiles); }
ReturnStatus FileMetaDAO::rmdirRecursive(const std::string &path, uint64_t *pDelta) { Channel* pDataChannel = ChannelManager::getInstance()->Mapping(m_BucketId); NameSpace *DataNS = pDataChannel->m_DataNS; int rt = 0; ReturnStatus rs; int error = 0; std::string entryName; std::string npath; Args st; rt = DataNS->OpenDir(path.c_str(), &st); if (rt < 0) { error = errno; ERROR_LOG("path %s, opendir() error, %s.", path.c_str(), strerror(errno)); if (ENOTDIR == error) { ERROR_LOG("path %s, opendir() error, no directory"); return ReturnStatus(MU_FAILED, NOT_DIRECTORY); } else if (ENOENT == error) { return checkPrefix(path); } } // delete its children Dirent dirent; while(DataNS->ReadDirNext(&st, &dirent)){ entryName = dirent.filename; // omit "." and ".." // omit user info file in user root dir if (entryName == DENTRY_CURRENT_DIR || entryName == DENTRY_PARENT_DIR || entryName == USER_INFO_FILE_NAME) { continue; } npath = path + PATH_SEPARATOR_STRING + entryName; if (MU_DIRECTORY == dirent.filetype) { // directory, call myself to delete it rs = rmdirRecursive(npath, pDelta); if (!rs.success()) { ERROR_LOG("path %s, rmdirRecursive() error", npath.c_str()); return rs; } } else { // add file size to changed user quota addFileSizeToDelta(npath, pDelta); // delete it directly rt = DataNS->Unlink(npath.c_str()); if (-1 == rt) { ERROR_LOG("path %s, unlink() error, %s.", npath.c_str(), strerror(errno)); return ReturnStatus(MU_FAILED, MU_UNKNOWN_ERROR); } } } // delete path // do not delete user root if (path.substr(path.length() - 1) == ROOT_PATH) { return ReturnStatus(MU_SUCCESS); } rt = DataNS->RmDir(path.c_str()); if (-1 == rt) { ERROR_LOG("path %s, rmdir() error, %s.", path.c_str(), strerror(errno)); return ReturnStatus(MU_FAILED, MU_UNKNOWN_ERROR); } return ReturnStatus(MU_SUCCESS); }