prepare peak-file cleanup/recreate.
authorRobin Gareus <robin@gareus.org>
Tue, 15 Sep 2015 12:41:27 +0000 (14:41 +0200)
committerRobin Gareus <robin@gareus.org>
Tue, 15 Sep 2015 12:44:05 +0000 (14:44 +0200)
libs/ardour/ardour/audiosource.h
libs/ardour/ardour/session.h
libs/ardour/audiosource.cc
libs/ardour/session_state.cc

index ad7884e4f42ea74c33a8cf390bd1a687435f90cb..345d424cf3ffcf92a52ce78c10fe1cf4eac58837 100644 (file)
@@ -96,6 +96,7 @@ class LIBARDOUR_API AudioSource : virtual public Source,
        }
 
        virtual int setup_peakfile () { return 0; }
+       int close_peakfile ();
 
        int prepare_for_peakfile_writes ();
        void done_with_peakfile_writes (bool done = true);
index 79eb2162da7a50d9a2ee102b76019beceb1c0a7a..6b71e3c1edde9c8b829882a1d47e1bb41cdbdbf9 100644 (file)
@@ -191,6 +191,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        bool reconnection_in_progress() const { return _reconnecting_routes_in_progress; }
        bool deletion_in_progress() const { return _state_of_the_state & Deletion; }
        bool routes_deletion_in_progress() const { return _route_deletion_in_progress; }
+       bool peaks_cleanup_in_progres() const { return _state_of_the_state & PeakCleanup; }
 
        PBD::Signal0<void> DirtyChanged;
 
@@ -505,7 +506,8 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
                Deletion = 0x4,
                InitialConnecting = 0x8,
                Loading = 0x10,
-               InCleanup = 0x20
+               InCleanup = 0x20,
+               PeakCleanup = 0x40
        };
 
        StateOfTheState state_of_the_state() const { return _state_of_the_state; }
@@ -661,7 +663,9 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        void add_source (boost::shared_ptr<Source>);
        void remove_source (boost::weak_ptr<Source>);
 
-       void  cleanup_regions();
+       void cleanup_regions();
+       bool can_cleanup_peakfiles () const;
+       int  cleanup_peakfiles ();
        int  cleanup_sources (CleanupReport&);
        int  cleanup_trash_sources (CleanupReport&);
 
@@ -1243,6 +1247,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        gint            _suspend_save; /* atomic */
        volatile bool   _save_queued;
        Glib::Threads::Mutex save_state_lock;
+       Glib::Threads::Mutex peak_cleanup_lock;
 
        int      load_options (const XMLNode&);
        int      load_state (std::string snapshot_name);
index 4439669c4f0aa0aba7dd79400e7fc8c45d2282bb..d4be1df22e7b9593b78931b755f9b3e03a32b282 100644 (file)
@@ -752,8 +752,9 @@ AudioSource::build_peaks_from_scratch ()
 
                        lp.release(); // allow butler to refill buffers
 
-                       if (_session.deletion_in_progress()) {
+                       if (_session.deletion_in_progress() || _session.peaks_cleanup_in_progres()) {
                                cerr << "peak file creation interrupted: " << _name << endmsg;
+                               lp.acquire();
                                done_with_peakfile_writes (false);
                                goto out;
                        }
@@ -788,9 +789,28 @@ AudioSource::build_peaks_from_scratch ()
        return ret;
 }
 
+int
+AudioSource::close_peakfile ()
+{
+       Glib::Threads::Mutex::Lock lp (_lock);
+       if (_peakfile_fd >= 0) {
+               close (_peakfile_fd);
+               _peakfile_fd = -1;
+       }
+       if (!_peakpath.empty()) {
+               ::g_unlink (_peakpath.c_str());
+       }
+       _peaks_built = false;
+       return 0;
+}
+
 int
 AudioSource::prepare_for_peakfile_writes ()
 {
+       if (_session.deletion_in_progress() || _session.peaks_cleanup_in_progres()) {
+               return -1;
+       }
+
        if ((_peakfile_fd = g_open (_peakpath.c_str(), O_CREAT|O_RDWR, 0664)) < 0) {
                error << string_compose(_("AudioSource: cannot open _peakpath (c) \"%1\" (%2)"), _peakpath, strerror (errno)) << endmsg;
                return -1;
@@ -801,6 +821,14 @@ AudioSource::prepare_for_peakfile_writes ()
 void
 AudioSource::done_with_peakfile_writes (bool done)
 {
+       if (_session.deletion_in_progress() || _session.peaks_cleanup_in_progres()) {
+               if (_peakfile_fd) {
+                       close (_peakfile_fd);
+                       _peakfile_fd = -1;
+               }
+               return;
+       }
+
        if (peak_leftover_cnt) {
                compute_and_write_peaks (0, 0, 0, true, false, _FPP);
        }
index f893c18a1b18936a7d80da157461238eb146568c..0c66b91578c9c084a453960f79617b4ec41b71f9 100644 (file)
@@ -2846,6 +2846,66 @@ Session::cleanup_regions ()
        save_state ("");
 }
 
+bool
+Session::can_cleanup_peakfiles () const
+{
+       if (deletion_in_progress()) {
+               return false;
+       }
+       if (!_writable || (_state_of_the_state & CannotSave)) {
+               warning << _("Cannot cleanup peak-files for read-only session.") << endmsg;
+               return false;
+       }
+        if (record_status() == Recording) {
+               error << _("Cannot cleanup peak-files while recording") << endmsg;
+               return false;
+       }
+       return true;
+}
+
+int
+Session::cleanup_peakfiles ()
+{
+       Glib::Threads::Mutex::Lock lm (peak_cleanup_lock, Glib::Threads::TRY_LOCK);
+       if (!lm.locked()) {
+               return -1;
+       }
+
+       assert (can_cleanup_peakfiles ());
+       assert (!peaks_cleanup_in_progres());
+
+       _state_of_the_state = StateOfTheState (_state_of_the_state | PeakCleanup);
+
+       int timeout = 5000; // 5 seconds
+       while (!SourceFactory::files_with_peaks.empty()) {
+               Glib::usleep (1000);
+               if (--timeout < 0) {
+                       warning << _("Timeout waiting for peak-file creation to terminate before cleanup, please try again later.") << endmsg;
+                       _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
+                       return -1;
+               }
+       }
+
+       for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
+               boost::shared_ptr<AudioSource> as;
+               if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
+                       as->close_peakfile();
+               }
+       }
+
+       PBD::clear_directory (session_directory().peak_path());
+
+       _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
+
+       for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
+               boost::shared_ptr<AudioSource> as;
+               if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
+                       SourceFactory::setup_peakfile(as, true);
+               }
+       }
+       return 0;
+}
+
 int
 Session::cleanup_sources (CleanupReport& rep)
 {