use SilentFileSource when sources cannot be found
authorPaul Davis <paul@linuxaudiosystems.com>
Mon, 5 Feb 2007 22:57:38 +0000 (22:57 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Mon, 5 Feb 2007 22:57:38 +0000 (22:57 +0000)
git-svn-id: svn://localhost/ardour2/trunk@1424 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/ardour.bindings
libs/ardour/SConscript
libs/ardour/ardour/audiofilesource.h
libs/ardour/ardour/silentfilesource.h [new file with mode: 0644]
libs/ardour/ardour/source_factory.h
libs/ardour/audio_diskstream.cc
libs/ardour/audiofilesource.cc
libs/ardour/session_state.cc
libs/ardour/silentfilesource.cc [new file with mode: 0644]
libs/ardour/source_factory.cc

index beec8fca381c66bc8d6319ad0960eb1727f3906a..b9d17e138fb4e87693a137fd34f8d88c0a4e0deb 100644 (file)
 (gtk_accel_path "<Actions>/Editor/extend-range-to-end-of-region" "rightanglebracket")
 (gtk_accel_path "<Actions>/Editor/scroll-backward" "leftarrow")
 (gtk_accel_path "<Actions>/Editor/start-range" "<Control>KP_Down")
-; (gtk_accel_path "<Actions>/Editor/ToggleTranzportSurface" "")
 ; (gtk_accel_path "<Actions>/ShuttleActions/SetShuttleUnitsSemitones" "")
 ; (gtk_accel_path "<Actions>/JACK/JACKLatency128" "")
 ; (gtk_accel_path "<Actions>/Snap/snap-to-beat" "")
index b602613a6a2faaf0d2cdcf14b16f1fb3b6504039..3772246f111eba50445c82248ee7426ea1c983c1 100644 (file)
@@ -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
index f91f78f6d961586573e4e2b6ad5ba691dc8b499b..4daa8c24f40f3476f599a46a56a6056fab7ae88b 100644 (file)
 #ifndef __ardour_audiofilesource_h__ 
 #define __ardour_audiofilesource_h__
 
+#include <exception>
+
 #include <time.h>
 
 #include <ardour/audiosource.h>
 
 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 (file)
index 0000000..92ef076
--- /dev/null
@@ -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 <ardour/audiofilesource.h>
+
+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__ */
+
index 207015a2530af5aa0e980d64c38927776705e5c7..cc3863904ac3b6983b0ec51eb8bc3e336af788a1 100644 (file)
@@ -20,6 +20,7 @@ class SourceFactory {
        static sigc::signal<void,boost::shared_ptr<Source> > SourceCreated;
 
        static boost::shared_ptr<Source> create (Session&, const XMLNode& node);
+       static boost::shared_ptr<Source> 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<Source> createReadable (Session&, std::string path, int chn, AudioFileSource::Flag flags, bool announce = true);
index 44d5c19ab1e787f90a1ddb832bfc1d104a81ff24..9c101bd757ee27fd589f25e7a08780fa5bc269c3 100644 (file)
@@ -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 ();
                }
        }
 
index b74f6b370f396a12e3fa85a2404a8b1a04b65893..409fc0468332c5bdb0e6e3ca842d4078272ff9c2 100644 (file)
@@ -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) {
index 42aac479a19bf8ddb2937f9d70adb2dd5b6fbef0..9c2e85448664e92eafa21e6ec79201dc256e42ca 100644 (file)
@@ -64,6 +64,7 @@
 #include <ardour/utils.h>
 #include <ardour/audioplaylist.h>
 #include <ardour/audiofilesource.h>
+#include <ardour/silentfilesource.h>
 #include <ardour/destructive_filesource.h>
 #include <ardour/sndfile_helpers.h>
 #include <ardour/auditioner.h>
@@ -1391,6 +1392,19 @@ Session::XMLRegionFactory (const XMLNode& node, bool full)
        
        try {
                boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (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<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*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<Source>();
diff --git a/libs/ardour/silentfilesource.cc b/libs/ardour/silentfilesource.cc
new file mode 100644 (file)
index 0000000..b34944e
--- /dev/null
@@ -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 <ardour/silentfilesource.h>
+
+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;
+}
index 2cbd7624be982853330e4553633670c1728a73d0..7b2103cdc663b5510a471266a52127bf4093a389 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <ardour/source_factory.h>
 #include <ardour/sndfilesource.h>
+#include <ardour/silentfilesource.h>
 #include <ardour/destructive_filesource.h>
 #include <ardour/configuration.h>
 
@@ -51,6 +52,17 @@ SourceFactory::setup_peakfile (boost::shared_ptr<Source> s)
        return 0;
 }
 
+boost::shared_ptr<Source>
+SourceFactory::createSilent (Session& s, const XMLNode& node, nframes_t nframes, float sr)
+{
+       boost::shared_ptr<Source> ret (new SilentFileSource (s, node, nframes, sr));
+       if (setup_peakfile (ret)) {
+               return boost::shared_ptr<Source>();
+       }
+       SourceCreated (ret);
+       return ret;
+}
+
 #ifdef HAVE_COREAUDIO
 boost::shared_ptr<Source>
 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<Source> ret (new SndFileSource (s, node));
                if (setup_peakfile (ret)) {
                        return boost::shared_ptr<Source>();
@@ -82,14 +97,15 @@ SourceFactory::create (Session& s, const XMLNode& node)
 boost::shared_ptr<Source>
 SourceFactory::create (Session& s, const XMLNode& node)
 {
-       boost::shared_ptr<Source> ret (new SndFileSource (s, node));
+       /* this is allowed to throw */
 
+       boost::shared_ptr<Source> ret (new SndFileSource (s, node));
+       
        if (setup_peakfile (ret)) {
                return boost::shared_ptr<Source>();
        }
-
+       
        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<Source> ret (new SndFileSource (s, path, chn, flags));
                        if (setup_peakfile (ret)) {
                                return boost::shared_ptr<Source>();