]> git.decadent.org.uk Git - videolink.git/commitdiff
Added auto-cleaning temporary directories.
authorBen Hutchings <ben@decadent.org.uk>
Sat, 14 Oct 2006 02:03:55 +0000 (02:03 +0000)
committerBen Hutchings <ben@decadent.org.uk>
Sun, 2 Nov 2008 23:58:11 +0000 (23:58 +0000)
Made use of them to give temporary files regular names; this is useful for debugging and for the next change.

generate_dvd.cpp
generate_dvd.hpp
temp_file.cpp
temp_file.hpp

index ff1b63574eaf0f01bb7fae9bb78e3b8b061fcd9a..aa57775e22639bdce088710cf24fc542cfd9315e 100644 (file)
@@ -7,6 +7,7 @@
 #include <stdexcept>
 
 #include <gdkmm/pixbuf.h>
+#include <glibmm/miscutils.h>
 #include <glibmm/spawn.h>
 
 #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 <<
        "<subpictures>\n"
        "  <stream>\n"
        "    <spu force='yes' start='00:00:00.00'\n"
-       "        highlight='" << highlights_temp.get_name() << "'\n"
-       "        select='" << highlights_temp.get_name() << "'>\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"
            "        </pre>\n"
-           "        <vob file='" << this_menu.vob_temp->get_name() << "'/>\n";
+           "        <vob file='"
+            << temp_file_name(temp_dir_, "menu-%3d.mpeg", 1 + menu_index)
+            << "'/>\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;
index 7f3823fee19db43d98a41bf344dbec3550cfbcac..d7681630ccacacb84538aa485df4f0f06dcdd955 100644 (file)
@@ -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<temp_file> 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<menu_entry> entries;
     };
 
+    temp_dir temp_dir_;
     video::frame_params frame_params_;
     mpeg_encoder encoder_;
     std::vector<menu> menus_;
index fc4106c27bc658e3377afae4caf9ea8ebcdb0e75..323b35896217456196446bcc4037a650719b17c7 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2005 Ben Hutchings <ben@decadent.org.uk>.
+// Copyright 2005-6 Ben Hutchings <ben@decadent.org.uk>.
 // See the file "COPYING" for licence details.
 
 #include "temp_file.hpp"
@@ -7,6 +7,8 @@
 #include <cerrno>
 #include <cstdlib>
 #include <cstring>
+#include <iostream>
+#include <ostream>
 #include <stdexcept>
 #include <vector>
 
 #include <unistd.h>
 
 #include <glibmm/fileutils.h>
+#include <glibmm/miscutils.h>
+
+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<char> 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";
 }
index 1ead61afb9f3831ae3b7a12c7d29889fcfb19bc6..9ea55f375848cfd1b9a2bae467eb7a1d5970c9ae 100644 (file)
@@ -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