}
virtual int setup_peakfile () { return 0; }
+ int close_peakfile ();
int prepare_for_peakfile_writes ();
void done_with_peakfile_writes (bool done = true);
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;
Deletion = 0x4,
InitialConnecting = 0x8,
Loading = 0x10,
- InCleanup = 0x20
+ InCleanup = 0x20,
+ PeakCleanup = 0x40
};
StateOfTheState state_of_the_state() const { return _state_of_the_state; }
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&);
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);
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;
}
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;
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);
}
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)
{