#include <glibmm/miscutils.h>
#include <glibmm/fileutils.h>
+#include <glibmm/thread.h>
#include <ardour/audiofilesource.h>
#include <ardour/sndfile_helpers.h>
/* 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)
throw failed_constructor ();
}
+ fix_writable_flags ();
}
AudioFileSource::AudioFileSource (Session& s, ustring path, Flag flags, SampleFormat samp_format, HeaderFormat hdr_format)
if (init (path, false)) {
throw failed_constructor ();
}
+
+ fix_writable_flags ();
}
AudioFileSource::AudioFileSource (Session& s, const XMLNode& node, bool must_exist)
if (init (foo, must_exist)) {
throw failed_constructor ();
}
+
+ fix_writable_flags ();
}
AudioFileSource::~AudioFileSource ()
}
}
+void
+AudioFileSource::fix_writable_flags ()
+{
+ if (!_session.writable()) {
+ _flags = Flag (_flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy|CanRename));
+ }
+}
+
bool
AudioFileSource::determine_embeddedness (ustring path)
{
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;
}
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
}
+ fix_writable_flags ();
+
if ((prop = node.property (X_("channel"))) != 0) {
_channel = atoi (prop->value());
} else {
// 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;
}
}
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;
}
}
- _name = pathstr;
- _path = keeppath;
+ name = pathstr;
+ path = keeppath;
ret = true;
} else {
}
}
- _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)) {
/* 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;
}
} else {
_flags = Flag (_flags & ~RemovableIfEmpty);
}
+
+ fix_writable_flags ();
}
int
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
_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;
+}