summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2014-06-10 10:07:04 -0400
committerPaul Davis <paul@linuxaudiosystems.com>2014-06-10 10:07:04 -0400
commit107e0d6d02333cd9947ddba4120af95175e5643e (patch)
tree832ae77039f98979ab9059494523e1b06e318a67
parent3f38a602cc4a6170dda7c19f7dd14f11717d5c9b (diff)
fix crash recovery: add new constructors to SndFileSource, AudioFileSource, add a new SourceFactory method and finally tweak
AudioDiskstream::use_pending_capture_data() to create both the required whole-file and the in-playlist regions
-rw-r--r--libs/ardour/ardour/audiofilesource.h6
-rw-r--r--libs/ardour/ardour/sndfilesource.h11
-rw-r--r--libs/ardour/ardour/source_factory.h3
-rw-r--r--libs/ardour/audio_diskstream.cc38
-rw-r--r--libs/ardour/audiofilesource.cc16
-rw-r--r--libs/ardour/file_source.cc2
-rw-r--r--libs/ardour/sndfilesource.cc36
-rw-r--r--libs/ardour/source_factory.cc33
8 files changed, 131 insertions, 14 deletions
diff --git a/libs/ardour/ardour/audiofilesource.h b/libs/ardour/ardour/audiofilesource.h
index e0a199fd72..4831eb2081 100644
--- a/libs/ardour/ardour/audiofilesource.h
+++ b/libs/ardour/ardour/audiofilesource.h
@@ -94,6 +94,12 @@ protected:
/** Constructor to be called for existing in-session files */
AudioFileSource (Session&, const XMLNode&, bool must_exist = true);
+ /** Constructor to be called for crash recovery. Final argument is not
+ * used but exists to differentiate from the external-to-session
+ * constructor above.
+ */
+ AudioFileSource (Session&, const std::string& path, Source::Flag flags, bool);
+
int init (const std::string& idstr, bool must_exist);
virtual void set_header_timeline_position () = 0;
diff --git a/libs/ardour/ardour/sndfilesource.h b/libs/ardour/ardour/sndfilesource.h
index 25b8f003b2..831f8db5f7 100644
--- a/libs/ardour/ardour/sndfilesource.h
+++ b/libs/ardour/ardour/sndfilesource.h
@@ -38,7 +38,16 @@ class LIBARDOUR_API SndFileSource : public AudioFileSource {
SampleFormat samp_format, HeaderFormat hdr_format, framecnt_t rate,
Flag flags = SndFileSource::default_writable_flags);
- /** Constructor to be called for existing in-session files */
+ /* Constructor to be called for recovering files being used for
+ * capture. They are in-session, they already exist, they should not
+ * be writable. They are an odd hybrid (from a constructor point of
+ * view) of the previous two constructors.
+ */
+ SndFileSource (Session&, const std::string& path, int chn);
+
+ /** Constructor to be called for existing in-session files during
+ * session loading
+ */
SndFileSource (Session&, const XMLNode&);
~SndFileSource ();
diff --git a/libs/ardour/ardour/source_factory.h b/libs/ardour/ardour/source_factory.h
index 4ef2cd60ee..614fdce7b1 100644
--- a/libs/ardour/ardour/source_factory.h
+++ b/libs/ardour/ardour/source_factory.h
@@ -57,6 +57,9 @@ class LIBARDOUR_API SourceFactory {
bool destructive, framecnt_t rate, bool announce = true, bool async = false);
+ static boost::shared_ptr<Source> createForRecovery
+ (DataType type, Session&, const std::string& path, int chn);
+
static boost::shared_ptr<Source> createFromPlaylist
(DataType type, Session& s, boost::shared_ptr<Playlist> p, const PBD::ID& orig, const std::string& name,
uint32_t chn, frameoffset_t start, framecnt_t len, bool copy, bool defer_peaks);
diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc
index ffb8ef8a1b..095bbf075a 100644
--- a/libs/ardour/audio_diskstream.cc
+++ b/libs/ardour/audio_diskstream.cc
@@ -2179,11 +2179,16 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node)
continue;
}
+ /* XXX as of June 2014, we always record to mono
+ files. Since this Source is being created as part of
+ crash recovery, we know that we need the first
+ channel (the final argument to the SourceFactory
+ call below). If we ever support non-mono files for
+ capture, this will need rethinking.
+ */
+
try {
- fs = boost::dynamic_pointer_cast<AudioFileSource> (
- SourceFactory::createWritable (
- DataType::AUDIO, _session,
- prop->value(), false, _session.frame_rate()));
+ fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createForRecovery (DataType::AUDIO, _session, prop->value(), 0));
}
catch (failed_constructor& err) {
@@ -2214,21 +2219,31 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node)
return -1;
}
- boost::shared_ptr<AudioRegion> region;
-
try {
- PropertyList plist;
+ boost::shared_ptr<AudioRegion> wf_region;
+ boost::shared_ptr<AudioRegion> region;
+
+ /* First create the whole file region */
+ PropertyList plist;
+
plist.add (Properties::start, 0);
plist.add (Properties::length, first_fs->length (first_fs->timeline_position()));
plist.add (Properties::name, region_name_from_path (first_fs->name(), true));
- region = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (pending_sources, plist));
+ wf_region = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (pending_sources, plist));
+
+ wf_region->set_automatic (true);
+ wf_region->set_whole_file (true);
+ wf_region->special_set_position (position);
- region->set_automatic (true);
- region->set_whole_file (true);
- region->special_set_position (0);
+ /* Now create a region that isn't the whole file for adding to
+ * the playlist */
+
+ region = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (pending_sources, plist));
+
+ _playlist->add_region (region, position);
}
catch (failed_constructor& err) {
@@ -2239,7 +2254,6 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node)
return -1;
}
- _playlist->add_region (region, position);
return 0;
}
diff --git a/libs/ardour/audiofilesource.cc b/libs/ardour/audiofilesource.cc
index 014baa9031..299b5a2bb5 100644
--- a/libs/ardour/audiofilesource.cc
+++ b/libs/ardour/audiofilesource.cc
@@ -115,6 +115,22 @@ AudioFileSource::AudioFileSource (Session& s, const string& path, const string&
}
}
+/** Constructor used for existing internal-to-session files during crash
+ * recovery. File must exist
+ */
+AudioFileSource::AudioFileSource (Session& s, const string& path, Source::Flag flags, bool /* ignored-exists-for-prototype differentiation */)
+ : Source (s, DataType::AUDIO, path, flags)
+ , AudioSource (s, path)
+ , FileSource (s, DataType::AUDIO, path, string(), flags)
+{
+ /* note that origin remains empty */
+
+ if (init (_path, true)) {
+ throw failed_constructor ();
+ }
+}
+
+
/** Constructor used for existing internal-to-session files via XML. File must exist. */
AudioFileSource::AudioFileSource (Session& s, const XMLNode& node, bool must_exist)
: Source (s, node)
diff --git a/libs/ardour/file_source.cc b/libs/ardour/file_source.cc
index 109539ce2d..ae63bd55b1 100644
--- a/libs/ardour/file_source.cc
+++ b/libs/ardour/file_source.cc
@@ -56,7 +56,7 @@ PBD::Signal2<int,std::string,std::vector<std::string> > FileSource::AmbiguousFil
FileSource::FileSource (Session& session, DataType type, const string& path, const string& origin, Source::Flag flag)
: Source(session, type, path, flag)
, _path (path)
- , _file_is_new (!origin.empty()) // origin empty => new file VS. origin !empty => new file
+ , _file_is_new (!origin.empty()) // if origin is left unspecified (empty string) then file must exist
, _channel (0)
, _origin (origin)
, _open (false)
diff --git a/libs/ardour/sndfilesource.cc b/libs/ardour/sndfilesource.cc
index e0851602fc..af25b3e76f 100644
--- a/libs/ardour/sndfilesource.cc
+++ b/libs/ardour/sndfilesource.cc
@@ -185,6 +185,34 @@ SndFileSource::SndFileSource (Session& s, const string& path, const string& orig
}
}
+/** Constructor to be called for recovering files being used for
+ * capture. They are in-session, they already exist, they should not
+ * be writable. They are an odd hybrid (from a constructor point of
+ * view) of the previous two constructors.
+ */
+SndFileSource::SndFileSource (Session& s, const string& path, int chn)
+ : Source (s, DataType::AUDIO, path, Flag (0))
+ /* the final boolean argument is not used, its value is irrelevant. see audiofilesource.h for explanation */
+ , AudioFileSource (s, path, Flag (0))
+ , _descriptor (0)
+ , _broadcast_info (0)
+ , _capture_start (false)
+ , _capture_end (false)
+ , file_pos (0)
+ , xfade_buf (0)
+{
+ _channel = chn;
+
+ init_sndfile ();
+
+ assert (Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
+ existence_check ();
+
+ if (open()) {
+ throw failed_constructor ();
+ }
+}
+
void
SndFileSource::init_sndfile ()
{
@@ -266,6 +294,14 @@ SndFileSource::open ()
delete _broadcast_info;
_broadcast_info = 0;
_flags = Flag (_flags & ~Broadcast);
+ }
+
+ /* Set the broadcast flag if the BWF info is already there. We need
+ * this when recovering or using existing files.
+ */
+
+ if (bwf_info_exists) {
+ _flags = Flag (_flags | Broadcast);
}
if (writable()) {
diff --git a/libs/ardour/source_factory.cc b/libs/ardour/source_factory.cc
index 391b205a94..6d2bb80b30 100644
--- a/libs/ardour/source_factory.cc
+++ b/libs/ardour/source_factory.cc
@@ -342,6 +342,39 @@ SourceFactory::createWritable (DataType type, Session& s, const std::string& pat
}
boost::shared_ptr<Source>
+SourceFactory::createForRecovery (DataType type, Session& s, const std::string& path, int chn)
+{
+ /* this might throw failed_constructor(), which is OK */
+
+ if (type == DataType::AUDIO) {
+ Source* src = new SndFileSource (s, path, chn);
+
+#ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
+ // boost_debug_shared_ptr_mark_interesting (src, "Source");
+#endif
+ boost::shared_ptr<Source> ret (src);
+
+ if (setup_peakfile (ret, false)) {
+ return boost::shared_ptr<Source>();
+ }
+
+ // no analysis data - this is still basically a new file (we
+ // crashed while recording.
+
+ // always announce these files
+
+ SourceCreated (ret);
+
+ return ret;
+
+ } else if (type == DataType::MIDI) {
+ error << _("Recovery attempted on a MIDI file - not implemented") << endmsg;
+ }
+
+ return boost::shared_ptr<Source> ();
+}
+
+boost::shared_ptr<Source>
SourceFactory::createFromPlaylist (DataType type, Session& s, boost::shared_ptr<Playlist> p, const PBD::ID& orig, const std::string& name,
uint32_t chn, frameoffset_t start, framecnt_t len, bool copy, bool defer_peaks)
{