From 672a31a552ae0bd67d40a0c078306d3a63a44746 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Mon, 5 Feb 2007 22:57:38 +0000 Subject: [PATCH] use SilentFileSource when sources cannot be found git-svn-id: svn://localhost/ardour2/trunk@1424 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/ardour.bindings | 1 - libs/ardour/SConscript | 1 + libs/ardour/ardour/audiofilesource.h | 9 +++- libs/ardour/ardour/silentfilesource.h | 66 +++++++++++++++++++++++++++ libs/ardour/ardour/source_factory.h | 1 + libs/ardour/audio_diskstream.cc | 2 +- libs/ardour/audiofilesource.cc | 6 +-- libs/ardour/session_state.cc | 26 +++++++++-- libs/ardour/silentfilesource.cc | 39 ++++++++++++++++ libs/ardour/source_factory.cc | 31 ++++++++++--- 10 files changed, 167 insertions(+), 15 deletions(-) create mode 100644 libs/ardour/ardour/silentfilesource.h create mode 100644 libs/ardour/silentfilesource.cc diff --git a/gtk2_ardour/ardour.bindings b/gtk2_ardour/ardour.bindings index beec8fca38..b9d17e138f 100644 --- a/gtk2_ardour/ardour.bindings +++ b/gtk2_ardour/ardour.bindings @@ -112,7 +112,6 @@ (gtk_accel_path "/Editor/extend-range-to-end-of-region" "rightanglebracket") (gtk_accel_path "/Editor/scroll-backward" "leftarrow") (gtk_accel_path "/Editor/start-range" "KP_Down") -; (gtk_accel_path "/Editor/ToggleTranzportSurface" "") ; (gtk_accel_path "/ShuttleActions/SetShuttleUnitsSemitones" "") ; (gtk_accel_path "/JACK/JACKLatency128" "") ; (gtk_accel_path "/Snap/snap-to-beat" "") diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript index b602613a6a..3772246f11 100644 --- a/libs/ardour/SConscript +++ b/libs/ardour/SConscript @@ -87,6 +87,7 @@ session_state.cc session_time.cc session_timefx.cc session_transport.cc +silentfilesource.cc sndfile_helpers.cc sndfilesource.cc source.cc diff --git a/libs/ardour/ardour/audiofilesource.h b/libs/ardour/ardour/audiofilesource.h index f91f78f6d9..4daa8c24f4 100644 --- a/libs/ardour/ardour/audiofilesource.h +++ b/libs/ardour/ardour/audiofilesource.h @@ -20,12 +20,19 @@ #ifndef __ardour_audiofilesource_h__ #define __ardour_audiofilesource_h__ +#include + #include #include namespace ARDOUR { +class non_existent_source : public std::exception { + public: + virtual const char *what() const throw() { return "audio file does not exist"; } +}; + struct SoundFileInfo { float samplerate; uint16_t channels; @@ -125,7 +132,7 @@ class AudioFileSource : public AudioSource { /* constructor to be called for existing in-session files */ - AudioFileSource (Session&, const XMLNode&); + AudioFileSource (Session&, const XMLNode&, bool must_exit = true); int init (string idstr, bool must_exist); diff --git a/libs/ardour/ardour/silentfilesource.h b/libs/ardour/ardour/silentfilesource.h new file mode 100644 index 0000000000..92ef076a9b --- /dev/null +++ b/libs/ardour/ardour/silentfilesource.h @@ -0,0 +1,66 @@ +/* + Copyright (C) 2007 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __ardour_silentfilesource_h__ +#define __ardour_silentfilesource_h__ + +#include + +namespace ARDOUR { + +class SilentFileSource : public AudioFileSource { + public: + virtual ~SilentFileSource (); + + int update_header (nframes_t when, struct tm&, time_t) { return 0; } + int flush_header () { return 0; } + float sample_rate () const { return _sample_rate; } + + void set_length (nframes_t len); + + int read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nframes_t cnt, double samples_per_unit) const { + memset (peaks, 0, sizeof (PeakData) * npeaks); + return 0; + } + + bool destructive() const { return false; } + + protected: + + float _sample_rate; + + SilentFileSource (Session&, const XMLNode&, nframes_t nframes, float sample_rate); + + friend class SourceFactory; + + nframes_t read_unlocked (Sample *dst, nframes_t start, nframes_t cnt) const { + memset (dst, 0, sizeof (Sample) * cnt); + return cnt; + } + + nframes_t write_unlocked (Sample *dst, nframes_t cnt) { return 0; } + + void set_header_timeline_position () {} + +}; + +} // namespace ARDOUR + +#endif /* __ardour_audiofilesource_h__ */ + diff --git a/libs/ardour/ardour/source_factory.h b/libs/ardour/ardour/source_factory.h index 207015a253..cc3863904a 100644 --- a/libs/ardour/ardour/source_factory.h +++ b/libs/ardour/ardour/source_factory.h @@ -20,6 +20,7 @@ class SourceFactory { static sigc::signal > SourceCreated; static boost::shared_ptr create (Session&, const XMLNode& node); + static boost::shared_ptr createSilent (Session&, const XMLNode& node, nframes_t nframes, float sample_rate); // MIDI sources will have to be hacked in here somehow static boost::shared_ptr createReadable (Session&, std::string path, int chn, AudioFileSource::Flag flags, bool announce = true); diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index 44d5c19ab1..9c101bd757 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -1480,7 +1480,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca srcs.push_back (s); s->update_header (capture_info.front()->start, when, twhen); s->set_captured_for (_name); - + s->mark_immutable (); } } diff --git a/libs/ardour/audiofilesource.cc b/libs/ardour/audiofilesource.cc index b74f6b370f..409fc04683 100644 --- a/libs/ardour/audiofilesource.cc +++ b/libs/ardour/audiofilesource.cc @@ -88,7 +88,7 @@ AudioFileSource::AudioFileSource (Session& s, std::string path, Flag flags, Samp } } -AudioFileSource::AudioFileSource (Session& s, const XMLNode& node) +AudioFileSource::AudioFileSource (Session& s, const XMLNode& node, bool must_exist) : AudioSource (s, node), _flags (Flag (Writable|CanRename)) /* channel is set in set_state() */ { @@ -98,7 +98,7 @@ AudioFileSource::AudioFileSource (Session& s, const XMLNode& node) throw failed_constructor (); } - if (init (_name, true)) { + if (init (_name, must_exist)) { throw failed_constructor (); } } @@ -135,7 +135,7 @@ AudioFileSource::init (string pathstr, bool must_exist) file_is_new = false; if (!find (pathstr, must_exist, is_new)) { - return -1; + throw non_existent_source (); } if (is_new && must_exist) { diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 42aac479a1..9c2e854486 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -64,6 +64,7 @@ #include #include #include +#include #include #include #include @@ -1391,6 +1392,19 @@ Session::XMLRegionFactory (const XMLNode& node, bool full) try { boost::shared_ptr region (boost::dynamic_pointer_cast (RegionFactory::create (sources, node))); + + /* a final detail: this is the one and only place that we know how long missing files are */ + + if (region->whole_file()) { + for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) { + boost::shared_ptr sfp = boost::dynamic_pointer_cast (*sx); + if (sfp) { + sfp->set_length (region->length()); + } + } + } + + return region; } @@ -1452,10 +1466,16 @@ Session::load_sources (const XMLNode& node) for (niter = nlist.begin(); niter != nlist.end(); ++niter) { - if ((source = XMLSourceFactory (**niter)) == 0) { - error << _("Session: cannot create Source from XML description.") << endmsg; + try { + if ((source = XMLSourceFactory (**niter)) == 0) { + error << _("Session: cannot create Source from XML description.") << endmsg; + } } + catch (non_existent_source& err) { + warning << _("A sound file is missing. It will be replaced by silence.") << endmsg; + source = SourceFactory::createSilent (*this, **niter, max_frames, _current_frame_rate); + } } return 0; @@ -1471,7 +1491,7 @@ Session::XMLSourceFactory (const XMLNode& node) try { return SourceFactory::create (*this, node); } - + catch (failed_constructor& err) { error << _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg; return boost::shared_ptr(); diff --git a/libs/ardour/silentfilesource.cc b/libs/ardour/silentfilesource.cc new file mode 100644 index 0000000000..b34944e342 --- /dev/null +++ b/libs/ardour/silentfilesource.cc @@ -0,0 +1,39 @@ +/* + Copyright (C) 2007 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include + +using namespace ARDOUR; + +SilentFileSource::SilentFileSource (Session& s, const XMLNode& node, nframes_t len, float sr) + : AudioFileSource (s, node, false) +{ + _length = len; + _sample_rate = sr; +} + +SilentFileSource::~SilentFileSource () +{ +} + +void +SilentFileSource::set_length (nframes_t len) +{ + _length = len; +} diff --git a/libs/ardour/source_factory.cc b/libs/ardour/source_factory.cc index 2cbd7624be..7b2103cdc6 100644 --- a/libs/ardour/source_factory.cc +++ b/libs/ardour/source_factory.cc @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -51,6 +52,17 @@ SourceFactory::setup_peakfile (boost::shared_ptr s) return 0; } +boost::shared_ptr +SourceFactory::createSilent (Session& s, const XMLNode& node, nframes_t nframes, float sr) +{ + boost::shared_ptr ret (new SilentFileSource (s, node, nframes, sr)); + if (setup_peakfile (ret)) { + return boost::shared_ptr(); + } + SourceCreated (ret); + return ret; +} + #ifdef HAVE_COREAUDIO boost::shared_ptr SourceFactory::create (Session& s, const XMLNode& node) @@ -63,9 +75,12 @@ SourceFactory::create (Session& s, const XMLNode& node) SourceCreated (ret); return ret; } - - - catch (failed_constructor& err) { + + + catch (failed_constructor& err) { + + /* this is allowed to throw */ + boost::shared_ptr ret (new SndFileSource (s, node)); if (setup_peakfile (ret)) { return boost::shared_ptr(); @@ -82,14 +97,15 @@ SourceFactory::create (Session& s, const XMLNode& node) boost::shared_ptr SourceFactory::create (Session& s, const XMLNode& node) { - boost::shared_ptr ret (new SndFileSource (s, node)); + /* this is allowed to throw */ + boost::shared_ptr ret (new SndFileSource (s, node)); + if (setup_peakfile (ret)) { return boost::shared_ptr(); } - + SourceCreated (ret); - return ret; } @@ -113,6 +129,9 @@ SourceFactory::createReadable (Session& s, string path, int chn, AudioFileSource } catch (failed_constructor& err) { + + /* this is allowed to throw */ + boost::shared_ptr ret (new SndFileSource (s, path, chn, flags)); if (setup_peakfile (ret)) { return boost::shared_ptr();