remove entire "stub" file concept; open new audio and MIDI files on demand (at first write); could be a few gotchas with some corner case scenarios, but apparently works OK

git-svn-id: svn://localhost/ardour2/branches/3.0@9038 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2011-03-02 17:05:16 +00:00
parent 488d54a341
commit 5e431d1d58
17 changed files with 133 additions and 260 deletions

View File

@ -19,7 +19,6 @@ extern const char* const templates_dir_name;
extern const char* const route_templates_dir_name;
extern const char* const surfaces_dir_name;
extern const char* const user_config_dir_name;
extern const char* const stub_dir_name;
extern const char* const panner_dir_name;
};

View File

@ -48,12 +48,6 @@ public:
const std::string& path() const { return _path; }
int unstubify ();
void stubify ();
bool is_stub () const;
static bool is_stub_path (const std::string& path);
virtual bool safe_file_extension (const std::string& path) const = 0;
int move_to_trash (const std::string& trash_dir_name);
@ -104,7 +98,8 @@ protected:
uint16_t _channel;
bool _within_session;
std::string _origin;
bool _open;
void prevent_deletion ();
};

View File

@ -78,7 +78,7 @@ class MidiSource : virtual public Source, public boost::enable_shared_from_this<
virtual framecnt_t length (framepos_t pos) const;
virtual void update_length (framepos_t pos, framecnt_t cnt);
virtual void mark_streaming_midi_write_started (NoteMode mode, framepos_t start_time);
virtual void mark_streaming_midi_write_started (NoteMode mode);
virtual void mark_streaming_write_started ();
virtual void mark_streaming_write_completed ();
void mark_write_starting_now ();

View File

@ -187,7 +187,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
std::string peak_path_from_audio_path (std::string) const;
std::string new_audio_source_name (const std::string&, uint32_t nchans, uint32_t chan, bool destructive);
std::string new_midi_source_name (const std::string&);
std::string new_source_path_from_name (DataType type, const std::string&, bool as_stub = false);
std::string new_source_path_from_name (DataType type, const std::string&);
RouteList new_route_from_template (uint32_t how_many, const std::string& template_path);
void process (pframes_t nframes);
@ -543,10 +543,10 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
static PBD::Signal0<int> AskAboutPendingState;
boost::shared_ptr<AudioFileSource> create_audio_source_for_session (
size_t, std::string const &, uint32_t, bool destructive, bool as_stub = false);
size_t, std::string const &, uint32_t, bool destructive);
boost::shared_ptr<MidiSource> create_midi_source_for_session (
Track*, std::string const &, bool as_stub = false);
Track*, std::string const &);
boost::shared_ptr<Source> source_by_id (const PBD::ID&);
boost::shared_ptr<Source> source_by_path_and_channel (const std::string&, uint16_t);
@ -1472,7 +1472,6 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
void add_session_range_location (framepos_t, framepos_t);
void setup_midi_machine_control ();
void cleanup_stubfiles ();
void route_order_key_changed ();

View File

@ -51,17 +51,6 @@ public:
*/
const PBD::sys::path sound_path () const;
/**
* @return the absolute path to the directory in which
* the session stores STUB audio files.
*
* If the session is an older session with an existing
* "sounds" directory then it will return a path to that
* directory otherwise it will return the new location
* of root_path()/interchange/session_name/audiofiles/.stubs
*/
const PBD::sys::path sound_stub_path () const;
/**
* @return the absolute path to the directory in which
* the session stores MIDI files, ie
@ -69,13 +58,6 @@ public:
*/
const PBD::sys::path midi_path () const;
/**
* @return the absolute path to the directory in which
* the session stores STUB MIDI files, ie
* root_path()/interchange/session_name/midifiles/.stubs
*/
const PBD::sys::path midi_stub_path () const;
/**
* @return the absolute path to the directory in which
* the session stores MIDNAM patch files, ie

View File

@ -54,7 +54,7 @@ public:
void append_event_unlocked_beats (const Evoral::Event<Evoral::MusicalTime>& ev);
void append_event_unlocked_frames (const Evoral::Event<framepos_t>& ev, framepos_t source_start);
void mark_streaming_midi_write_started (NoteMode mode, framepos_t start_time);
void mark_streaming_midi_write_started (NoteMode mode);
void mark_streaming_write_completed ();
XMLNode& get_state ();
@ -73,6 +73,8 @@ public:
void set_path (const std::string& newpath);
private:
int open_for_write ();
framecnt_t read_unlocked (Evoral::EventSink<framepos_t>& dst,
framepos_t position,
framepos_t start,

View File

@ -1425,9 +1425,6 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo
if (s) {
srcs.push_back (s);
if (s->unstubify ()) {
error << string_compose (_("Could not move capture file from %1"), s->path()) << endmsg;
}
s->update_header (capture_info.front()->start, when, twhen);
s->set_captured_for (_name.val());
s->mark_immutable ();
@ -1903,13 +1900,8 @@ AudioDiskstream::use_new_write_source (uint32_t n)
ChannelInfo* chan = (*c)[n];
try {
/* file starts off as a stub file, it will be converted
when we're done with a capture pass.
*/
if ((chan->write_source = _session.create_audio_source_for_session (n_channels().n_audio(),
name(), n, destructive(),
true)) == 0) {
name(), n, destructive())) == 0) {
throw failed_constructor();
}
}

