+bool
+Source::has_been_analysed() const
+{
+ Glib::Threads::Mutex::Lock lm (_analysis_lock);
+ return _analysed;
+}
+
+void
+Source::set_been_analysed (bool yn)
+{
+ if (yn) {
+ if (0 == load_transients (get_transients_path())) {
+ yn = false;
+ }
+ }
+ if (yn != _analysed) {
+ Glib::Threads::Mutex::Lock lm (_analysis_lock);
+ _analysed = yn;
+ }
+ AnalysisChanged(); // EMIT SIGNAL
+}
+
+int
+Source::load_transients (const string& path)
+{
+ int rv = 0;
+ FILE *tf;
+ if (! (tf = g_fopen (path.c_str (), "rb"))) {
+ return -1;
+ }
+
+ transients.clear ();
+ while (!feof (tf) && !ferror(tf)) {
+ double val;
+ if (1 != fscanf (tf, "%lf", &val)) {
+ rv = -1;
+ break;
+ }
+
+ framepos_t frame = (framepos_t) floor (val * _session.frame_rate());
+ transients.push_back (frame);
+ }
+
+ ::fclose (tf);
+ return rv;
+}
+
+string
+Source::get_transients_path () const
+{
+ vector<string> parts;
+ string s;
+
+ /* old sessions may not have the analysis directory */
+
+ _session.ensure_subdirs ();
+
+ s = _session.analysis_dir ();
+ parts.push_back (s);
+
+ s = id().to_s();
+ s += '.';
+ s += TransientDetector::operational_identifier();
+ parts.push_back (s);
+
+ return Glib::build_filename (parts);
+}
+
+bool
+Source::check_for_analysis_data_on_disk ()
+{
+ /* looks to see if the analysis files for this source are on disk.
+ if so, mark us already analysed.
+ */
+
+ string path = get_transients_path ();
+ bool ok = true;
+
+ if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
+ ok = false;
+ }
+
+ // XXX add other tests here as appropriate
+
+ set_been_analysed (ok);
+ return ok;
+}
+
+void
+Source::mark_for_remove ()
+{
+ // This operation is not allowed for sources for destructive tracks or out-of-session files.
+
+ /* XXX need a way to detect _within_session() condition here - move it from FileSource?
+ */
+
+ if ((_flags & Destructive)) {
+ return;
+ }
+
+ _flags = Flag (_flags | Removable | RemoveAtDestroy);
+}
+
+void
+Source::set_timeline_position (framepos_t pos)
+{
+ _timeline_position = pos;
+}
+
+void
+Source::set_allow_remove_if_empty (bool yn)
+{
+ if (!writable()) {
+ return;
+ }
+
+ if (yn) {
+ _flags = Flag (_flags | RemovableIfEmpty);
+ } else {
+ _flags = Flag (_flags & ~RemovableIfEmpty);
+ }
+}
+