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:
Paul Davis 2007-01-25 17:42:19 +00:00
parent 1c61d4007a
commit 5ee3e58718
15 changed files with 130 additions and 98 deletions

View file

@ -31,7 +31,7 @@
<Option name="quieten-at-speed" value="1.000000"/> <Option name="quieten-at-speed" value="1.000000"/>
<Option name="use-vst" value="yes"/> <Option name="use-vst" value="yes"/>
<Option name="use-tranzport" value="yes"/> <Option name="use-tranzport" value="yes"/>
<Option name="destructive-xfade-msecs" value="500"/> <Option name="destructive-xfade-msecs" value="20"/>
</Config> </Config>
<extra> <extra>
<Keyboard edit-button="3" edit-modifier="4" delete-button="3" delete-modifier="1" snap-modifier="32"/> <Keyboard edit-button="3" edit-modifier="4" delete-button="3" delete-modifier="1" snap-modifier="32"/>

View file

@ -70,9 +70,9 @@
(gtk_accel_path "<Actions>/Editor/editor-paste" "<Control>v") (gtk_accel_path "<Actions>/Editor/editor-paste" "<Control>v")
(gtk_accel_path "<Actions>/Editor/scroll-tracks-down" "Page_Down") (gtk_accel_path "<Actions>/Editor/scroll-tracks-down" "Page_Down")
; (gtk_accel_path "<Actions>/Snap/snap-to-smpte-minutes" "") ; (gtk_accel_path "<Actions>/Snap/snap-to-smpte-minutes" "")
; (gtk_accel_path "<Actions>/Main/FlushWastebasket" "")
(gtk_accel_path "<Actions>/Editor/normalize-region" "n") (gtk_accel_path "<Actions>/Editor/normalize-region" "n")
(gtk_accel_path "<Actions>/Editor/nudge-forward" "KP_Add") (gtk_accel_path "<Actions>/Editor/nudge-forward" "KP_Add")
; (gtk_accel_path "<Actions>/Main/FlushWastebasket" "")
; (gtk_accel_path "<Actions>/RegionList/SortByRegionEndinFile" "") ; (gtk_accel_path "<Actions>/RegionList/SortByRegionEndinFile" "")
; (gtk_accel_path "<Actions>/Editor/ToggleMeasureVisibility" "") ; (gtk_accel_path "<Actions>/Editor/ToggleMeasureVisibility" "")
; (gtk_accel_path "<Actions>/Zoom/zoom-focus-center" "") ; (gtk_accel_path "<Actions>/Zoom/zoom-focus-center" "")
@ -99,6 +99,7 @@
; (gtk_accel_path "<Actions>/Editor/addExternalAudioAsTapeTrack" "") ; (gtk_accel_path "<Actions>/Editor/addExternalAudioAsTapeTrack" "")
; (gtk_accel_path "<Actions>/redirectmenu/paste" "") ; (gtk_accel_path "<Actions>/redirectmenu/paste" "")
; (gtk_accel_path "<Actions>/Editor/Smpte25" "") ; (gtk_accel_path "<Actions>/Editor/Smpte25" "")
; (gtk_accel_path "<Actions>/options/RegionEquivalentsOverlap" "")
; (gtk_accel_path "<Actions>/Main/MeteringFallOffRate" "") ; (gtk_accel_path "<Actions>/Main/MeteringFallOffRate" "")
; (gtk_accel_path "<Actions>/options/UseHardwareMonitoring" "") ; (gtk_accel_path "<Actions>/options/UseHardwareMonitoring" "")
; (gtk_accel_path "<Actions>/Editor/Smpte24" "") ; (gtk_accel_path "<Actions>/Editor/Smpte24" "")
@ -174,6 +175,7 @@
; (gtk_accel_path "<Actions>/options/MeterFalloffMedium" "") ; (gtk_accel_path "<Actions>/options/MeterFalloffMedium" "")
(gtk_accel_path "<Actions>/Editor/toggle-follow-playhead" "f") (gtk_accel_path "<Actions>/Editor/toggle-follow-playhead" "f")
; (gtk_accel_path "<Actions>/Main/SaveTemplate" "") ; (gtk_accel_path "<Actions>/Main/SaveTemplate" "")
(gtk_accel_path "<Actions>/Transport/TransitionToRoll" "<Control>uparrow")
; (gtk_accel_path "<Actions>/RegionList/SortByRegionStartinFile" "") ; (gtk_accel_path "<Actions>/RegionList/SortByRegionStartinFile" "")
; (gtk_accel_path "<Actions>/options/GainReduceFastTransport" "") ; (gtk_accel_path "<Actions>/options/GainReduceFastTransport" "")
; (gtk_accel_path "<Actions>/Common/ToggleInspector" "") ; (gtk_accel_path "<Actions>/Common/ToggleInspector" "")
@ -213,6 +215,7 @@
(gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-gain" "g") (gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-gain" "g")
; (gtk_accel_path "<Actions>/Snap/snap-to-frame" "") ; (gtk_accel_path "<Actions>/Snap/snap-to-frame" "")
; (gtk_accel_path "<Actions>/Editor/SnapTo" "") ; (gtk_accel_path "<Actions>/Editor/SnapTo" "")
(gtk_accel_path "<Actions>/Transport/TransitionToReverse" "<Control>downarrow")
; (gtk_accel_path "<Actions>/Editor/Crossfades" "") ; (gtk_accel_path "<Actions>/Editor/Crossfades" "")
; (gtk_accel_path "<Actions>/Editor/PullupPlus4" "") ; (gtk_accel_path "<Actions>/Editor/PullupPlus4" "")
(gtk_accel_path "<Actions>/Editor/add-location-from-playhead" "KP_Enter") (gtk_accel_path "<Actions>/Editor/add-location-from-playhead" "KP_Enter")
@ -257,8 +260,6 @@
; (gtk_accel_path "<Actions>/Main/Snapshot" "") ; (gtk_accel_path "<Actions>/Main/Snapshot" "")
; (gtk_accel_path "<Actions>/Transport/ToggleVideoSync" "") ; (gtk_accel_path "<Actions>/Transport/ToggleVideoSync" "")
(gtk_accel_path "<Actions>/Transport/ToggleRoll" "space") (gtk_accel_path "<Actions>/Transport/ToggleRoll" "space")
(gtk_accel_path "<Actions>/Transport/TransitionToRoll" "<Ctrl>uparrow")
(gtk_accel_path "<Actions>/Transport/TransitionToReverse" "<Ctrl>downarrow")
; (gtk_accel_path "<Actions>/RegionList/SortBySourceFilesystem" "") ; (gtk_accel_path "<Actions>/RegionList/SortBySourceFilesystem" "")
(gtk_accel_path "<Actions>/Common/ToggleColorManager" "<Alt>c") (gtk_accel_path "<Actions>/Common/ToggleColorManager" "<Alt>c")
; (gtk_accel_path "<Actions>/Common/About" "") ; (gtk_accel_path "<Actions>/Common/About" "")

View file

@ -737,7 +737,7 @@ AudioRegionView::create_waves ()
for (uint32_t n = 0; n < nchans; ++n) { for (uint32_t n = 0; n < nchans; ++n) {
tmp_waves.push_back (0); tmp_waves.push_back (0);
} }
for (uint32_t n = 0; n < nchans; ++n) { for (uint32_t n = 0; n < nchans; ++n) {
if (n >= audio_region()->n_channels()) { if (n >= audio_region()->n_channels()) {
@ -828,7 +828,7 @@ AudioRegionView::create_one_wave (uint32_t which, bool direct)
break; break;
} }
} }
if (n == nwaves && waves.empty()) { if (n == nwaves && waves.empty()) {
/* all waves are ready */ /* all waves are ready */
tmp_waves.resize(nwaves); tmp_waves.resize(nwaves);

View file

@ -130,6 +130,8 @@ Editor::do_embed (vector<ustring> paths, bool split, ImportMode mode, AudioTrack
vector<ustring>::iterator a; vector<ustring>::iterator a;
for (a = paths.begin(); a != paths.end(); ) { for (a = paths.begin(); a != paths.end(); ) {
cerr << "Considering embed of " << (*a) << endl;
Glib::ustring path = *a; Glib::ustring path = *a;
Glib::ustring pair_base; Glib::ustring pair_base;
@ -264,12 +266,12 @@ Editor::embed_sndfile (vector<Glib::ustring> paths, bool split, bool multiple_fi
boost::shared_ptr<AudioFileSource> source; boost::shared_ptr<AudioFileSource> source;
SourceList sources; SourceList sources;
boost::shared_ptr<AudioRegion> region; boost::shared_ptr<AudioRegion> region;
string idspec;
string linked_path; string linked_path;
SoundFileInfo finfo; SoundFileInfo finfo;
ustring region_name; ustring region_name;
uint32_t input_chan = 0; uint32_t input_chan = 0;
uint32_t output_chan = 0; uint32_t output_chan = 0;
int ret = 0;
track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH)); track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
ARDOUR_UI::instance()->flush_pending (); ARDOUR_UI::instance()->flush_pending ();
@ -301,7 +303,7 @@ Editor::embed_sndfile (vector<Glib::ustring> paths, bool split, bool multiple_fi
if (!AudioFileSource::get_soundfile_info (path, finfo, error_msg)) { if (!AudioFileSource::get_soundfile_info (path, finfo, error_msg)) {
error << string_compose(_("Editor: cannot open file \"%1\", (%2)"), selection, error_msg ) << endmsg; error << string_compose(_("Editor: cannot open file \"%1\", (%2)"), selection, error_msg ) << endmsg;
return 0; goto out;
} }
if (check_sample_rate && (finfo.samplerate != (int) session->frame_rate())) { if (check_sample_rate && (finfo.samplerate != (int) session->frame_rate())) {
@ -311,27 +313,47 @@ Editor::embed_sndfile (vector<Glib::ustring> paths, bool split, bool multiple_fi
choices.push_back (_("Cancel entire import")); choices.push_back (_("Cancel entire import"));
choices.push_back (_("Don't embed it")); choices.push_back (_("Don't embed it"));
choices.push_back (_("Embed all without questions")); choices.push_back (_("Embed all without questions"));
Gtkmm2ext::Choice rate_choice (
string_compose (_("%1\nThis audiofile's sample rate doesn't match the session sample rate!"), path),
choices, false);
int resx = rate_choice.run ();
switch (resx) {
case 0: /* stop a multi-file import */
case 1: /* don't import this one */
ret = -1;
goto out;
case 2: /* do it, and the rest without asking */
check_sample_rate = false;
break;
case 3: /* do it */
break;
default:
ret = -2;
goto out;
}
} else { } else {
choices.push_back (_("Cancel")); choices.push_back (_("Cancel"));
} choices.push_back (_("Embed it anyway"));
choices.push_back (_("Embed it anyway")); Gtkmm2ext::Choice rate_choice (
string_compose (_("%1\nThis audiofile's sample rate doesn't match the session sample rate!"), path),
Gtkmm2ext::Choice rate_choice ( choices, false);
string_compose (_("%1\nThis audiofile's sample rate doesn't match the session sample rate!"), path),
choices, false); int resx = rate_choice.run ();
switch (rate_choice.run()) { switch (resx) {
case 0: /* stop a multi-file import */ case 0: /* don't import */
case 1: /* don't import this one */ ret = -1;
return -1; goto out;
case 2: /* do it, and the rest without asking */ case 1: /* do it */
check_sample_rate = false; break;
break; default:
case 3: /* do it */ ret = -2;
break; goto out;
default: }
return -2;
} }
} }
@ -341,18 +363,16 @@ Editor::embed_sndfile (vector<Glib::ustring> paths, bool split, bool multiple_fi
/* make the proper number of channels in the region */ /* make the proper number of channels in the region */
input_chan += finfo.channels; input_chan += finfo.channels;
for (int n = 0; n < finfo.channels; ++n) for (int n = 0; n < finfo.channels; ++n)
{ {
idspec = path;
idspec += string_compose(":%1", n);
try { try {
source = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable source = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable
(*session, idspec, (*session, path, n,
(mode == ImportAsTapeTrack ? (mode == ImportAsTapeTrack ?
AudioFileSource::Destructive : AudioFileSource::Destructive :
AudioFileSource::Flag (0)))); AudioFileSource::Flag (0))));
sources.push_back(source); sources.push_back(source);
} }
@ -377,7 +397,7 @@ Editor::embed_sndfile (vector<Glib::ustring> paths, bool split, bool multiple_fi
region = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, 0, sources[0]->length(), region_name, 0, region = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, 0, sources[0]->length(), region_name, 0,
Region::Flag (Region::DefaultFlags|Region::WholeFile|Region::External))); Region::Flag (Region::DefaultFlags|Region::WholeFile|Region::External)));
if (Config->get_output_auto_connect() & AutoConnectMaster) { if (Config->get_output_auto_connect() & AutoConnectMaster) {
output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan); output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
} else { } else {
@ -388,7 +408,7 @@ Editor::embed_sndfile (vector<Glib::ustring> paths, bool split, bool multiple_fi
out: out:
track_canvas.get_window()->set_cursor (*current_canvas_cursor); track_canvas.get_window()->set_cursor (*current_canvas_cursor);
return 0; return ret;
} }
int int

View file

@ -208,7 +208,7 @@ Editor::write_region (string path, boost::shared_ptr<AudioRegion> region)
try { try {
fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (*session, path, AudioFileSource::Flag (0))); fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (*session, path, false, session->frame_rate()));
} }
catch (failed_constructor& err) { catch (failed_constructor& err) {
@ -256,6 +256,7 @@ Editor::write_region (string path, boost::shared_ptr<AudioRegion> region)
for (vector<boost::shared_ptr<AudioFileSource> >::iterator src = sources.begin(); src != sources.end(); ++src) { for (vector<boost::shared_ptr<AudioFileSource> >::iterator src = sources.begin(); src != sources.end(); ++src) {
(*src)->update_header (0, *now, tnow); (*src)->update_header (0, *now, tnow);
(*src)->mark_immutable ();
} }
return true; return true;
@ -339,7 +340,7 @@ Editor::write_audio_range (AudioPlaylist& playlist, uint32_t channels, list<Audi
path = s; path = s;
try { try {
fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (*session, path, AudioFileSource::Flag (0))); fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (*session, path, false, session->frame_rate()));
} }
catch (failed_constructor& err) { catch (failed_constructor& err) {
@ -412,8 +413,9 @@ Editor::write_audio_range (AudioPlaylist& playlist, uint32_t channels, list<Audi
time (&tnow); time (&tnow);
now = localtime (&tnow); now = localtime (&tnow);
for (uint32_t n=0; n < channels; ++n) { for (vector<boost::shared_ptr<AudioFileSource> >::iterator s = sources.begin(); s != sources.end(); ++s) {
sources[n]->update_header (0, *now, tnow); (*s)->update_header (0, *now, tnow);
(*s)->mark_immutable ();
// do we need to ref it again? // do we need to ref it again?
} }

View file

@ -197,7 +197,7 @@ SoundFileBox::play_btn_clicked ()
for (int n = 0; n < sf_info.channels; ++n) { for (int n = 0; n < sf_info.channels; ++n) {
try { try {
afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (*_session, path+":"+string_compose("%1", n), AudioFileSource::Flag (0))); afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (*_session, path, n, AudioFileSource::Flag (0)));
srclist.push_back(afs); srclist.push_back(afs);
} catch (failed_constructor& err) { } catch (failed_constructor& err) {

View file

@ -101,6 +101,10 @@ class AudioFileSource : public AudioSource {
bool destructive() const { return (_flags & Destructive); } bool destructive() const { return (_flags & Destructive); }
virtual bool set_destructive (bool yn) { return false; } 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 /* this should really be protected, but C++ is getting stricter
and creating slots from protected member functions is starting and creating slots from protected member functions is starting
to cause issues. to cause issues.
@ -125,12 +129,12 @@ class AudioFileSource : public AudioSource {
int init (string idstr, bool must_exist); int init (string idstr, bool must_exist);
uint16_t channel;
string _path; string _path;
Flag _flags; Flag _flags;
string _take_id; string _take_id;
int64_t timeline_position; int64_t timeline_position;
bool file_is_new; bool file_is_new;
uint16_t channel;
bool _is_embedded; bool _is_embedded;
static bool determine_embeddedness(string path); static bool determine_embeddedness(string path);

View file

@ -29,7 +29,7 @@ namespace ARDOUR {
class CoreAudioSource : public AudioFileSource { class CoreAudioSource : public AudioFileSource {
public: public:
CoreAudioSource (ARDOUR::Session&, const XMLNode&); CoreAudioSource (ARDOUR::Session&, const XMLNode&);
CoreAudioSource (ARDOUR::Session&, const string& path_plus_channel, Flag); CoreAudioSource (ARDOUR::Session&, const string& path, int chn, Flag);
~CoreAudioSource (); ~CoreAudioSource ();
float sample_rate() const; float sample_rate() const;

View file

@ -31,7 +31,7 @@ class SndFileSource : public AudioFileSource {
public: public:
/* constructor to be called for existing external-to-session files */ /* 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 */ /* constructor to be called for new in-session files */
@ -78,7 +78,7 @@ class SndFileSource : public AudioFileSource {
mutable float *interleave_buf; mutable float *interleave_buf;
mutable nframes_t interleave_bufsize; mutable nframes_t interleave_bufsize;
void init (string str); void init ();
int open(); int open();
void close(); void close();
int setup_broadcast_info (nframes_t when, struct tm&, time_t); int setup_broadcast_info (nframes_t when, struct tm&, time_t);

View file

@ -22,7 +22,7 @@ class SourceFactory {
static boost::shared_ptr<Source> create (Session&, const XMLNode& node); static boost::shared_ptr<Source> create (Session&, const XMLNode& node);
// MIDI sources will have to be hacked in here somehow // 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); static boost::shared_ptr<Source> createWritable (Session&, std::string name, bool destructive, nframes_t rate, bool announce = true);
private: private:

View file

@ -63,20 +63,22 @@ uint64_t AudioFileSource::header_position_offset = 0;
/* XXX maybe this too */ /* XXX maybe this too */
char AudioFileSource::bwf_serial_number[13] = "000000000000"; char AudioFileSource::bwf_serial_number[13] = "000000000000";
AudioFileSource::AudioFileSource (Session& s, string idstr, Flag flags) AudioFileSource::AudioFileSource (Session& s, string path, Flag flags)
: AudioSource (s, idstr), _flags (flags) : AudioSource (s, path), _flags (flags),
channel (0)
{ {
/* constructor used for existing external to session files. file must exist already */ /* 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 (); throw failed_constructor ();
} }
} }
AudioFileSource::AudioFileSource (Session& s, std::string path, Flag flags, SampleFormat samp_format, HeaderFormat hdr_format) 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 */ /* constructor used for new internal-to-session files. file cannot exist */
_is_embedded = false; _is_embedded = false;
@ -88,6 +90,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)
: AudioSource (s, node), _flags (Flag (Writable|CanRename)) : AudioSource (s, node), _flags (Flag (Writable|CanRename))
/* channel is set in set_state() */
{ {
/* constructor used for existing internal-to-session files. file must exist */ /* constructor used for existing internal-to-session files. file must exist */
@ -195,7 +198,10 @@ XMLNode&
AudioFileSource::get_state () AudioFileSource::get_state ()
{ {
XMLNode& root (AudioSource::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; return root;
} }
@ -209,15 +215,18 @@ AudioFileSource::set_state (const XMLNode& node)
} }
if ((prop = node.property (X_("flags"))) != 0) { if ((prop = node.property (X_("flags"))) != 0) {
_flags = Flag (string_2_enum (prop->value(), _flags)); _flags = Flag (string_2_enum (prop->value(), _flags));
} else { } else {
_flags = Flag (0); _flags = Flag (0);
} }
if ((prop = node.property (X_("channel"))) != 0) {
channel = atoi (prop->value());
} else {
channel = 0;
}
if ((prop = node.property (X_("name"))) != 0) { if ((prop = node.property (X_("name"))) != 0) {
_is_embedded = AudioFileSource::determine_embeddedness (prop->value()); _is_embedded = AudioFileSource::determine_embeddedness (prop->value());
} else { } else {
@ -527,7 +536,7 @@ bool
AudioFileSource::is_empty (Session& s, string path) AudioFileSource::is_empty (Session& s, string path)
{ {
bool ret = false; 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) { if (afs) {
ret = (afs->length() == 0); ret = (afs->length() == 0);
@ -568,3 +577,9 @@ AudioFileSource::safe_file_extension(string file)
#endif // HAVE_COREAUDIO #endif // HAVE_COREAUDIO
file.rfind(".voc") == string::npos); file.rfind(".voc") == string::npos);
} }
void
AudioFileSource::mark_immutable ()
{
_flags = Flag (_flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy|CanRename));
}

View file

@ -34,33 +34,22 @@ using namespace PBD;
CoreAudioSource::CoreAudioSource (Session& s, const XMLNode& node) CoreAudioSource::CoreAudioSource (Session& s, const XMLNode& node)
: AudioFileSource (s, node) : AudioFileSource (s, node)
{ {
init (_name); init ();
} }
CoreAudioSource::CoreAudioSource (Session& s, const string& idstr, Flag flags) CoreAudioSource::CoreAudioSource (Session& s, const string& path, int chn, Flag flags)
: AudioFileSource(s, idstr, flags) : AudioFileSource(s, path, flags),
{ {
init (idstr); channel = chn;
init ();
} }
void void
CoreAudioSource::init (string idstr) CoreAudioSource::init ()
{ {
string::size_type pos;
tmpbuf = 0; tmpbuf = 0;
tmpbufsize = 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; cerr << "CoreAudioSource::init() " << name() << endl;
/* note that we temporarily truncated _id at the colon */ /* note that we temporarily truncated _id at the colon */

View file

@ -1738,6 +1738,10 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
track->set_control_outs (cports); 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->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes));
track->set_remote_control_id (control_id); track->set_remote_control_id (control_id);

View file

@ -48,30 +48,34 @@ const AudioFileSource::Flag SndFileSource::default_writable_flags = AudioFileSou
SndFileSource::SndFileSource (Session& s, const XMLNode& node) SndFileSource::SndFileSource (Session& s, const XMLNode& node)
: AudioFileSource (s, node) : AudioFileSource (s, node)
{ {
init (_name); init ();
cerr << "SndFileSource @ " << _path << " channel = " << channel << endl;
if (open()) { if (open()) {
throw failed_constructor (); throw failed_constructor ();
} }
} }
SndFileSource::SndFileSource (Session& s, string idstr, Flag flags) SndFileSource::SndFileSource (Session& s, string path, int chn, Flag flags)
/* files created this way are never writable or removable */ /* files created this way are never writable or removable */
: AudioFileSource (s, idstr, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy))) : AudioFileSource (s, path, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
{ {
init (idstr); channel = chn;
init ();
if (open()) { if (open()) {
throw failed_constructor (); throw failed_constructor ();
} }
} }
SndFileSource::SndFileSource (Session& s, string idstr, SampleFormat sfmt, HeaderFormat hf, nframes_t rate, Flag flags) SndFileSource::SndFileSource (Session& s, string path, SampleFormat sfmt, HeaderFormat hf, nframes_t rate, Flag flags)
: AudioFileSource (s, idstr, flags, sfmt, hf) : AudioFileSource (s, path, flags, sfmt, hf)
{ {
int fmt = 0; int fmt = 0;
init (idstr); init ();
/* this constructor is used to construct new files, not open /* this constructor is used to construct new files, not open
existing ones. existing ones.
@ -174,9 +178,8 @@ SndFileSource::SndFileSource (Session& s, string idstr, SampleFormat sfmt, Heade
} }
void void
SndFileSource::init (string idstr) SndFileSource::init ()
{ {
string::size_type pos;
string file; string file;
// lets try to keep the object initalizations here at the top // lets try to keep the object initalizations here at the top
@ -186,20 +189,10 @@ SndFileSource::init (string idstr)
sf = 0; sf = 0;
_broadcast_info = 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()) { if (is_embedded()) {
_name = tmp_name; _name = _path;
} else { } else {
_name = Glib::path_get_basename (tmp_name); _name = Glib::path_get_basename (_path);
} }
/* although libsndfile says we don't need to set this, /* 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) SndFileSource::nondestructive_write_unlocked (Sample *data, nframes_t cnt)
{ {
if (!writable()) { if (!writable()) {
warning << string_compose (_("attempt to write a non-writable audio file source (%1)"), _path) << endmsg;
return 0; return 0;
} }
@ -440,6 +434,7 @@ SndFileSource::destructive_write_unlocked (Sample* data, nframes_t cnt)
nframes_t old_file_pos; nframes_t old_file_pos;
if (!writable()) { if (!writable()) {
warning << string_compose (_("attempt to write a non-writable audio file source (%1)"), _path) << endmsg;
return 0; return 0;
} }
@ -563,6 +558,7 @@ int
SndFileSource::flush_header () SndFileSource::flush_header ()
{ {
if (!writable() || (sf == 0)) { if (!writable() || (sf == 0)) {
warning << string_compose (_("attempt to flush a non-writable audio file source (%1)"), _path) << endmsg;
return -1; return -1;
} }
return (sf_command (sf, SFC_UPDATE_HEADER_NOW, 0, 0) != SF_TRUE); 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) SndFileSource::setup_broadcast_info (nframes_t when, struct tm& now, time_t tnow)
{ {
if (!writable()) { if (!writable()) {
warning << string_compose (_("attempt to store broadcast info in a non-writable audio file source (%1)"), _path) << endmsg;
return -1; return -1;
} }

View file

@ -97,12 +97,12 @@ SourceFactory::create (Session& s, const XMLNode& node)
#ifdef HAVE_COREAUDIO #ifdef HAVE_COREAUDIO
boost::shared_ptr<Source> 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)) { if (!(flags & Destructive)) {
try { 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)) { if (setup_peakfile (ret)) {
return boost::shared_ptr<Source>(); return boost::shared_ptr<Source>();
} }
@ -113,7 +113,7 @@ SourceFactory::createReadable (Session& s, string idstr, AudioFileSource::Flag f
} }
catch (failed_constructor& err) { 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)) { if (setup_peakfile (ret)) {
return boost::shared_ptr<Source>(); return boost::shared_ptr<Source>();
} }
@ -125,7 +125,7 @@ SourceFactory::createReadable (Session& s, string idstr, AudioFileSource::Flag f
} else { } 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)) { if (setup_peakfile (ret)) {
return boost::shared_ptr<Source>(); return boost::shared_ptr<Source>();
} }
@ -141,9 +141,9 @@ SourceFactory::createReadable (Session& s, string idstr, AudioFileSource::Flag f
#else #else
boost::shared_ptr<Source> 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)) { if (setup_peakfile (ret)) {
return boost::shared_ptr<Source>(); return boost::shared_ptr<Source>();