View File

@ -16,7 +16,6 @@ const char* const templates_dir_name = X_("templates");
const char* const route_templates_dir_name = X_("route_templates");
const char* const surfaces_dir_name = X_("surfaces");
const char* const user_config_dir_name = X_("ardour3");
const char* const stub_dir_name = X_(".stubs");
const char* const panner_dir_name = X_("panners");
}

View File

@ -60,6 +60,7 @@ FileSource::FileSource (Session& session, DataType type, const string& path, con
, _file_is_new(true)
, _channel (0)
, _origin (origin)
, _open (false)
{
set_within_session_from_path (path);
@ -99,11 +100,10 @@ FileSource::prevent_deletion ()
bool
FileSource::removable () const
{
bool r = (_path.find (stub_dir_name) != string::npos) ||
((_flags & Removable)
&& ((_flags & RemoveAtDestroy) ||
((_flags & RemovableIfEmpty) && empty() == 0)));
bool r = ((_flags & Removable)
&& ((_flags & RemoveAtDestroy) ||
((_flags & RemovableIfEmpty) && empty() == 0)));
return r;
}
@ -537,44 +537,6 @@ FileSource::set_within_session_from_path (const std::string& path)
_within_session = _session.path_is_within_session (path);
}
bool
FileSource::is_stub_path (const std::string& path)
{
return path.find (stub_dir_name) != string::npos;
}
bool
FileSource::is_stub () const
{
return is_stub_path (_path);
}
int
FileSource::unstubify ()
{
string::size_type pos = _path.find (stub_dir_name);
if (pos == string::npos || (_flags & Destructive)) {
return 0;
}
vector<string> v;
v.push_back (Glib::path_get_dirname (Glib::path_get_dirname (_path)));
v.push_back (Glib::path_get_basename(_path));
string newpath = Glib::build_filename (v);
if (::rename (_path.c_str(), newpath.c_str()) != 0) {
error << string_compose (_("rename from %1 to %2 failed: %3)"), _path, newpath, strerror (errno)) << endmsg;
return -1;
}
set_path (newpath);
return 0;
}
void
FileSource::set_path (const std::string& newpath)
{

View File

@ -981,10 +981,6 @@ MidiDiskstream::transport_stopped_wallclock (struct tm& /*when*/, time_t /*twhen
const double total_capture_beats = converter.from(total_capture);
_write_source->set_length_beats(total_capture_beats);
/* make it not a stub anymore */
_write_source->unstubify ();
/* we will want to be able to keep (over)writing the source
but we don't want it to be removable. this also differs
from the audio situation, where the source at this point
@ -1366,13 +1362,8 @@ MidiDiskstream::use_new_write_source (uint32_t n)
_write_source.reset();
try {
/* file starts off as a stub file, it will be converted
when we're done with a capture pass, or when "stolen"
by the GUI.
*/
_write_source = boost::dynamic_pointer_cast<SMFSource>(
_session.create_midi_source_for_session (0, name (), true));
_session.create_midi_source_for_session (0, name ()));
if (!_write_source) {
throw failed_constructor();
@ -1385,8 +1376,6 @@ MidiDiskstream::use_new_write_source (uint32_t n)
return -1;
}
_write_source->mark_streaming_midi_write_started (_note_mode, _session.transport_frame());
return 0;
}
@ -1403,8 +1392,6 @@ MidiDiskstream::steal_write_sources()
boost::dynamic_pointer_cast<MidiSource>(_write_source)->session_saved ();
/* make it visible/present */
_write_source->unstubify ();
/* never let it go away */
_write_source->mark_nonremovable ();

View File

@ -1335,7 +1335,7 @@ MidiModel::write_to (boost::shared_ptr<MidiSource> source)
assert (ms);
source->drop_model();
source->mark_streaming_midi_write_started (note_mode(), ms->timeline_position ());
source->mark_streaming_midi_write_started (note_mode());
for (Evoral::Sequence<TimeType>::const_iterator i = begin(0, true); i != end(); ++i) {
source->append_event_unlocked_beats(*i);
@ -1365,7 +1365,7 @@ MidiModel::sync_to_source ()
boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
assert (ms);
ms->mark_streaming_midi_write_started (note_mode(), ms->timeline_position());
ms->mark_streaming_midi_write_started (note_mode());
for (Evoral::Sequence<TimeType>::const_iterator i = begin(0, true); i != end(); ++i) {
ms->append_event_unlocked_beats(*i);
@ -1400,7 +1400,7 @@ MidiModel::write_section_to (boost::shared_ptr<MidiSource> source, Evoral::Music
assert (ms);
source->drop_model();
source->mark_streaming_midi_write_started (note_mode(), ms->timeline_position());
source->mark_streaming_midi_write_started (note_mode());
for (Evoral::Sequence<TimeType>::const_iterator i = begin(0, true); i != end(); ++i) {
const Evoral::Event<Evoral::MusicalTime>& ev (*i);

View File

@ -265,11 +265,11 @@ MidiSource::midi_write (MidiRingBuffer<framepos_t>& source, framepos_t source_st
}
void
MidiSource::mark_streaming_midi_write_started (NoteMode mode, framepos_t start_frame)
MidiSource::mark_streaming_midi_write_started (NoteMode mode)
{
if (_model) {
_model->set_note_mode(mode);
_model->start_write();
_model->set_note_mode (mode);
_model->start_write ();
}
_writing = true;
@ -297,7 +297,7 @@ void
MidiSource::mark_streaming_write_started ()
{
NoteMode note_mode = _model ? _model->note_mode() : Sustained;
mark_streaming_midi_write_started(note_mode, _session.transport_frame());
mark_streaming_midi_write_started (note_mode);
}
void

View File

@ -238,10 +238,6 @@ Session::destroy ()
delete state_tree;
/* remove all stubfiles that might still be lurking */
cleanup_stubfiles ();
/* reset dynamic state version back to default */
Stateful::loading_state_version = 0;
@ -2878,7 +2874,7 @@ Session::change_source_path_by_name (string path, string oldname, string newname
* (e.g. as returned by new_*_source_name)
*/
string
Session::new_source_path_from_name (DataType type, const string& name, bool as_stub)
Session::new_source_path_from_name (DataType type, const string& name)
{
assert(name.find("/") == string::npos);
@ -2886,9 +2882,9 @@ Session::new_source_path_from_name (DataType type, const string& name, bool as_s
sys::path p;
if (type == DataType::AUDIO) {
p = (as_stub ? sdir.sound_stub_path() : sdir.sound_path());
p = sdir.sound_path();
} else if (type == DataType::MIDI) {
p = (as_stub ? sdir.midi_stub_path() : sdir.midi_path());
p = sdir.midi_path();
} else {
error << "Unknown source type, unable to create file path" << endmsg;
return "";
@ -2968,7 +2964,6 @@ Session::new_audio_source_name (const string& base, uint32_t nchan, uint32_t cha
SessionDirectory sdir((*i).path);
string spath = sdir.sound_path().to_string();
string spath_stubs = sdir.sound_stub_path().to_string();
/* note that we search *without* the extension so that
we don't end up both "Audio 1-1.wav" and "Audio 1-1.caf"
@ -2976,8 +2971,7 @@ Session::new_audio_source_name (const string& base, uint32_t nchan, uint32_t cha
a file format change.
*/
if (matching_unsuffixed_filename_exists_in (spath, buf) ||
matching_unsuffixed_filename_exists_in (spath_stubs, buf)) {
if (matching_unsuffixed_filename_exists_in (spath, buf)) {
existing++;
break;
}
@ -3001,10 +2995,10 @@ Session::new_audio_source_name (const string& base, uint32_t nchan, uint32_t cha
/** Create a new within-session audio source */
boost::shared_ptr<AudioFileSource>
Session::create_audio_source_for_session (size_t n_chans, string const & n, uint32_t chan, bool destructive, bool as_stub)
Session::create_audio_source_for_session (size_t n_chans, string const & n, uint32_t chan, bool destructive)
{
const string name = new_audio_source_name (n, n_chans, chan, destructive);
const string path = new_source_path_from_name(DataType::AUDIO, name, as_stub);
const string path = new_source_path_from_name(DataType::AUDIO, name);
return boost::dynamic_pointer_cast<AudioFileSource> (
SourceFactory::createWritable (DataType::AUDIO, *this, path, string(), destructive, frame_rate()));
@ -3061,7 +3055,7 @@ Session::new_midi_source_name (const string& base)
/** Create a new within-session MIDI source */
boost::shared_ptr<MidiSource>
Session::create_midi_source_for_session (Track* track, string const & n, bool as_stub)
Session::create_midi_source_for_session (Track* track, string const & n)
{
/* try to use the existing write source for the track, to keep numbering sane
*/
@ -3080,7 +3074,7 @@ Session::create_midi_source_for_session (Track* track, string const & n, bool as
}
const string name = new_midi_source_name (n);
const string path = new_source_path_from_name (DataType::MIDI, name, as_stub);
const string path = new_source_path_from_name (DataType::MIDI, name);
return boost::dynamic_pointer_cast<SMFSource> (
SourceFactory::createWritable (

View File

@ -101,27 +101,12 @@ SessionDirectory::sound_path () const
return sources_root() / sound_dir_name;
}
const path
SessionDirectory::sound_stub_path () const
{
if(is_directory (old_sound_path ())) return old_sound_path();
// the new style sound directory
return sources_root() / sound_dir_name / stub_dir_name;
}
const path
SessionDirectory::midi_path () const
{
return sources_root() / midi_dir_name;
}
const path
SessionDirectory::midi_stub_path () const
{
return sources_root() / midi_dir_name / stub_dir_name;
}
const path
SessionDirectory::midi_patch_path () const
{

View File

@ -467,13 +467,6 @@ Session::ensure_subdirs ()
return -1;
}
dir = session_directory().sound_stub_path().to_string();
if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
error << string_compose(_("Session: cannot create session stub sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
return -1;
}
dir = session_directory().midi_path().to_string();
if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
@ -481,13 +474,6 @@ Session::ensure_subdirs ()
return -1;
}
dir = session_directory().midi_stub_path().to_string();
if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
error << string_compose(_("Session: cannot create session stub midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
return -1;
}
dir = session_directory().dead_path().to_string();
if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
@ -1236,8 +1222,6 @@ Session::set_state (const XMLNode& node, int version)
setup_raid_path(_session_dir->root_path().to_string());
cleanup_stubfiles ();
if ((prop = node.property (X_("id-counter"))) != 0) {
uint64_t x;
sscanf (prop->value().c_str(), "%" PRIu64, &x);
@ -2416,16 +2400,12 @@ Session::commit_reversible_command (Command *cmd)
}
static bool
accept_all_non_stub_audio_files (const string& path, void */*arg*/)
accept_all_audio_files (const string& path, void */*arg*/)
{
if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
return false;
}
if (FileSource::is_stub_path (path)) {
return false;
}
if (!AudioFileSource::safe_audio_file_extension (path)) {
return false;
}
@ -2434,16 +2414,12 @@ accept_all_non_stub_audio_files (const string& path, void */*arg*/)
}
static bool
accept_all_non_stub_midi_files (const string& path, void */*arg*/)
accept_all_midi_files (const string& path, void */*arg*/)
{
if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
return false;
}
if (FileSource::is_stub_path (path)) {
return false;
}
return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
(path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
(path.length() > 5 && path.find (".midi") != (path.length() - 5)));
@ -2686,8 +2662,8 @@ Session::cleanup_sources (CleanupReport& rep)
i = nexti;
}
candidates = scanner (audio_path, accept_all_non_stub_audio_files, (void *) 0, true, true);
candidates2 = scanner (midi_path, accept_all_non_stub_midi_files, (void *) 0, true, true);
candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
/* merge them */
@ -2718,22 +2694,18 @@ Session::cleanup_sources (CleanupReport& rep)
++tmp;
if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
if (!fs->is_stub()) {
if (playlists->source_use_count (fs) != 0) {
all_sources.insert (fs->path());
} else {
/* we might not remove this source from disk, because it may be used
by other snapshots, but its not being used in this version
so lets get rid of it now, along with any representative regions
in the region list.
*/
cerr << "Source " << i->second->name() << "ID " << i->second->id() << " not used, remove from source list and also all regions\n";
RegionFactory::remove_regions_using_source (i->second);
sources.erase (i);
}
if (playlists->source_use_count (fs) != 0) {
all_sources.insert (fs->path());
} else {
/* we might not remove this source from disk, because it may be used
by other snapshots, but its not being used in this version
so lets get rid of it now, along with any representative regions
in the region list.
*/
RegionFactory::remove_regions_using_source (i->second);
sources.erase (i);
}
}
@ -2920,45 +2892,6 @@ Session::cleanup_trash_sources (CleanupReport& rep)
return 0;
}
void
Session::cleanup_stubfiles ()
{
vector<space_and_path>::iterator i;
for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
string dir;
string lname = legalize_for_path (_name);
vector<string> v;
/* XXX this is a hack caused by semantic conflicts
between space_and_path and the SessionDirectory concept.
*/
v.push_back ((*i).path);
v.push_back ("interchange");
v.push_back (lname);
v.push_back ("audiofiles");
v.push_back (stub_dir_name);
dir = Glib::build_filename (v);
clear_directory (dir);
v.clear ();
v.push_back ((*i).path);
v.push_back ("interchange");
v.push_back (lname);
v.push_back ("midifiles");
v.push_back (stub_dir_name);
dir = Glib::build_filename (v);
clear_directory (dir);
}
}
void
Session::set_dirty ()
{

View File

@ -65,10 +65,8 @@ SMFSource::SMFSource (Session& s, const string& path, Source::Flag flags)
if (init(_path, false)) {
throw failed_constructor ();
}
if (create(path)) {
throw failed_constructor ();
}
/* file is not opened until write */
}
/** Constructor used for existing internal-to-session files. */
@ -92,6 +90,8 @@ SMFSource::SMFSource (Session& s, const XMLNode& node, bool must_exist)
if (open(_path)) {
throw failed_constructor ();
}
_open = true;
}
SMFSource::~SMFSource ()
@ -101,6 +101,16 @@ SMFSource::~SMFSource ()
}
}
int
SMFSource::open_for_write ()
{
if (create (_path)) {
return -1;
}
_open = true;
return 0;
}
/** All stamps in audio frames */
framecnt_t
SMFSource::read_unlocked (Evoral::EventSink<framepos_t>& destination, framepos_t const source_start,
@ -110,6 +120,11 @@ SMFSource::read_unlocked (Evoral::EventSink<framepos_t>& destination, framepos_t
int ret = 0;
uint64_t time = 0; // in SMF ticks, 1 tick per _ppqn
if (writable() && !_open) {
/* nothing to read since nothing has ben written */
return duration;
}
DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("SMF read_unlocked: start %1 duration %2\n", start, duration));
_read_data_count = 0;
@ -206,6 +221,15 @@ SMFSource::read_unlocked (Evoral::EventSink<framepos_t>& destination, framepos_t
framecnt_t
SMFSource::write_unlocked (MidiRingBuffer<framepos_t>& source, framepos_t position, framecnt_t duration)
{
if (!_open && open_for_write()) {
error << string_compose (_("cannot open MIDI file %1 for write"), _path) << endmsg;
return 0;
}
if (!_writing) {
mark_streaming_write_started ();
}
_write_data_count = 0;
framepos_t time;
@ -387,10 +411,11 @@ SMFSource::set_state (const XMLNode& node, int version)
}
void
SMFSource::mark_streaming_midi_write_started (NoteMode mode, framepos_t start_frame)
SMFSource::mark_streaming_midi_write_started (NoteMode mode)
{
Glib::Mutex::Lock lm (_lock);
MidiSource::mark_streaming_midi_write_started (mode, start_frame);
/* CALLER MUST HOLD LOCK */
MidiSource::mark_streaming_midi_write_started (mode);
Evoral::SMF::begin_write ();
_last_ev_time_beats = 0.0;
_last_ev_time_frames = 0;
@ -444,6 +469,10 @@ SMFSource::load_model (bool lock, bool force_reload)
_model->clear();
}
if (writable() && !_open) {
return;
}
_model->start_write();
Evoral::SMF::seek_to_start();
@ -533,7 +562,7 @@ SMFSource::destroy_model ()
void
SMFSource::flush_midi ()
{
if (!writable()) {
if (!writable() || (writable() && !_open)) {
return;
}

View File

@ -89,7 +89,7 @@ SndFileSource::SndFileSource (Session& s, const string& path, const string& orig
{
int fmt = 0;
init_sndfile ();
init_sndfile ();
_file_is_new = true;
@ -143,37 +143,9 @@ SndFileSource::SndFileSource (Session& s, const string& path, const string& orig
_info.channels = 1;
_info.samplerate = rate;
_info.format = fmt;
if (open()) {
throw failed_constructor();
}
if (writable() && (_flags & Broadcast)) {
SNDFILE* sf = _descriptor->allocate ();
if (sf == 0) {
error << string_compose (_("could not allocate file %1"), _path) << endmsg;
throw failed_constructor ();
}
if (!_broadcast_info) {
_broadcast_info = new BroadcastInfo;
}
_broadcast_info->set_from_session (s, header_position_offset);
_broadcast_info->set_description (string_compose ("BWF %1", _name));
if (!_broadcast_info->write_to_file (sf)) {
error << string_compose (_("cannot set broadcast info for audio file %1 (%2); dropping broadcast info for this file"),
_path, _broadcast_info->get_error())
<< endmsg;
_flags = Flag (_flags & ~Broadcast);
delete _broadcast_info;
_broadcast_info = 0;
}
_descriptor->release ();
}
/* do not open the file here - do that in write_unlocked() as needed
*/
}
void
@ -181,6 +153,8 @@ SndFileSource::init_sndfile ()
{
string file;
_descriptor = 0;
// lets try to keep the object initalizations here at the top
xfade_buf = 0;
_broadcast_info = 0;
@ -253,9 +227,29 @@ SndFileSource::open ()
if (writable()) {
sf_command (sf, SFC_SET_UPDATE_HEADER_AUTO, 0, SF_FALSE);
}
if (_flags & Broadcast) {
if (!_broadcast_info) {
_broadcast_info = new BroadcastInfo;
}
_broadcast_info->set_from_session (_session, header_position_offset);
_broadcast_info->set_description (string_compose ("BWF %1", _name));
if (!_broadcast_info->write_to_file (sf)) {
error << string_compose (_("cannot set broadcast info for audio file %1 (%2); dropping broadcast info for this file"),
_path, _broadcast_info->get_error())
<< endmsg;
_flags = Flag (_flags & ~Broadcast);
delete _broadcast_info;
_broadcast_info = 0;
}
}
}
_descriptor->release ();
_descriptor->release ();
_open = true;
return 0;
}
@ -280,7 +274,14 @@ SndFileSource::read_unlocked (Sample *dst, framepos_t start, framecnt_t cnt) con
uint32_t real_cnt;
framepos_t file_cnt;
if (writable() && !_open) {
/* file has not been opened yet - nothing written to it */
memset (dst, 0, sizeof (Sample) * cnt);
return cnt;
}
SNDFILE* sf = _descriptor->allocate ();
if (sf == 0) {
error << string_compose (_("could not allocate file %1 for reading."), _path) << endmsg;
return 0;
@ -357,6 +358,10 @@ SndFileSource::read_unlocked (Sample *dst, framepos_t start, framecnt_t cnt) con
framecnt_t
SndFileSource::write_unlocked (Sample *data, framecnt_t cnt)
{
if (!_open && open()) {
return 0; // failure
}
if (destructive()) {
return destructive_write_unlocked (data, cnt);
} else {
@ -511,6 +516,11 @@ SndFileSource::flush_header ()
return -1;
}
if (!_open) {
warning << string_compose (_("attempt to flush an un-opened audio file source (%1)"), _path) << endmsg;
return -1;
}
SNDFILE* sf = _descriptor->allocate ();
if (sf == 0) {
error << string_compose (_("could not allocate file %1 to write header"), _path) << endmsg;
@ -531,6 +541,11 @@ SndFileSource::setup_broadcast_info (framepos_t /*when*/, struct tm& now, time_t
return -1;
}
if (!_open) {
warning << string_compose (_("attempt to set BWF info for an un-opened audio file source (%1)"), _path) << endmsg;
return -1;
}
if (!(_flags & Broadcast)) {
return 0;
}