fix import/embed of multichannel audiofiles, as per #1433
git-svn-id: svn://localhost/ardour2/trunk@1386 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
@@ -101,6 +101,10 @@ class AudioFileSource : public AudioSource {
|
||||
bool destructive() const { return (_flags & Destructive); }
|
||||
virtual bool set_destructive (bool yn) { return false; }
|
||||
|
||||
Flag flags() const { return _flags; }
|
||||
|
||||
void mark_immutable ();
|
||||
|
||||
/* this should really be protected, but C++ is getting stricter
|
||||
and creating slots from protected member functions is starting
|
||||
to cause issues.
|
||||
@@ -125,12 +129,12 @@ class AudioFileSource : public AudioSource {
|
||||
|
||||
int init (string idstr, bool must_exist);
|
||||
|
||||
uint16_t channel;
|
||||
string _path;
|
||||
Flag _flags;
|
||||
string _take_id;
|
||||
int64_t timeline_position;
|
||||
bool file_is_new;
|
||||
uint16_t channel;
|
||||
|
||||
bool _is_embedded;
|
||||
static bool determine_embeddedness(string path);
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace ARDOUR {
|
||||
class CoreAudioSource : public AudioFileSource {
|
||||
public:
|
||||
CoreAudioSource (ARDOUR::Session&, const XMLNode&);
|
||||
CoreAudioSource (ARDOUR::Session&, const string& path_plus_channel, Flag);
|
||||
CoreAudioSource (ARDOUR::Session&, const string& path, int chn, Flag);
|
||||
~CoreAudioSource ();
|
||||
|
||||
float sample_rate() const;
|
||||
|
||||
@@ -31,7 +31,7 @@ class SndFileSource : public AudioFileSource {
|
||||
public:
|
||||
/* constructor to be called for existing external-to-session files */
|
||||
|
||||
SndFileSource (Session&, std::string path, Flag flags);
|
||||
SndFileSource (Session&, std::string path, int chn, Flag flags);
|
||||
|
||||
/* constructor to be called for new in-session files */
|
||||
|
||||
@@ -78,7 +78,7 @@ class SndFileSource : public AudioFileSource {
|
||||
mutable float *interleave_buf;
|
||||
mutable nframes_t interleave_bufsize;
|
||||
|
||||
void init (string str);
|
||||
void init ();
|
||||
int open();
|
||||
void close();
|
||||
int setup_broadcast_info (nframes_t when, struct tm&, time_t);
|
||||
|
||||
@@ -22,7 +22,7 @@ class SourceFactory {
|
||||
static boost::shared_ptr<Source> create (Session&, const XMLNode& node);
|
||||
|
||||
// MIDI sources will have to be hacked in here somehow
|
||||
static boost::shared_ptr<Source> createReadable (Session&, std::string idstr, AudioFileSource::Flag flags, bool announce = true);
|
||||
static boost::shared_ptr<Source> createReadable (Session&, std::string path, int chn, AudioFileSource::Flag flags, bool announce = true);
|
||||
static boost::shared_ptr<Source> createWritable (Session&, std::string name, bool destructive, nframes_t rate, bool announce = true);
|
||||
|
||||
private:
|
||||
|
||||
@@ -63,20 +63,22 @@ uint64_t AudioFileSource::header_position_offset = 0;
|
||||
/* XXX maybe this too */
|
||||
char AudioFileSource::bwf_serial_number[13] = "000000000000";
|
||||
|
||||
AudioFileSource::AudioFileSource (Session& s, string idstr, Flag flags)
|
||||
: AudioSource (s, idstr), _flags (flags)
|
||||
AudioFileSource::AudioFileSource (Session& s, string path, Flag flags)
|
||||
: AudioSource (s, path), _flags (flags),
|
||||
channel (0)
|
||||
{
|
||||
/* constructor used for existing external to session files. file must exist already */
|
||||
_is_embedded = AudioFileSource::determine_embeddedness (idstr);
|
||||
_is_embedded = AudioFileSource::determine_embeddedness (path);
|
||||
|
||||
if (init (idstr, true)) {
|
||||
if (init (path, true)) {
|
||||
throw failed_constructor ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AudioFileSource::AudioFileSource (Session& s, std::string path, Flag flags, SampleFormat samp_format, HeaderFormat hdr_format)
|
||||
: AudioSource (s, path), _flags (flags)
|
||||
: AudioSource (s, path), _flags (flags),
|
||||
channel (0)
|
||||
{
|
||||
/* constructor used for new internal-to-session files. file cannot exist */
|
||||
_is_embedded = false;
|
||||
@@ -88,6 +90,7 @@ AudioFileSource::AudioFileSource (Session& s, std::string path, Flag flags, Samp
|
||||
|
||||
AudioFileSource::AudioFileSource (Session& s, const XMLNode& node)
|
||||
: AudioSource (s, node), _flags (Flag (Writable|CanRename))
|
||||
/* channel is set in set_state() */
|
||||
{
|
||||
/* constructor used for existing internal-to-session files. file must exist */
|
||||
|
||||
@@ -195,7 +198,10 @@ XMLNode&
|
||||
AudioFileSource::get_state ()
|
||||
{
|
||||
XMLNode& root (AudioSource::get_state());
|
||||
root.add_property ("flags", enum_2_string (_flags));
|
||||
char buf[32];
|
||||
root.add_property (X_("flags"), enum_2_string (_flags));
|
||||
snprintf (buf, sizeof (buf), "%d", channel);
|
||||
root.add_property (X_("channel"), buf);
|
||||
return root;
|
||||
}
|
||||
|
||||
@@ -209,15 +215,18 @@ AudioFileSource::set_state (const XMLNode& node)
|
||||
}
|
||||
|
||||
if ((prop = node.property (X_("flags"))) != 0) {
|
||||
|
||||
_flags = Flag (string_2_enum (prop->value(), _flags));
|
||||
|
||||
} else {
|
||||
|
||||
_flags = Flag (0);
|
||||
|
||||
}
|
||||
|
||||
if ((prop = node.property (X_("channel"))) != 0) {
|
||||
channel = atoi (prop->value());
|
||||
} else {
|
||||
channel = 0;
|
||||
}
|
||||
|
||||
if ((prop = node.property (X_("name"))) != 0) {
|
||||
_is_embedded = AudioFileSource::determine_embeddedness (prop->value());
|
||||
} else {
|
||||
@@ -527,7 +536,7 @@ bool
|
||||
AudioFileSource::is_empty (Session& s, string path)
|
||||
{
|
||||
bool ret = false;
|
||||
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (s, path, NoPeakFile, false));
|
||||
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (s, path, 0, NoPeakFile, false));
|
||||
|
||||
if (afs) {
|
||||
ret = (afs->length() == 0);
|
||||
@@ -568,3 +577,9 @@ AudioFileSource::safe_file_extension(string file)
|
||||
#endif // HAVE_COREAUDIO
|
||||
file.rfind(".voc") == string::npos);
|
||||
}
|
||||
|
||||
void
|
||||
AudioFileSource::mark_immutable ()
|
||||
{
|
||||
_flags = Flag (_flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy|CanRename));
|
||||
}
|
||||
|
||||
@@ -34,33 +34,22 @@ using namespace PBD;
|
||||
CoreAudioSource::CoreAudioSource (Session& s, const XMLNode& node)
|
||||
: AudioFileSource (s, node)
|
||||
{
|
||||
init (_name);
|
||||
init ();
|
||||
}
|
||||
|
||||
CoreAudioSource::CoreAudioSource (Session& s, const string& idstr, Flag flags)
|
||||
: AudioFileSource(s, idstr, flags)
|
||||
CoreAudioSource::CoreAudioSource (Session& s, const string& path, int chn, Flag flags)
|
||||
: AudioFileSource(s, path, flags),
|
||||
{
|
||||
init (idstr);
|
||||
channel = chn;
|
||||
init ();
|
||||
}
|
||||
|
||||
void
|
||||
CoreAudioSource::init (string idstr)
|
||||
CoreAudioSource::init ()
|
||||
{
|
||||
string::size_type pos;
|
||||
|
||||
tmpbuf = 0;
|
||||
tmpbufsize = 0;
|
||||
|
||||
_name = idstr;
|
||||
|
||||
if ((pos = idstr.find_last_of (':')) == string::npos) {
|
||||
channel = 0;
|
||||
_path = idstr;
|
||||
} else {
|
||||
channel = atoi (idstr.substr (pos+1).c_str());
|
||||
_path = idstr.substr (0, pos);
|
||||
}
|
||||
|
||||
cerr << "CoreAudioSource::init() " << name() << endl;
|
||||
|
||||
/* note that we temporarily truncated _id at the colon */
|
||||
|
||||
@@ -1738,6 +1738,10 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
|
||||
|
||||
track->set_control_outs (cports);
|
||||
}
|
||||
|
||||
// assert (current_thread != RT_thread)
|
||||
|
||||
track->audio_diskstream()->non_realtime_input_change();
|
||||
|
||||
track->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes));
|
||||
track->set_remote_control_id (control_id);
|
||||
|
||||
@@ -48,30 +48,34 @@ const AudioFileSource::Flag SndFileSource::default_writable_flags = AudioFileSou
|
||||
SndFileSource::SndFileSource (Session& s, const XMLNode& node)
|
||||
: AudioFileSource (s, node)
|
||||
{
|
||||
init (_name);
|
||||
init ();
|
||||
|
||||
cerr << "SndFileSource @ " << _path << " channel = " << channel << endl;
|
||||
|
||||
if (open()) {
|
||||
throw failed_constructor ();
|
||||
}
|
||||
}
|
||||
|
||||
SndFileSource::SndFileSource (Session& s, string idstr, Flag flags)
|
||||
/* files created this way are never writable or removable */
|
||||
: AudioFileSource (s, idstr, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
|
||||
SndFileSource::SndFileSource (Session& s, string path, int chn, Flag flags)
|
||||
/* files created this way are never writable or removable */
|
||||
: AudioFileSource (s, path, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
|
||||
{
|
||||
init (idstr);
|
||||
channel = chn;
|
||||
|
||||
init ();
|
||||
|
||||
if (open()) {
|
||||
throw failed_constructor ();
|
||||
}
|
||||
}
|
||||
|
||||
SndFileSource::SndFileSource (Session& s, string idstr, SampleFormat sfmt, HeaderFormat hf, nframes_t rate, Flag flags)
|
||||
: AudioFileSource (s, idstr, flags, sfmt, hf)
|
||||
SndFileSource::SndFileSource (Session& s, string path, SampleFormat sfmt, HeaderFormat hf, nframes_t rate, Flag flags)
|
||||
: AudioFileSource (s, path, flags, sfmt, hf)
|
||||
{
|
||||
int fmt = 0;
|
||||
|
||||
init (idstr);
|
||||
init ();
|
||||
|
||||
/* this constructor is used to construct new files, not open
|
||||
existing ones.
|
||||
@@ -174,9 +178,8 @@ SndFileSource::SndFileSource (Session& s, string idstr, SampleFormat sfmt, Heade
|
||||
}
|
||||
|
||||
void
|
||||
SndFileSource::init (string idstr)
|
||||
SndFileSource::init ()
|
||||
{
|
||||
string::size_type pos;
|
||||
string file;
|
||||
|
||||
// lets try to keep the object initalizations here at the top
|
||||
@@ -186,20 +189,10 @@ SndFileSource::init (string idstr)
|
||||
sf = 0;
|
||||
_broadcast_info = 0;
|
||||
|
||||
string tmp_name;
|
||||
|
||||
if ((pos = idstr.find_last_of (':')) == string::npos) {
|
||||
channel = 0;
|
||||
tmp_name = idstr;
|
||||
} else {
|
||||
channel = atoi (idstr.substr (pos+1).c_str());
|
||||
tmp_name = idstr.substr (0, pos);
|
||||
}
|
||||
|
||||
if (is_embedded()) {
|
||||
_name = tmp_name;
|
||||
_name = _path;
|
||||
} else {
|
||||
_name = Glib::path_get_basename (tmp_name);
|
||||
_name = Glib::path_get_basename (_path);
|
||||
}
|
||||
|
||||
/* although libsndfile says we don't need to set this,
|
||||
@@ -385,6 +378,7 @@ nframes_t
|
||||
SndFileSource::nondestructive_write_unlocked (Sample *data, nframes_t cnt)
|
||||
{
|
||||
if (!writable()) {
|
||||
warning << string_compose (_("attempt to write a non-writable audio file source (%1)"), _path) << endmsg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -440,6 +434,7 @@ SndFileSource::destructive_write_unlocked (Sample* data, nframes_t cnt)
|
||||
nframes_t old_file_pos;
|
||||
|
||||
if (!writable()) {
|
||||
warning << string_compose (_("attempt to write a non-writable audio file source (%1)"), _path) << endmsg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -563,6 +558,7 @@ int
|
||||
SndFileSource::flush_header ()
|
||||
{
|
||||
if (!writable() || (sf == 0)) {
|
||||
warning << string_compose (_("attempt to flush a non-writable audio file source (%1)"), _path) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
return (sf_command (sf, SFC_UPDATE_HEADER_NOW, 0, 0) != SF_TRUE);
|
||||
@@ -572,6 +568,7 @@ int
|
||||
SndFileSource::setup_broadcast_info (nframes_t when, struct tm& now, time_t tnow)
|
||||
{
|
||||
if (!writable()) {
|
||||
warning << string_compose (_("attempt to store broadcast info in a non-writable audio file source (%1)"), _path) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -97,12 +97,12 @@ SourceFactory::create (Session& s, const XMLNode& node)
|
||||
|
||||
#ifdef HAVE_COREAUDIO
|
||||
boost::shared_ptr<Source>
|
||||
SourceFactory::createReadable (Session& s, string idstr, AudioFileSource::Flag flags, bool announce)
|
||||
SourceFactory::createReadable (Session& s, string path, int chn, AudioFileSource::Flag flags, bool announce)
|
||||
{
|
||||
if (!(flags & Destructive)) {
|
||||
|
||||
try {
|
||||
boost::shared_ptr<Source> ret (new CoreAudioSource (s, idstr, flags));
|
||||
boost::shared_ptr<Source> ret (new CoreAudioSource (s, path, chn, flags));
|
||||
if (setup_peakfile (ret)) {
|
||||
return boost::shared_ptr<Source>();
|
||||
}
|
||||
@@ -113,7 +113,7 @@ SourceFactory::createReadable (Session& s, string idstr, AudioFileSource::Flag f
|
||||
}
|
||||
|
||||
catch (failed_constructor& err) {
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, idstr, flags));
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, path, chn, flags));
|
||||
if (setup_peakfile (ret)) {
|
||||
return boost::shared_ptr<Source>();
|
||||
}
|
||||
@@ -125,7 +125,7 @@ SourceFactory::createReadable (Session& s, string idstr, AudioFileSource::Flag f
|
||||
|
||||
} else {
|
||||
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, idstr, flags));
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, path, chn, flags));
|
||||
if (setup_peakfile (ret)) {
|
||||
return boost::shared_ptr<Source>();
|
||||
}
|
||||
@@ -141,9 +141,9 @@ SourceFactory::createReadable (Session& s, string idstr, AudioFileSource::Flag f
|
||||
#else
|
||||
|
||||
boost::shared_ptr<Source>
|
||||
SourceFactory::createReadable (Session& s, string idstr, AudioFileSource::Flag flags, bool announce)
|
||||
SourceFactory::createReadable (Session& s, string path, int chn, AudioFileSource::Flag flags, bool announce)
|
||||
{
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, idstr, flags));
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, path, chn, flags));
|
||||
|
||||
if (setup_peakfile (ret)) {
|
||||
return boost::shared_ptr<Source>();
|
||||
|
||||
Reference in New Issue
Block a user