mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 07:14:56 +01:00
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
This commit is contained in:
parent
74bc0c8468
commit
b660bc8ae9
8 changed files with 131 additions and 14 deletions
|
|
@ -93,6 +93,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;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,16 @@ class 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 ();
|
||||
|
|
|
|||
|
|
@ -57,6 +57,9 @@ class 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);
|
||||
|
|
|
|||
|
|
@ -2181,11 +2181,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) {
|
||||
|
|
@ -2216,21 +2221,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));
|
||||
|
||||
region->set_automatic (true);
|
||||
region->set_whole_file (true);
|
||||
region->special_set_position (0);
|
||||
wf_region->set_automatic (true);
|
||||
wf_region->set_whole_file (true);
|
||||
wf_region->special_set_position (position);
|
||||
|
||||
/* 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) {
|
||||
|
|
@ -2241,7 +2256,6 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node)
|
|||
return -1;
|
||||
}
|
||||
|
||||
_playlist->add_region (region, position);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ PBD::Signal3<int,std::string,std::string,std::vector<std::string> > FileSource::
|
|||
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)
|
||||
|
|
|
|||
|
|
@ -183,6 +183,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 ()
|
||||
{
|
||||
|
|
@ -256,6 +284,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()) {
|
||||
|
|
|
|||
|
|
@ -341,6 +341,39 @@ SourceFactory::createWritable (DataType type, Session& s, const std::string& pat
|
|||
return boost::shared_ptr<Source> ();
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue