mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-09 00:04:56 +01:00
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:
parent
1c61d4007a
commit
5ee3e58718
15 changed files with 130 additions and 98 deletions
|
|
@ -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"/>
|
||||||
|
|
|
||||||
|
|
@ -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" "")
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,8 @@ Editor::do_embed (vector<ustring> paths, bool split, ImportMode mode, AudioTrack
|
||||||
|
|
||||||
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;
|
||||||
vector<ustring> to_embed;
|
vector<ustring> to_embed;
|
||||||
|
|
@ -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"));
|
||||||
} else {
|
|
||||||
choices.push_back (_("Cancel"));
|
|
||||||
}
|
|
||||||
|
|
||||||
choices.push_back (_("Embed it anyway"));
|
|
||||||
|
|
||||||
Gtkmm2ext::Choice rate_choice (
|
Gtkmm2ext::Choice rate_choice (
|
||||||
string_compose (_("%1\nThis audiofile's sample rate doesn't match the session sample rate!"), path),
|
string_compose (_("%1\nThis audiofile's sample rate doesn't match the session sample rate!"), path),
|
||||||
choices, false);
|
choices, false);
|
||||||
|
|
||||||
switch (rate_choice.run()) {
|
int resx = rate_choice.run ();
|
||||||
|
|
||||||
|
switch (resx) {
|
||||||
case 0: /* stop a multi-file import */
|
case 0: /* stop a multi-file import */
|
||||||
case 1: /* don't import this one */
|
case 1: /* don't import this one */
|
||||||
return -1;
|
ret = -1;
|
||||||
|
goto out;
|
||||||
case 2: /* do it, and the rest without asking */
|
case 2: /* do it, and the rest without asking */
|
||||||
check_sample_rate = false;
|
check_sample_rate = false;
|
||||||
break;
|
break;
|
||||||
case 3: /* do it */
|
case 3: /* do it */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -2;
|
ret = -2;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
choices.push_back (_("Cancel"));
|
||||||
|
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),
|
||||||
|
choices, false);
|
||||||
|
|
||||||
|
int resx = rate_choice.run ();
|
||||||
|
|
||||||
|
switch (resx) {
|
||||||
|
case 0: /* don't import */
|
||||||
|
ret = -1;
|
||||||
|
goto out;
|
||||||
|
case 1: /* do it */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = -2;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -344,15 +366,13 @@ Editor::embed_sndfile (vector<Glib::ustring> paths, bool split, bool multiple_fi
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
|
||||||
|
|
@ -1739,6 +1739,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);
|
||||||
++control_id;
|
++control_id;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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>();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue