summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/ardour.bindings1
-rw-r--r--libs/ardour/SConscript1
-rw-r--r--libs/ardour/ardour/audiofilesource.h9
-rw-r--r--libs/ardour/ardour/silentfilesource.h66
-rw-r--r--libs/ardour/ardour/source_factory.h1
-rw-r--r--libs/ardour/audio_diskstream.cc2
-rw-r--r--libs/ardour/audiofilesource.cc6
-rw-r--r--libs/ardour/session_state.cc26
-rw-r--r--libs/ardour/silentfilesource.cc39
-rw-r--r--libs/ardour/source_factory.cc31
10 files changed, 167 insertions, 15 deletions
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 "<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" "")
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 <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
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 <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__ */
+
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<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);
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 <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
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 <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;
+}
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 <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>();