when renaming redirects, scan all routes AND sends AND port inserts for the name...
[ardour.git] / libs / ardour / audiofilesource.cc
index 73629368267bafcc59cf6e84e3a86343466286ea..b1ec8a3baa7c543b5a283c5f344b2bf3d982d49d 100644 (file)
@@ -39,6 +39,7 @@
 
 #include <glibmm/miscutils.h>
 #include <glibmm/fileutils.h>
+#include <glibmm/thread.h>
 
 #include <ardour/audiofilesource.h>
 #include <ardour/sndfile_helpers.h>
@@ -69,6 +70,21 @@ uint64_t           AudioFileSource::header_position_offset = 0;
 /* XXX maybe this too */
 char   AudioFileSource::bwf_serial_number[13] = "000000000000";
 
+struct SizedSampleBuffer {
+    nframes_t size;
+    Sample* buf;
+
+    SizedSampleBuffer (nframes_t sz) : size (sz) { 
+           buf = new Sample[size];
+    }
+
+    ~SizedSampleBuffer() {
+           delete [] buf;
+    }
+};
+
+Glib::StaticPrivate<SizedSampleBuffer> thread_interleave_buffer = GLIBMM_STATIC_PRIVATE_INIT;
+
 AudioFileSource::AudioFileSource (Session& s, ustring path, Flag flags)
        : AudioSource (s, path), _flags (flags),
          _channel (0)
@@ -80,6 +96,7 @@ AudioFileSource::AudioFileSource (Session& s, ustring path, Flag flags)
                throw failed_constructor ();
        }
 
+       fix_writable_flags ();
 }
 
 AudioFileSource::AudioFileSource (Session& s, ustring path, Flag flags, SampleFormat samp_format, HeaderFormat hdr_format)
@@ -92,6 +109,8 @@ AudioFileSource::AudioFileSource (Session& s, ustring path, Flag flags, SampleFo
        if (init (path, false)) {
                throw failed_constructor ();
        }
+
+       fix_writable_flags ();
 }
 
 AudioFileSource::AudioFileSource (Session& s, const XMLNode& node, bool must_exist)
@@ -109,6 +128,8 @@ AudioFileSource::AudioFileSource (Session& s, const XMLNode& node, bool must_exi
        if (init (foo, must_exist)) {
                throw failed_constructor ();
        }
+
+       fix_writable_flags ();
 }
 
 AudioFileSource::~AudioFileSource ()
@@ -119,6 +140,14 @@ AudioFileSource::~AudioFileSource ()
        }
 }
 
+void
+AudioFileSource::fix_writable_flags ()
+{
+       if (!_session.writable()) {
+               _flags = Flag (_flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy|CanRename));
+       }
+}
+
 bool
 AudioFileSource::determine_embeddedness (ustring path)
 {
@@ -131,21 +160,28 @@ AudioFileSource::removable () const
        return (_flags & Removable) && ((_flags & RemoveAtDestroy) || ((_flags & RemovableIfEmpty) && length() == 0));
 }
 
+bool
+AudioFileSource::writable() const
+{
+       return (_flags & Writable);
+}
+
 int
 AudioFileSource::init (ustring pathstr, bool must_exist)
 {
-       bool is_new = false;
-
        _length = 0;
        timeline_position = 0;
        _peaks_built = false;
-       file_is_new = false;
 
-       if (!find (pathstr, must_exist, is_new, _channel)) {
+       /* is_embedded() can't work yet, because our _path is not set */
+
+       bool embedded = determine_embeddedness (pathstr);
+
+       if (!find (pathstr, must_exist, embedded, file_is_new, _channel, _path, _name)) {
                throw non_existent_source ();
        }
 
-       if (is_new && must_exist) {
+       if (file_is_new && must_exist) {
                return -1;
        }
 
@@ -209,13 +245,7 @@ AudioFileSource::find_broken_peakfile (ustring peak_path, ustring audio_path)
 ustring
 AudioFileSource::broken_peak_path (ustring audio_path)
 {
-       ustring res;
-
-       res = _session.peak_dir ();
-       res += PBD::basename_nosuffix (audio_path);
-       res += ".peak";
-
-       return res;
+       return Glib::build_filename(_session.peak_dir (), PBD::basename_nosuffix (audio_path) + ".peak");
 }
 
 ustring
@@ -287,6 +317,8 @@ AudioFileSource::set_state (const XMLNode& node)
 
        }
 
+       fix_writable_flags ();
+
        if ((prop = node.property (X_("channel"))) != 0) {
                _channel = atoi (prop->value());
        } else {
@@ -313,7 +345,7 @@ AudioFileSource::mark_for_remove ()
        // This operation is not allowed for sources for destructive tracks or embedded files.
        // Fortunately mark_for_remove() is never called for embedded files. This function
        // must be fixed if that ever happens.
-       if (_flags & Destructive) {
+       if (!_session.writable() || (_flags & Destructive)) {
                return;
        }
 
@@ -432,7 +464,9 @@ AudioFileSource::move_to_trash (const ustring& trash_dir_name)
 }
 
 bool
-AudioFileSource::find (ustring& pathstr, bool must_exist, bool& isnew, uint16_t& chan)
+AudioFileSource::find (ustring pathstr, bool must_exist, bool embedded,
+                      bool& isnew, uint16_t& chan, 
+                      ustring& path, std::string& name)
 {
        ustring::size_type pos;
        bool ret = false;
@@ -534,8 +568,8 @@ AudioFileSource::find (ustring& pathstr, bool must_exist, bool& isnew, uint16_t&
                        }
                }
 
-               _name = pathstr;
-               _path = keeppath;
+               name = pathstr;
+               path = keeppath;
                ret = true;
 
        } else {
@@ -554,12 +588,12 @@ AudioFileSource::find (ustring& pathstr, bool must_exist, bool& isnew, uint16_t&
                        }
                }
                
-               _path = pathstr;
+               path = pathstr;
 
-               if (is_embedded()) {
-                       _name = pathstr;
+               if (embedded) {
+                       name = pathstr;
                } else {
-                       _name = pathstr.substr (pathstr.find_last_of ('/') + 1);
+                       name = Glib::path_get_basename (pathstr);
                }
 
                if (!Glib::file_test (pathstr, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
@@ -567,12 +601,12 @@ AudioFileSource::find (ustring& pathstr, bool must_exist, bool& isnew, uint16_t&
                        /* file does not exist or we cannot read it */
                        
                        if (must_exist) {
-                               error << string_compose(_("Filesource: cannot find required file (%1): %2"), _path, strerror (errno)) << endmsg;
+                               error << string_compose(_("Filesource: cannot find required file (%1): %2"), pathstr, strerror (errno)) << endmsg;
                                goto out;
                        }
                        
                        if (errno != ENOENT) {
-                               error << string_compose(_("Filesource: cannot check for existing file (%1): %2"), _path, strerror (errno)) << endmsg;
+                               error << string_compose(_("Filesource: cannot check for existing file (%1): %2"), pathstr, strerror (errno)) << endmsg;
                                goto out;
                        }
                        
@@ -625,6 +659,8 @@ AudioFileSource::set_allow_remove_if_empty (bool yn)
        } else {
                _flags = Flag (_flags & ~RemovableIfEmpty);
        }
+
+       fix_writable_flags ();
 }
 
 int
@@ -683,27 +719,38 @@ AudioFileSource::setup_peakfile ()
 bool
 AudioFileSource::safe_file_extension(ustring file)
 {
-       return !(file.rfind(".wav") == ustring::npos &&
-               file.rfind(".aiff")== ustring::npos &&
-               file.rfind(".aif") == ustring::npos &&
-               file.rfind(".snd") == ustring::npos &&
-               file.rfind(".au")  == ustring::npos &&
-               file.rfind(".raw") == ustring::npos &&
-               file.rfind(".sf")  == ustring::npos &&
-               file.rfind(".cdr") == ustring::npos &&
-               file.rfind(".smp") == ustring::npos &&
-               file.rfind(".maud")== ustring::npos &&
-               file.rfind(".vwe") == ustring::npos &&
-               file.rfind(".paf") == ustring::npos &&
-#ifdef HAVE_FLAC
-               file.rfind(".flac")== ustring::npos &&
-#endif // HAVE_FLAC
+       const char* suffixes[] = {
+               ".wav", ".WAV",
+               ".aiff", ".AIFF",
+               ".caf", ".CAF",
+               ".aif", ".AIF",
+               ".amb", ".AMB",
+               ".snd", ".SND",
+               ".au", ".AU",
+               ".raw", ".RAW",
+               ".sf", ".SF",
+               ".cdr", ".CDR",
+               ".smp", ".SMP",
+               ".maud", ".MAUD",
+               ".vwe", ".VWE",
+               ".paf",
+               ".flac", ".FLAC",
+               ".ogg", ".OGG",
 #ifdef HAVE_COREAUDIO
-               file.rfind(".mp3") == ustring::npos &&
-               file.rfind(".aac") == ustring::npos &&
-               file.rfind(".mp4") == ustring::npos &&
+               ".mp3", ".MP3",
+               ".aac", ".AAC",
+               ".mp4", ".MP4",
 #endif // HAVE_COREAUDIO
-               file.rfind(".voc") == ustring::npos);
+               ".voc", ".VOC"
+       };
+
+       for (size_t n = 0; n < sizeof(suffixes)/sizeof(suffixes[0]); ++n) {
+               if (file.rfind (suffixes[n]) == file.length() - strlen (suffixes[n])) {
+                       return true;
+               }
+       }
+
+       return false;
 }
 
 void
@@ -717,3 +764,22 @@ AudioFileSource::mark_immutable ()
                _flags = Flag (_flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy|CanRename));
        }
 }
+
+
+Sample*
+AudioFileSource::get_interleave_buffer (nframes_t size)
+{
+       SizedSampleBuffer* ssb;
+
+       if ((ssb = thread_interleave_buffer.get()) == 0) {
+               ssb = new SizedSampleBuffer (size);
+               thread_interleave_buffer.set (ssb);
+       }
+
+       if (ssb->size < size) {
+               ssb = new SizedSampleBuffer (size);
+               thread_interleave_buffer.set (ssb);
+       }
+
+       return ssb->buf;
+}