From 3194c256cf967c11bbc267f05044fa7eb049100f Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 14 Oct 2006 02:03:55 +0000 Subject: [PATCH] Added auto-cleaning temporary directories. Made use of them to give temporary files regular names; this is useful for debugging and for the next change. --- generate_dvd.cpp | 73 ++++++++++++++++++++++++++++++------------------ generate_dvd.hpp | 12 ++------ temp_file.cpp | 61 ++++++++++++++++++++++++++++++++++++---- temp_file.hpp | 11 +++++++- 4 files changed, 114 insertions(+), 43 deletions(-) diff --git a/generate_dvd.cpp b/generate_dvd.cpp index ff1b635..aa57775 100644 --- a/generate_dvd.cpp +++ b/generate_dvd.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include "dvd.hpp" @@ -55,14 +56,31 @@ namespace + (end_y - start_y) * (end_y - start_y); return vertical_distance / distance_squared; } -} -dvd_generator::menu::menu() - : vob_temp(new temp_file("videolink-vob-")) -{ - vob_temp->close(); + std::string temp_file_name(const temp_dir & dir, + std::string base_name, + unsigned index=0) + { + if (index != 0) + { + std::size_t index_pos = base_name.find("%3d"); + assert(index_pos != std::string::npos); + base_name[index_pos] = '0' + index / 100; + base_name[index_pos + 1] = '0' + (index / 10) % 10; + base_name[index_pos + 2] = '0' + index % 10; + } + + return Glib::build_filename(dir.get_name(), base_name); + } } +dvd_generator::dvd_generator(const video::frame_params & frame_params, + mpeg_encoder encoder) + : temp_dir_("videolink-"), + frame_params_(frame_params), + encoder_(encoder) +{} + dvd_generator::pgc_ref dvd_generator::add_menu() { pgc_ref next_menu(menu_pgc, menus_.size()); @@ -98,25 +116,25 @@ void dvd_generator::generate_menu_vob(unsigned index, assert(index < menus_.size()); const menu & this_menu = menus_[index]; - temp_file background_temp("videolink-back-"); - background_temp.close(); - std::cout << "saving " << background_temp.get_name() << std::endl; - background->save(background_temp.get_name(), "png"); + std::string background_name( + temp_file_name(temp_dir_, "menu-%3d-back.png", 1 + index)); + std::cout << "saving " << background_name << std::endl; + background->save(background_name, "png"); - temp_file highlights_temp("videolink-links-"); - highlights_temp.close(); - std::cout << "saving " << highlights_temp.get_name() << std::endl; - highlights->save(highlights_temp.get_name(), "png"); + std::string highlights_name( + temp_file_name(temp_dir_, "menu-%3d-links.png", 1 + index)); + std::cout << "saving " << highlights_name << std::endl; + highlights->save(highlights_name, "png"); - temp_file spumux_temp("videolink-spumux-"); - spumux_temp.close(); - std::ofstream spumux_file(spumux_temp.get_name().c_str()); + std::string spumux_name( + temp_file_name(temp_dir_, "menu-%3d.subpictures", 1 + index)); + std::ofstream spumux_file(spumux_name.c_str()); spumux_file << "\n" " \n" " \n"; + " highlight='" << highlights_name << "'\n" + " select='" << highlights_name << "'>\n"; int button_count = this_menu.entries.size(); for (int i = 0; i != button_count; ++i) { @@ -175,7 +193,7 @@ void dvd_generator::generate_menu_vob(unsigned index, command_stream << "ffmpeg" << " -f image2 -vcodec png -i " - << background_temp.get_name() + << background_name << " -target " << frame_params_.common_name << "-dvd" << " -vcodec mpeg2video -aspect 4:3 -an -y /dev/stdout"; } @@ -185,7 +203,7 @@ void dvd_generator::generate_menu_vob(unsigned index, || encoder_ == mpeg_encoder_mjpegtools_new); command_stream << "pngtopnm " - << background_temp.get_name() + << background_name << " | ppmtoy4m -v0 -n1 -F" << frame_params_.rate_numer << ":" << frame_params_.rate_denom << " -A" << frame_params_.pixel_ratio_width @@ -203,8 +221,8 @@ void dvd_generator::generate_menu_vob(unsigned index, " | mplex -v0 -f8 -o/dev/stdout /dev/stdin"; } command_stream - << " | spumux -v0 -mdvd " << spumux_temp.get_name() - << " > " << this_menu.vob_temp->get_name(); + << " | spumux -v0 -mdvd " << spumux_name + << " > " << temp_file_name(temp_dir_, "menu-%3d.mpeg", 1 + index); std::string command(command_stream.str()); const char * argv[] = { "/bin/sh", "-c", command.c_str(), 0 @@ -238,9 +256,8 @@ dvd_generator::pgc_ref dvd_generator::add_title(vob_list & content) void dvd_generator::generate(const std::string & output_dir) const { - temp_file temp("videolink-dvdauthor-"); - temp.close(); - std::ofstream file(temp.get_name().c_str()); + std::string name(temp_file_name(temp_dir_, "videolink.dvdauthor")); + std::ofstream file(name.c_str()); // We generate code that uses registers in the following way: // @@ -332,7 +349,9 @@ void dvd_generator::generate(const std::string & output_dir) const // this same menu! " g1 = 0;\n" " \n" - " \n"; + " \n"; for (unsigned button_index = 0; button_index != this_menu.entries.size(); @@ -491,7 +510,7 @@ void dvd_generator::generate(const std::string & output_dir) const const char * argv[] = { "dvdauthor", "-o", output_dir.c_str(), - "-x", temp.get_name().c_str(), + "-x", name.c_str(), 0 }; int command_result; diff --git a/generate_dvd.hpp b/generate_dvd.hpp index 7f3823f..d768163 100644 --- a/generate_dvd.hpp +++ b/generate_dvd.hpp @@ -60,10 +60,7 @@ public: }; dvd_generator(const video::frame_params & frame_params, - mpeg_encoder encoder) - : frame_params_(frame_params), - encoder_(encoder) - {} + mpeg_encoder encoder); // Create a new empty menu; return a reference to it. // The client must call generate_menu_vob() for each menu before @@ -96,17 +93,12 @@ private: // Menu definition. struct menu { - menu(); - - // Temporary file in which the menu VOB should be generated. - // This is created as an empty file and then closed. - boost::shared_ptr vob_temp; - // References to the menus and titles that the menu buttons // are meant to link to, in the same order as the buttons. std::vector entries; }; + temp_dir temp_dir_; video::frame_params frame_params_; mpeg_encoder encoder_; std::vector menus_; diff --git a/temp_file.cpp b/temp_file.cpp index fc4106c..323b358 100644 --- a/temp_file.cpp +++ b/temp_file.cpp @@ -1,4 +1,4 @@ -// Copyright 2005 Ben Hutchings . +// Copyright 2005-6 Ben Hutchings . // See the file "COPYING" for licence details. #include "temp_file.hpp" @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include @@ -14,6 +16,31 @@ #include #include +#include + +namespace +{ + bool try_rmdir_recursive(const std::string & dir_name) + { + Glib::Dir dir(dir_name); + bool empty = true; + + for (Glib::Dir::iterator it = dir.begin(), end = dir.end(); + it != end; + ++it) + { + std::string full_name(Glib::build_filename(dir_name, *it)); + if (!(Glib::file_test(full_name, Glib::FILE_TEST_IS_DIR) + ? try_rmdir_recursive(full_name) + : (unlink(full_name.c_str()) == 0 || errno == ENOENT))) + empty = false; + } + + return empty && (rmdir(dir_name.c_str()) == 0 || errno == ENOENT); + } + + bool do_keep_all = false; +} temp_file::temp_file(const std::string & base_name) { @@ -37,7 +64,7 @@ temp_file::~temp_file() { close(); - if (!keep_) + if (!do_keep_all) { // Don't assert that this is successful. The file could have // been removed by another process. @@ -55,9 +82,33 @@ void temp_file::close() } } -bool temp_file::keep_ = false; - void temp_file::keep_all(bool keep) { - keep_ = keep; + do_keep_all = keep; +} + +temp_dir::temp_dir(const std::string & base_name) +{ + std::string tmp_dir_name(Glib::get_tmp_dir()); + std::vector template_name; + template_name.reserve(tmp_dir_name.size() + 1 + base_name.size() + 6 + 1); + name_.reserve(tmp_dir_name.size() + 1 + base_name.size() + 6); + template_name.assign(tmp_dir_name.begin(), tmp_dir_name.end()); + template_name.insert(template_name.end(), '/'); + template_name.insert(template_name.end(), + base_name.begin(), base_name.end()); + template_name.insert(template_name.end(), 6, 'X'); + template_name.insert(template_name.end(), '\0'); + if (mkdtemp(&template_name[0])) + name_.assign(template_name.begin(), template_name.end() - 1); + else + throw std::runtime_error( + std::string("mkdtemp: ").append(std::strerror(errno))); +} + +temp_dir::~temp_dir() +{ + if (!do_keep_all && !try_rmdir_recursive(name_)) + std::cerr << "Warning: failed to remove temporary directory " + << name_ << "\n"; } diff --git a/temp_file.hpp b/temp_file.hpp index 1ead61a..9ea55f3 100644 --- a/temp_file.hpp +++ b/temp_file.hpp @@ -22,8 +22,17 @@ public: private: int fd_; std::string name_; +}; - static bool keep_; +class temp_dir +{ +public: + explicit temp_dir(const std::string & base_name); + ~temp_dir(); + const std::string & get_name() const { return name_; } + +private: + std::string name_; }; #endif // !INC_TEMP_FILE_HPP -- 2.39.5