summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2009-02-17 02:11:49 +0000
committerDavid Robillard <d@drobilla.net>2009-02-17 02:11:49 +0000
commit022818b4a796f52c0a91eea42e65aec0bc7bed43 (patch)
treef82bde33d44c7b3e16af7e837536665e17fe0189 /libs
parent4565b73a3993b0cb5ccb9170e276180f2b5c1372 (diff)
Fix the horrible mess that was anything related to sources and paths.
Most significant changes: - Factor out FileSource from AudioFileSource, use for SMFSource too - Explicitly pass embedded rather than mysterious name mangling or whatever - Destroy a ton of duplicated or very-nearly-duplicated code - Clean up and document all that weird source stuff in session.cc git-svn-id: svn://localhost/ardour2/branches/3.0@4609 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/SConscript2
-rw-r--r--libs/ardour/ardour/audiofilesource.h87
-rw-r--r--libs/ardour/ardour/audiosource.h6
-rw-r--r--libs/ardour/ardour/file_source.h83
-rw-r--r--libs/ardour/ardour/midi_source.h10
-rw-r--r--libs/ardour/ardour/route.h117
-rw-r--r--libs/ardour/ardour/session.h116
-rw-r--r--libs/ardour/ardour/silentfilesource.h27
-rw-r--r--libs/ardour/ardour/smf_source.h72
-rw-r--r--libs/ardour/ardour/sndfilesource.h18
-rw-r--r--libs/ardour/ardour/source.h20
-rw-r--r--libs/ardour/ardour/source_factory.h6
-rw-r--r--libs/ardour/audio_diskstream.cc21
-rw-r--r--libs/ardour/audio_library.cc1
-rw-r--r--libs/ardour/audiofilesource.cc417
-rw-r--r--libs/ardour/audiosource.cc12
-rw-r--r--libs/ardour/configuration.cc2
-rw-r--r--libs/ardour/file_source.cc419
-rw-r--r--libs/ardour/filter.cc4
-rw-r--r--libs/ardour/import.cc11
-rw-r--r--libs/ardour/midi_source.cc15
-rw-r--r--libs/ardour/session.cc283
-rw-r--r--libs/ardour/session_state.cc34
-rw-r--r--libs/ardour/silentfilesource.cc39
-rw-r--r--libs/ardour/smf_source.cc299
-rw-r--r--libs/ardour/sndfilesource.cc33
-rw-r--r--libs/ardour/source.cc46
-rw-r--r--libs/ardour/source_factory.cc18
-rw-r--r--libs/evoral/evoral/SMF.hpp4
-rw-r--r--libs/evoral/src/SMF.cpp10
30 files changed, 966 insertions, 1266 deletions
diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript
index 83b7d659b5..d30c276840 100644
--- a/libs/ardour/SConscript
+++ b/libs/ardour/SConscript
@@ -86,6 +86,7 @@ export_status.cc
export_timespan.cc
export_utilities.cc
filename_extensions.cc
+file_source.cc
filesystem_paths.cc
filter.cc
find_session.cc
@@ -152,7 +153,6 @@ session_state_utils.cc
session_time.cc
session_transport.cc
session_utils.cc
-silentfilesource.cc
smf_source.cc
sndfile_helpers.cc
sndfileimportable.cc
diff --git a/libs/ardour/ardour/audiofilesource.h b/libs/ardour/ardour/audiofilesource.h
index 249651c3cf..2b59de63ca 100644
--- a/libs/ardour/ardour/audiofilesource.h
+++ b/libs/ardour/ardour/audiofilesource.h
@@ -21,18 +21,12 @@
#define __ardour_audiofilesource_h__
#include <exception>
-
#include <time.h>
-
#include <ardour/audiosource.h>
+#include <ardour/file_source.h>
namespace ARDOUR {
-class non_existent_source : public std::exception {
- public:
- virtual const char *what() const throw() { return "audio file does not exist"; }
-};
-
struct SoundFileInfo {
float samplerate;
uint16_t channels;
@@ -41,107 +35,78 @@ struct SoundFileInfo {
int64_t timecode;
};
-class AudioFileSource : public AudioSource {
- public:
+class AudioFileSource : public AudioSource, public FileSource {
+public:
virtual ~AudioFileSource ();
bool set_name (const std::string& newname) {
return (set_source_name(newname, destructive()) == 0);
}
- int set_source_name (Glib::ustring newname, bool destructive);
- Glib::ustring path() const { return _path; }
Glib::ustring peak_path (Glib::ustring audio_path);
Glib::ustring find_broken_peakfile (Glib::ustring missing_peak_path,
Glib::ustring audio_path);
- uint16_t channel() const { return _channel; }
-
static void set_peak_dir (Glib::ustring dir) { peak_dir = dir; }
static bool get_soundfile_info (Glib::ustring path, SoundFileInfo& _info, std::string& error);
- static bool safe_file_extension (Glib::ustring path);
-
- void set_allow_remove_if_empty (bool yn);
- void mark_for_remove();
+ bool safe_file_extension (const Glib::ustring& path) const {
+ return safe_audio_file_extension(path);
+ }
/* this block of methods do nothing for regular file sources, but are significant
for files used in destructive recording.
*/
virtual nframes_t last_capture_start_frame() const { return 0; }
- virtual void mark_capture_start (nframes_t) {}
- virtual void mark_capture_end () {}
- virtual void clear_capture_marks() {}
- virtual bool one_of_several_channels () const { return false; }
+ virtual void mark_capture_start (nframes_t) {}
+ virtual void mark_capture_end () {}
+ virtual void clear_capture_marks() {}
+ virtual bool one_of_several_channels () const { return false; }
virtual int update_header (nframes_t when, struct tm&, time_t) = 0;
virtual int flush_header () = 0;
- int move_to_trash (const Glib::ustring& trash_dir_name);
-
- static bool is_empty (Session&, Glib::ustring path);
void mark_streaming_write_completed ();
- void mark_take (Glib::ustring);
- Glib::ustring take_id() const { return _take_id; }
-
- bool is_embedded() const { return _is_embedded; }
-
- static void set_bwf_serial_number (int);
-
- static void set_search_path (Glib::ustring string);
- static void set_header_position_offset (nframes_t offset );
-
int setup_peakfile ();
XMLNode& get_state ();
int set_state (const XMLNode&);
- bool destructive() const { return (_flags & Destructive); }
- virtual bool set_destructive (bool yn) { return false; }
- bool can_truncate_peaks() const { return !destructive(); }
- bool can_be_analysed() const { return _length > 0; }
-
- void mark_immutable ();
+ bool can_truncate_peaks() const { return !destructive(); }
+ bool can_be_analysed() const { return _length > 0; }
+ static bool safe_audio_file_extension (const Glib::ustring& path);
+
+ static bool is_empty (Session&, Glib::ustring path);
+
+ static void set_bwf_serial_number (int);
+ static void set_header_position_offset (nframes_t offset );
+
static sigc::signal<void> HeaderPositionOffsetChanged;
- protected:
-
+protected:
/** Constructor to be called for existing external-to-session files */
- AudioFileSource (Session&, Glib::ustring path, Source::Flag flags);
+ AudioFileSource (Session&, const Glib::ustring& path, bool embedded, Source::Flag flags);
/** Constructor to be called for new in-session files */
- AudioFileSource (Session&, Glib::ustring path, Source::Flag flags,
+ AudioFileSource (Session&, const Glib::ustring& path, bool embedded, Source::Flag flags,
SampleFormat samp_format, HeaderFormat hdr_format);
/** Constructor to be called for existing in-session files */
- AudioFileSource (Session&, const XMLNode&, bool must_exit = true);
+ AudioFileSource (Session&, const XMLNode&, bool must_exist = true);
- int init (Glib::ustring idstr, bool must_exist);
-
- static bool determine_embeddedness (Glib::ustring path);
+ int init (const Glib::ustring& idstr, bool must_exist);
- virtual void set_timeline_position (int64_t pos);
virtual void set_header_timeline_position () = 0;
virtual void handle_header_position_change () {}
-
- bool find (Glib::ustring& path, bool must_exist, bool& is_new, uint16_t& chan);
- bool removable() const;
- bool writable() const { return _flags & Writable; }
+
+ int move_dependents_to_trash();
static Sample* get_interleave_buffer (nframes_t size);
- Glib::ustring _path;
- Glib::ustring _take_id;
- int64_t _timeline_position;
- bool _file_is_new;
- uint16_t _channel;
- bool _is_embedded;
-
static Glib::ustring peak_dir;
- static Glib::ustring search_path;
static char bwf_country_code[3];
static char bwf_organization_code[4];
diff --git a/libs/ardour/ardour/audiosource.h b/libs/ardour/ardour/audiosource.h
index 43273301b1..eff21b898c 100644
--- a/libs/ardour/ardour/audiosource.h
+++ b/libs/ardour/ardour/audiosource.h
@@ -43,7 +43,7 @@ using std::vector;
namespace ARDOUR {
-class AudioSource : public Source, public boost::enable_shared_from_this<ARDOUR::AudioSource>
+class AudioSource : virtual public Source, public boost::enable_shared_from_this<ARDOUR::AudioSource>
{
public:
AudioSource (Session&, Glib::ustring name);
@@ -68,7 +68,6 @@ class AudioSource : public Source, public boost::enable_shared_from_this<ARDOUR:
virtual float sample_rate () const = 0;
- virtual void mark_for_remove() = 0;
virtual void mark_streaming_write_completed () {}
virtual bool can_truncate_peaks() const { return true; }
@@ -116,7 +115,6 @@ class AudioSource : public Source, public boost::enable_shared_from_this<ARDOUR:
static bool _build_peakfiles;
bool _peaks_built;
- mutable Glib::Mutex _lock;
mutable Glib::Mutex _peaks_ready_lock;
Glib::ustring peakpath;
Glib::ustring _captured_for;
@@ -138,8 +136,6 @@ class AudioSource : public Source, public boost::enable_shared_from_this<ARDOUR:
virtual Glib::ustring find_broken_peakfile (Glib::ustring missing_peak_path,
Glib::ustring audio_path) = 0;
- void update_length (nframes_t pos, nframes_t cnt);
-
virtual int read_peaks_with_fpp (PeakData *peaks,
nframes_t npeaks, nframes_t start, nframes_t cnt,
double samples_per_visual_peak, nframes_t fpp) const;
diff --git a/libs/ardour/ardour/file_source.h b/libs/ardour/ardour/file_source.h
new file mode 100644
index 0000000000..0d6cae9b18
--- /dev/null
+++ b/libs/ardour/ardour/file_source.h
@@ -0,0 +1,83 @@
+/*
+ Copyright (C) 2006-2009 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __ardour_filesource_h__
+#define __ardour_filesource_h__
+
+#include <exception>
+#include <time.h>
+#include <ardour/source.h>
+
+namespace ARDOUR {
+
+class MissingSource : public std::exception {
+public:
+ virtual const char *what() const throw() { return "source file does not exist"; }
+};
+
+/** A source associated with a file on disk somewhere */
+class FileSource : virtual public Source {
+public:
+ const Glib::ustring& path() const { return _path; }
+
+ virtual bool safe_file_extension (const Glib::ustring& path) const = 0;
+
+ int move_to_trash (const Glib::ustring& trash_dir_name);
+ void mark_take (const Glib::ustring& id);
+ void mark_immutable ();
+
+ const Glib::ustring& take_id () const { return _take_id; }
+ bool is_embedded () const { return _is_embedded; }
+ uint16_t channel() const { return _channel; }
+
+ int set_state (const XMLNode&);
+
+ int set_source_name (const Glib::ustring& newname, bool destructive);
+
+ static void set_search_path (DataType type, const Glib::ustring& path);
+
+protected:
+ FileSource (Session& session, DataType type,
+ const Glib::ustring& path, bool embedded,
+ Source::Flag flags = Source::Flag(0));
+
+ FileSource (Session& session, const XMLNode& node, bool must_exist);
+
+ virtual int init (const Glib::ustring& idstr, bool must_exist);
+
+ virtual int move_dependents_to_trash() { return 0; }
+
+ bool find (DataType type, const Glib::ustring& path,
+ bool must_exist, bool& is_new, uint16_t& chan);
+
+ bool removable () const;
+
+ Glib::ustring _path;
+ Glib::ustring _take_id;
+ bool _file_is_new;
+ uint16_t _channel;
+ bool _is_embedded;
+
+ static map<DataType, Glib::ustring> search_paths;
+};
+
+} // namespace ARDOUR
+
+#endif /* __ardour_filesource_h__ */
+
diff --git a/libs/ardour/ardour/midi_source.h b/libs/ardour/ardour/midi_source.h
index 0dedb3282d..0bc431a8d8 100644
--- a/libs/ardour/ardour/midi_source.h
+++ b/libs/ardour/ardour/midi_source.h
@@ -38,7 +38,7 @@ class MidiModel;
template<typename T> class MidiRingBuffer;
/** Source for MIDI data */
-class MidiSource : public Source
+class MidiSource : virtual public Source
{
public:
typedef double TimeType;
@@ -60,14 +60,10 @@ class MidiSource : public Source
virtual void append_event_unlocked_beats(const Evoral::Event<double>& ev) = 0;
virtual void append_event_unlocked_frames(const Evoral::Event<nframes_t>& ev) = 0;
- virtual void mark_for_remove() = 0;
virtual void mark_streaming_midi_write_started (NoteMode mode, nframes_t start_time);
virtual void mark_streaming_write_started ();
virtual void mark_streaming_write_completed ();
- uint64_t timeline_position () { return _timeline_position; }
- void set_timeline_position (nframes_t when);
-
virtual void session_saved();
std::string captured_for() const { return _captured_for; }
@@ -90,6 +86,8 @@ class MidiSource : public Source
virtual void destroy_model() = 0;
void set_note_mode(NoteMode mode);
+
+ void set_timeline_position (int64_t pos);
boost::shared_ptr<MidiModel> model() { return _model; }
void set_model(boost::shared_ptr<MidiModel> m) { _model = m; }
@@ -106,9 +104,7 @@ class MidiSource : public Source
nframes_t stamp_offset, nframes_t negative_stamp_offset) const = 0;
virtual nframes_t write_unlocked (MidiRingBuffer<nframes_t>& dst, nframes_t cnt) = 0;
- mutable Glib::Mutex _lock;
std::string _captured_for;
- uint64_t _timeline_position;
mutable uint32_t _read_data_count; ///< modified in read()
mutable uint32_t _write_data_count; ///< modified in write()
diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h
index 98b7fa0d64..217ce36fe9 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -70,7 +70,6 @@ class Route : public IO
ControlOut = 0x4
};
-
Route (Session&, std::string name, int input_min, int input_max, int output_min, int output_max,
Flag flags = Flag(0), DataType default_type = DataType::AUDIO);
Route (Session&, const XMLNode&, DataType default_type = DataType::AUDIO);
@@ -91,14 +90,15 @@ class Route : public IO
/* these are the core of the API of a Route. see the protected sections as well */
- virtual int roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
- nframes_t offset, int declick, bool can_record, bool rec_monitors_input);
+ virtual int roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
+ nframes_t offset, int declick, bool can_record, bool rec_monitors_input);
+
+ virtual int no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
+ nframes_t offset, bool state_changing, bool can_record, bool rec_monitors_input);
- virtual int no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
- nframes_t offset, bool state_changing, bool can_record, bool rec_monitors_input);
+ virtual int silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
+ nframes_t offset, bool can_record, bool rec_monitors_input);
- virtual int silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
- nframes_t offset, bool can_record, bool rec_monitors_input);
virtual void toggle_monitor_input ();
virtual bool can_record() { return false; }
virtual void set_record_enable (bool yn, void *src) {}
@@ -136,8 +136,8 @@ class Route : public IO
void drop_mix_group (void *);
RouteGroup *mix_group () { return _mix_group; }
- virtual void set_meter_point (MeterPoint, void *src);
- MeterPoint meter_point() const { return _meter_point; }
+ virtual void set_meter_point (MeterPoint, void *src);
+ MeterPoint meter_point() const { return _meter_point; }
/* Processors */
@@ -271,56 +271,53 @@ class Route : public IO
void curve_reallocate ();
protected:
- Flag _flags;
-
- /* tight cache-line access here is more important than sheer speed of
- access.
- */
-
- bool _muted : 1;
- bool _soloed : 1;
- bool _solo_safe : 1;
- bool _recordable : 1;
- bool _mute_affects_pre_fader : 1;
- bool _mute_affects_post_fader : 1;
- bool _mute_affects_control_outs : 1;
- bool _mute_affects_main_outs : 1;
- bool _silent : 1;
- bool _declickable : 1;
- int _pending_declick;
+ nframes_t check_initial_delay (nframes_t, nframes_t&, nframes_t&);
- MeterPoint _meter_point;
-
- gain_t solo_gain;
- gain_t mute_gain;
- gain_t desired_solo_gain;
- gain_t desired_mute_gain;
-
-
-
- nframes_t _initial_delay;
- nframes_t _roll_delay;
- ProcessorList _processors;
- Glib::RWLock _processor_lock;
- IO *_control_outs;
- Glib::Mutex _control_outs_lock;
- RouteGroup *_edit_group;
- RouteGroup *_mix_group;
- std::string _comment;
- bool _have_internal_generator;
+ void passthru (nframes_t start_frame, nframes_t end_frame,
+ nframes_t nframes, nframes_t offset, int declick, bool meter_inputs);
- boost::shared_ptr<ToggleControllable> _solo_control;
- boost::shared_ptr<ToggleControllable> _mute_control;
+ virtual void process_output_buffers (BufferSet& bufs,
+ nframes_t start_frame, nframes_t end_frame,
+ nframes_t nframes, nframes_t offset, bool with_processors, int declick,
+ bool meter);
+
+ Flag _flags;
+ int _pending_declick;
+ MeterPoint _meter_point;
+
+ gain_t solo_gain;
+ gain_t mute_gain;
+ gain_t desired_solo_gain;
+ gain_t desired_mute_gain;
- nframes_t check_initial_delay (nframes_t, nframes_t&, nframes_t&);
+ nframes_t _initial_delay;
+ nframes_t _roll_delay;
+ ProcessorList _processors;
+ Glib::RWLock _processor_lock;
+ IO *_control_outs;
+ Glib::Mutex _control_outs_lock;
+ RouteGroup *_edit_group;
+ RouteGroup *_mix_group;
+ std::string _comment;
+ bool _have_internal_generator;
- void passthru (nframes_t start_frame, nframes_t end_frame,
- nframes_t nframes, nframes_t offset, int declick, bool meter_inputs);
+ boost::shared_ptr<ToggleControllable> _solo_control;
+ boost::shared_ptr<ToggleControllable> _mute_control;
- virtual void process_output_buffers (BufferSet& bufs,
- nframes_t start_frame, nframes_t end_frame,
- nframes_t nframes, nframes_t offset, bool with_processors, int declick,
- bool meter);
+ /* tight cache-line access here is more important than sheer speed of access.
+ keep these after things that should be aligned
+ */
+
+ bool _muted : 1;
+ bool _soloed : 1;
+ bool _solo_safe : 1;
+ bool _recordable : 1;
+ bool _mute_affects_pre_fader : 1;
+ bool _mute_affects_post_fader : 1;
+ bool _mute_affects_control_outs : 1;
+ bool _mute_affects_main_outs : 1;
+ bool _silent : 1;
+ bool _declickable : 1;
protected:
@@ -348,10 +345,8 @@ class Route : public IO
static uint32_t order_key_cnt;
- struct ltstr
- {
- bool operator()(const char* s1, const char* s2) const
- {
+ struct ltstr {
+ bool operator()(const char* s1, const char* s2) const {
return strcmp(s1, s2) < 0;
}
};
@@ -365,8 +360,7 @@ class Route : public IO
int reset_processor_counts (ProcessorStreams*); /* locked */
int _reset_processor_counts (ProcessorStreams*); /* unlocked */
- /* processor I/O channels and plugin count handling */
-
+ /** processor I/O channels and plugin count handling */
struct ProcessorCount {
boost::shared_ptr<ARDOUR::Processor> processor;
ChanCount in;
@@ -376,7 +370,8 @@ class Route : public IO
};
int32_t apply_some_processor_counts (std::list<ProcessorCount>& iclist);
- bool check_some_processor_counts (std::list<ProcessorCount>& iclist, ChanCount required_inputs, ProcessorStreams* err_streams);
+ bool check_some_processor_counts (std::list<ProcessorCount>& iclist,
+ ChanCount required_inputs, ProcessorStreams* err_streams);
void set_deferred_state ();
void add_processor_from_xml (const XMLNode&);
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index ef67d0cc79..2e56e99722 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -150,9 +150,7 @@ class Session : public PBD::StatefulDestructible
SetAudioRange,
SetPlayRange,
- /* only one of each of these events
- can be queued at any one time
- */
+ /* only one of each of these events can be queued at any one time */
StopOnce,
AutoLoop
@@ -165,32 +163,33 @@ class Session : public PBD::StatefulDestructible
Clear
};
- Type type;
- Action action;
- nframes_t action_frame;
- nframes_t target_frame;
- double speed;
+ Type type;
+ Action action;
+ nframes_t action_frame;
+ nframes_t target_frame;
+ double speed;
union {
- void* ptr;
- bool yes_or_no;
- nframes_t target2_frame;
- SlaveSource slave;
- Route* route;
+ void* ptr;
+ bool yes_or_no;
+ nframes_t target2_frame;
+ SlaveSource slave;
+ Route* route;
};
- boost::shared_ptr<Region> region;
-
- list<AudioRange> audio_range;
- list<MusicRange> music_range;
+ list<AudioRange> audio_range;
+ list<MusicRange> music_range;
+
+ boost::shared_ptr<Region> region;
Event(Type t, Action a, nframes_t when, nframes_t where, double spd, bool yn = false)
- : type (t),
- action (a),
- action_frame (when),
- target_frame (where),
- speed (spd),
- yes_or_no (yn) {}
+ : type (t)
+ , action (a)
+ , action_frame (when)
+ , target_frame (where)
+ , speed (spd)
+ , yes_or_no (yn)
+ {}
void set_ptr (void* p) {
ptr = p;
@@ -275,12 +274,12 @@ class Session : public PBD::StatefulDestructible
Glib::ustring peak_path (Glib::ustring) const;
- static string change_audio_path_by_name (string oldpath, string oldname, string newname, bool destructive);
- static string change_midi_path_by_name (string oldpath, string oldname, string newname, bool destructive);
+ static string change_source_path_by_name (string oldpath, string oldname, string newname, bool destructive);
string peak_path_from_audio_path (string) const;
- string audio_path_from_name (string, uint32_t nchans, uint32_t chan, bool destructive);
- string midi_path_from_name (string);
+ string new_audio_source_name (const string&, uint32_t nchans, uint32_t chan, bool destructive);
+ string new_midi_source_name (const string&);
+ string new_source_path_from_name (DataType type, const string&);
void process (nframes_t nframes);
@@ -400,16 +399,15 @@ class Session : public PBD::StatefulDestructible
bool transport_locked () const;
int wipe ();
- //int wipe_diskstream (AudioDiskstream *);
int remove_region_from_region_list (boost::shared_ptr<Region>);
nframes_t get_maximum_extent () const;
nframes_t current_end_frame() const { return end_location->start(); }
nframes_t current_start_frame() const { return start_location->start(); }
- // "actual" sample rate of session, set by current audioengine rate, pullup/down etc.
+ /// "actual" sample rate of session, set by current audioengine rate, pullup/down etc.
nframes_t frame_rate() const { return _current_frame_rate; }
- // "native" sample rate of session, regardless of current audioengine rate, pullup/down etc
+ /// "native" sample rate of session, regardless of current audioengine rate, pullup/down etc
nframes_t nominal_frame_rate() const { return _nominal_frame_rate; }
nframes_t frames_per_hour() const { return _frames_per_hour; }
@@ -441,10 +439,10 @@ class Session : public PBD::StatefulDestructible
void remove_event (nframes_t frame, Event::Type type);
void clear_events (Event::Type type);
- nframes_t get_block_size() const { return current_block_size; }
+ nframes_t get_block_size() const { return current_block_size; }
nframes_t worst_output_latency () const { return _worst_output_latency; }
- nframes_t worst_input_latency () const { return _worst_input_latency; }
- nframes_t worst_track_latency () const { return _worst_track_latency; }
+ nframes_t worst_input_latency () const { return _worst_input_latency; }
+ nframes_t worst_track_latency () const { return _worst_track_latency; }
int save_state (std::string snapshot_name, bool pending = false);
int restore_state (std::string snapshot_name);
@@ -470,7 +468,7 @@ class Session : public PBD::StatefulDestructible
/// The instant xml file is written to the session directory
void add_instant_xml (XMLNode&, bool write_to_config = true);
- XMLNode * instant_xml (const std::string& str);
+ XMLNode* instant_xml (const std::string& str);
enum StateOfTheState {
Clean = 0x0,
@@ -495,8 +493,8 @@ class Session : public PBD::StatefulDestructible
sigc::signal<void,RouteGroup*> edit_group_added;
sigc::signal<void,RouteGroup*> mix_group_added;
- sigc::signal<void> edit_group_removed;
- sigc::signal<void> mix_group_removed;
+ sigc::signal<void> edit_group_removed;
+ sigc::signal<void> mix_group_removed;
void foreach_edit_group (sigc::slot<void,RouteGroup*> sl) {
for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); i++) {
@@ -512,11 +510,13 @@ class Session : public PBD::StatefulDestructible
/* fundamental operations. duh. */
- std::list<boost::shared_ptr<AudioTrack> > new_audio_track (int input_channels, int output_channels, TrackMode mode = Normal, uint32_t how_many = 1);
+ std::list<boost::shared_ptr<AudioTrack> > new_audio_track (
+ int input_channels, int output_channels, TrackMode mode = Normal, uint32_t how_many = 1);
+
RouteList new_audio_route (int input_channels, int output_channels, uint32_t how_many);
- std::list<boost::shared_ptr<MidiTrack> > new_midi_track (TrackMode mode = Normal, uint32_t how_many = 1);
- //boost::shared_ptr<Route> new_midi_route (uint32_t how_many = 1);
+ std::list<boost::shared_ptr<MidiTrack> > new_midi_track (
+ TrackMode mode = Normal, uint32_t how_many = 1);
void remove_route (boost::shared_ptr<Route>);
void resort_routes ();
@@ -552,8 +552,8 @@ class Session : public PBD::StatefulDestructible
void sync_time_vars();
void bbt_time (nframes_t when, BBT_Time&);
- void smpte_to_sample( SMPTE::Time& smpte, nframes_t& sample, bool use_offset, bool use_subframes ) const;
- void sample_to_smpte( nframes_t sample, SMPTE::Time& smpte, bool use_offset, bool use_subframes ) const;
+ void smpte_to_sample(SMPTE::Time& smpte, nframes_t& sample, bool use_offset, bool use_subframes) const;
+ void sample_to_smpte(nframes_t sample, SMPTE::Time& smpte, bool use_offset, bool use_subframes) const;
void smpte_time (SMPTE::Time &);
void smpte_time (nframes_t when, SMPTE::Time&);
void smpte_time_subframes (nframes_t when, SMPTE::Time&);
@@ -656,23 +656,19 @@ class Session : public PBD::StatefulDestructible
int remove_last_capture ();
- /* handlers should return -1 for "stop cleanup", 0 for
- "yes, delete this playlist" and 1 for "no, don't delete
- this playlist.
+ /** handlers should return -1 for "stop cleanup",
+ 0 for "yes, delete this playlist",
+ 1 for "no, don't delete this playlist".
*/
-
sigc::signal<int,boost::shared_ptr<ARDOUR::Playlist> > AskAboutPlaylistDeletion;
- /* handlers should return 0 for "ignore the rate mismatch"
- and !0 for "do not use this session"
+ /** handlers should return 0 for "ignore the rate mismatch",
+ !0 for "do not use this session"
*/
-
static sigc::signal<int,nframes_t, nframes_t> AskAboutSampleRateMismatch;
- /* handlers should return !0 for use pending state, 0 for
- ignore it.
+ /** handlers should return !0 for use pending state, 0 for ignore it.
*/
-
static sigc::signal<int> AskAboutPendingState;
boost::shared_ptr<AudioFileSource> create_audio_source_for_session (ARDOUR::AudioDiskstream&, uint32_t which_channel, bool destructive);
@@ -780,7 +776,7 @@ class Session : public PBD::StatefulDestructible
sigc::signal<void,boost::shared_ptr<Bundle> > BundleAdded;
sigc::signal<void,boost::shared_ptr<Bundle> > BundleRemoved;
- /* MIDI */
+ /* MIDI control */
void midi_panic(void);
int set_mtc_port (string port_tag);
@@ -917,7 +913,7 @@ class Session : public PBD::StatefulDestructible
/* clicking */
- boost::shared_ptr<IO> click_io() { return _click_io; }
+ boost::shared_ptr<IO> click_io() { return _click_io; }
/* disk, buffer loads */
@@ -1078,10 +1074,10 @@ class Session : public PBD::StatefulDestructible
bool follow_slave (nframes_t, nframes_t);
void calculate_moving_average_of_slave_delta(int dir, nframes_t this_delta);
void track_slave_state(
- float slave_speed,
+ float slave_speed,
nframes_t slave_transport_frame,
nframes_t this_delta,
- bool starting);
+ bool starting);
void follow_slave_silently(nframes_t nframes, nframes_t offset, float slave_speed);
void set_slave_source (SlaveSource);
@@ -1119,7 +1115,6 @@ class Session : public PBD::StatefulDestructible
}
int get_transport_declick_required () {
-
if (transport_sub_state & PendingDeclickIn) {
transport_sub_state &= ~PendingDeclickIn;
return 1;
@@ -1131,7 +1126,8 @@ class Session : public PBD::StatefulDestructible
}
bool maybe_stop (nframes_t limit) {
- if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
+ if ( (_transport_speed > 0.0f && _transport_frame >= limit)
+ || (_transport_speed < 0.0f && _transport_frame == 0) ) {
stop_transport ();
return true;
}
@@ -1194,7 +1190,9 @@ class Session : public PBD::StatefulDestructible
mutable gint butler_should_do_transport_work;
int butler_request_pipe[2];
- inline bool transport_work_requested() const { return g_atomic_int_get(&butler_should_do_transport_work); }
+ inline bool transport_work_requested() const {
+ return g_atomic_int_get(&butler_should_do_transport_work);
+ }
struct ButlerRequest {
enum Type {
@@ -1498,8 +1496,6 @@ class Session : public PBD::StatefulDestructible
SourceMap get_sources() { return sources; }
private:
-
-
int load_sources (const XMLNode& node);
XMLNode& get_sources_as_xml ();
diff --git a/libs/ardour/ardour/silentfilesource.h b/libs/ardour/ardour/silentfilesource.h
index cbb123139a..ad433e5f94 100644
--- a/libs/ardour/ardour/silentfilesource.h
+++ b/libs/ardour/ardour/silentfilesource.h
@@ -26,26 +26,27 @@
namespace ARDOUR {
class SilentFileSource : public AudioFileSource {
- public:
- virtual ~SilentFileSource ();
-
+public:
int update_header (nframes_t when, struct tm&, time_t) { return 0; }
int flush_header () { return 0; }
float sample_rate () const { return _sample_rate; }
- void set_length (nframes_t len);
+ void set_length (nframes_t len) { _length = len; }
bool destructive() const { return false; }
bool can_be_analysed() const { return false; }
- protected:
-
- float _sample_rate;
-
- SilentFileSource (Session&, const XMLNode&, nframes_t nframes, float sample_rate);
-
+protected:
friend class SourceFactory;
+ SilentFileSource (Session& s, const XMLNode& x, nframes_t len, float srate)
+ : Source (s, x)
+ , AudioFileSource (s, x, false)
+ , _sample_rate(srate)
+ {
+ _length = len;
+ }
+
nframes_t read_unlocked (Sample *dst, nframes_t start, nframes_t cnt) const {
memset (dst, 0, sizeof (Sample) * cnt);
return cnt;
@@ -55,11 +56,13 @@ class SilentFileSource : public AudioFileSource {
void set_header_timeline_position () {}
- int read_peaks_with_fpp (PeakData *peaks, nframes_t npeaks, nframes_t start, nframes_t cnt, double samples_per_unit, nframes_t fpp) const {
+ int read_peaks_with_fpp (PeakData *peaks, nframes_t npeaks, nframes_t start, nframes_t cnt,
+ double samples_per_unit, nframes_t fpp) const {
memset (peaks, 0, sizeof (PeakData) * npeaks);
return 0;
}
-
+
+ float _sample_rate;
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/smf_source.h b/libs/ardour/ardour/smf_source.h
index 4855cb6e31..259328c5fa 100644
--- a/libs/ardour/ardour/smf_source.h
+++ b/libs/ardour/ardour/smf_source.h
@@ -18,14 +18,14 @@
*/
-#ifndef __ardour_smf_filesource_h__
-#define __ardour_smf_filesource_h__
+#ifndef __ardour_smf_source_h__
+#define __ardour_smf_source_h__
#include <cstdio>
#include <time.h>
-
-#include <ardour/midi_source.h>
#include <evoral/SMF.hpp>
+#include <ardour/midi_source.h>
+#include <ardour/file_source.h>
namespace Evoral { template<typename T> class Event; }
@@ -34,51 +34,42 @@ namespace ARDOUR {
template<typename T> class MidiRingBuffer;
/** Standard Midi File (Type 0) Source */
-class SMFSource : public MidiSource, public Evoral::SMF {
- public:
+class SMFSource : public MidiSource, public FileSource, public Evoral::SMF {
+public:
/** Constructor for existing external-to-session files */
- SMFSource (Session& session, std::string path, Source::Flag flags = Source::Flag(0));
+ SMFSource (Session& session, const Glib::ustring& path, bool embedded,
+ Source::Flag flags = Source::Flag(0));
- /* Constructor for existing in-session files */
- SMFSource (Session& session, const XMLNode&);
+ /** Constructor for existing in-session files */
+ SMFSource (Session& session, const XMLNode&, bool must_exist = false);
virtual ~SMFSource ();
-
- bool set_name (const std::string& newname) { return (set_source_name(newname, false) == 0); }
- int set_source_name (string newname, bool destructive);
-
- static bool safe_file_extension (const Glib::ustring& path);
- Glib::ustring path() const { return _path; }
+ bool safe_file_extension (const Glib::ustring& path) const {
+ return safe_midi_file_extension(path);
+ }
- void set_allow_remove_if_empty (bool yn);
- void mark_for_remove();
+ bool set_name (const std::string& newname) { return (set_source_name(newname, false) == 0); }
- void append_event_unlocked_beats(const Evoral::Event<double>& ev);
- void append_event_unlocked_frames(const Evoral::Event<nframes_t>& ev);
-
- int move_to_trash (const string trash_dir_name);
+ void append_event_unlocked_beats (const Evoral::Event<double>& ev);
+ void append_event_unlocked_frames (const Evoral::Event<nframes_t>& ev);
void mark_streaming_midi_write_started (NoteMode mode, nframes_t start_time);
void mark_streaming_write_completed ();
- void mark_take (string);
- string take_id() const { return _take_id; }
-
- static void set_search_path (string);
- static void set_header_position_offset (nframes_t offset, bool negative);
-
XMLNode& get_state ();
int set_state (const XMLNode&);
- void load_model(bool lock=true, bool force_reload=false);
- void destroy_model();
+ void load_model (bool lock=true, bool force_reload=false);
+ void destroy_model ();
- void flush_midi();
+ void flush_midi ();
+
+ static void set_header_position_offset (nframes_t offset, bool negative);
- private:
- int init (string idstr, bool must_exist);
+ static bool safe_midi_file_extension (const Glib::ustring& path);
+private:
nframes_t read_unlocked (
MidiRingBuffer<nframes_t>& dst,
nframes_t start,
@@ -90,22 +81,13 @@ class SMFSource : public MidiSource, public Evoral::SMF {
MidiRingBuffer<nframes_t>& src,
nframes_t cnt);
- bool find (std::string path, bool must_exist, bool& is_new);
- bool removable() const;
- bool writable() const { return _flags & Writable; }
-
- void set_default_controls_interpolation();
-
- Glib::ustring _path;
- string _take_id;
- bool _allow_remove_if_empty;
- double _last_ev_time_beats;
- nframes_t _last_ev_time_frames;
+ void set_default_controls_interpolation ();
- static string _search_path;
+ double _last_ev_time_beats;
+ nframes_t _last_ev_time_frames;
};
}; /* namespace ARDOUR */
-#endif /* __ardour_smf_filesource_h__ */
+#endif /* __ardour_smf_source_h__ */
diff --git a/libs/ardour/ardour/sndfilesource.h b/libs/ardour/ardour/sndfilesource.h
index acb03391a4..5154a7a80c 100644
--- a/libs/ardour/ardour/sndfilesource.h
+++ b/libs/ardour/ardour/sndfilesource.h
@@ -29,17 +29,15 @@ namespace ARDOUR {
class SndFileSource : public AudioFileSource {
public:
- /* constructor to be called for existing external-to-session files */
+ /** Constructor to be called for existing external-to-session files */
+ SndFileSource (Session&, const Glib::ustring& path, bool embedded, int chn, Flag flags);
- SndFileSource (Session&, Glib::ustring path, int chn, Flag flags);
-
- /* constructor to be called for new in-session files */
-
- SndFileSource (Session&, Glib::ustring path, SampleFormat samp_format, HeaderFormat hdr_format, nframes_t rate,
- Flag flags = SndFileSource::default_writable_flags);
+ /* Constructor to be called for new in-session files */
+ SndFileSource (Session&, const Glib::ustring& path, bool embedded,
+ SampleFormat samp_format, HeaderFormat hdr_format, nframes_t rate,
+ Flag flags = SndFileSource::default_writable_flags);
- /* constructor to be called for existing in-session files */
-
+ /** Constructor to be called for existing in-session files */
SndFileSource (Session&, const XMLNode&);
~SndFileSource ();
@@ -77,7 +75,7 @@ class SndFileSource : public AudioFileSource {
SF_INFO _info;
BroadcastInfo *_broadcast_info;
- void init ();
+ void init_sndfile ();
int open();
int setup_broadcast_info (nframes_t when, struct tm&, time_t);
diff --git a/libs/ardour/ardour/source.h b/libs/ardour/ardour/source.h
index 137aad5fbe..7b5fc43659 100644
--- a/libs/ardour/ardour/source.h
+++ b/libs/ardour/ardour/source.h
@@ -51,7 +51,7 @@ class Source : public SessionObject, public ARDOUR::Readable
Destructive = 0x80
};
- Source (Session&, const std::string& name, DataType type, Flag flags=Flag(0));
+ Source (Session&, DataType type, const std::string& name, Flag flags=Flag(0));
Source (Session&, const XMLNode&);
virtual ~Source ();
@@ -63,11 +63,12 @@ class Source : public SessionObject, public ARDOUR::Readable
nframes_t length() const { return _length; }
- virtual Glib::ustring path() const = 0;
+ virtual const Glib::ustring& path() const = 0;
virtual nframes_t natural_position() const { return 0; }
- virtual void mark_for_remove() = 0;
+ void mark_for_remove();
+
virtual void mark_streaming_write_started () {}
virtual void mark_streaming_write_completed () = 0;
@@ -76,8 +77,10 @@ class Source : public SessionObject, public ARDOUR::Readable
XMLNode& get_state ();
int set_state (const XMLNode&);
- virtual bool destructive() const { return false; }
- virtual bool length_mutable() const { return false; }
+ bool destructive() const { return (_flags & Destructive); }
+ bool writable () const { return _flags & Writable; }
+ virtual bool set_destructive (bool yn) { return false; }
+ virtual bool length_mutable() const { return false; }
void use () { _in_use++; }
void disuse () { if (_in_use) { _in_use--; } }
@@ -103,6 +106,11 @@ class Source : public SessionObject, public ARDOUR::Readable
void update_length (nframes_t pos, nframes_t cnt);
+ int64_t timeline_position() const { return _timeline_position; }
+ virtual void set_timeline_position (int64_t pos);
+
+ void set_allow_remove_if_empty (bool yn);
+
virtual const Evoral::TimeConverter<double, nframes_t>& time_converter() const {
return Evoral::IdentityConverter<double, nframes_t>();
}
@@ -114,7 +122,9 @@ class Source : public SessionObject, public ARDOUR::Readable
Flag _flags;
time_t _timestamp;
nframes_t _length;
+ int64_t _timeline_position;
bool _analysed;
+ mutable Glib::Mutex _lock;
mutable Glib::Mutex _analysis_lock;
Glib::Mutex _playlist_lock;
diff --git a/libs/ardour/ardour/source_factory.h b/libs/ardour/ardour/source_factory.h
index 5370ad845d..69aa641657 100644
--- a/libs/ardour/ardour/source_factory.h
+++ b/libs/ardour/ardour/source_factory.h
@@ -44,10 +44,12 @@ class SourceFactory {
static boost::shared_ptr<Source> createSilent (Session&, const XMLNode& node,
nframes_t nframes, float sample_rate);
- static boost::shared_ptr<Source> createReadable (DataType type, Session&, std::string path,
+ static boost::shared_ptr<Source> createReadable (DataType type, Session&,
+ const std::string& path, bool embedded,
int chn, Source::Flag flags, bool announce = true, bool async = false);
- static boost::shared_ptr<Source> createWritable (DataType type, Session&, std::string name,
+ static boost::shared_ptr<Source> createWritable (DataType type, Session&,
+ const std::string& path, bool embedded,
bool destructive, nframes_t rate, bool announce = true, bool async = false);
static Glib::Cond* PeaksToBuild;
diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc
index 78f5ee29e2..ed8027ec59 100644
--- a/libs/ardour/audio_diskstream.cc
+++ b/libs/ardour/audio_diskstream.cc
@@ -2336,7 +2336,9 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node)
try {
fs = boost::dynamic_pointer_cast<AudioFileSource> (
- SourceFactory::createWritable (DataType::AUDIO, _session, prop->value(), false, _session.frame_rate()));
+ SourceFactory::createWritable (DataType::AUDIO, _session,
+ prop->value(), true,
+ false, _session.frame_rate()));
}
catch (failed_constructor& err) {
@@ -2370,22 +2372,25 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node)
boost::shared_ptr<AudioRegion> region;
try {
- region = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (pending_sources, 0, first_fs->length(),
- region_name_from_path (first_fs->name(), true),
- 0, AudioRegion::Flag (AudioRegion::DefaultFlags|AudioRegion::Automatic|AudioRegion::WholeFile)));
+ region = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (
+ pending_sources, 0, first_fs->length(),
+ region_name_from_path (first_fs->name(), true), 0,
+ Region::Flag (Region::DefaultFlags|Region::Automatic|Region::WholeFile)));
region->special_set_position (0);
}
catch (failed_constructor& err) {
- error << string_compose (_("%1: cannot create whole-file region from pending capture sources"),
- _name)
- << endmsg;
+ error << string_compose (
+ _("%1: cannot create whole-file region from pending capture sources"),
+ _name) << endmsg;
return -1;
}
try {
- region = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (pending_sources, 0, first_fs->length(), region_name_from_path (first_fs->name(), true)));
+ region = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (
+ pending_sources, 0, first_fs->length(),
+ region_name_from_path (first_fs->name(), true)));
}
catch (failed_constructor& err) {
diff --git a/libs/ardour/audio_library.cc b/libs/ardour/audio_library.cc
index cd473d933f..42ec537830 100644
--- a/libs/ardour/audio_library.cc
+++ b/libs/ardour/audio_library.cc
@@ -136,7 +136,6 @@ AudioLibrary::search_members_and (vector<string>& members, const vector<string>
if (*head != 0) {
lrdf_uris* ulist = lrdf_match_multi(*head);
for (uint32_t j = 0; ulist && j < ulist->count; ++j) {
-// cerr << "AND: " << Glib::filename_from_uri(ulist->items[j]) << endl;
members.push_back(Glib::filename_from_uri(ulist->items[j]));
}
lrdf_free_uris(ulist);
diff --git a/libs/ardour/audiofilesource.cc b/libs/ardour/audiofilesource.cc
index 434b64e88d..d1371ad0fb 100644
--- a/libs/ardour/audiofilesource.cc
+++ b/libs/ardour/audiofilesource.cc
@@ -63,13 +63,12 @@ using namespace PBD;
using namespace Glib;
ustring AudioFileSource::peak_dir = "";
-ustring AudioFileSource::search_path;
sigc::signal<void> AudioFileSource::HeaderPositionOffsetChanged;
uint64_t AudioFileSource::header_position_offset = 0;
/* XXX maybe this too */
-char AudioFileSource::bwf_serial_number[13] = "000000000000";
+char AudioFileSource::bwf_serial_number[13] = "000000000000";
struct SizedSampleBuffer {
nframes_t size;
@@ -86,24 +85,23 @@ struct SizedSampleBuffer {
Glib::StaticPrivate<SizedSampleBuffer> thread_interleave_buffer = GLIBMM_STATIC_PRIVATE_INIT;
-/** Constructor used for existing internal-to-session files. File must exist. */
-AudioFileSource::AudioFileSource (Session& s, ustring path, Source::Flag flags)
- : AudioSource (s, path)
- , _channel (0)
+/** Constructor used for existing internal-to-session files. */
+AudioFileSource::AudioFileSource (Session& s, const ustring& path, bool embedded, Source::Flag flags)
+ : Source (s, DataType::AUDIO, path, flags)
+ , AudioSource (s, path)
+ , FileSource (s, DataType::AUDIO, path, embedded, flags)
{
- _is_embedded = AudioFileSource::determine_embeddedness (path);
-
if (init (path, true)) {
throw failed_constructor ();
}
-
}
-/** Constructor used for new internal-to-session files. File cannot exist. */
-AudioFileSource::AudioFileSource (Session& s, ustring path, Source::Flag flags,
+/** Constructor used for new internal-to-session files. */
+AudioFileSource::AudioFileSource (Session& s, const ustring& path, bool embedded, Source::Flag flags,
SampleFormat samp_format, HeaderFormat hdr_format)
- : AudioSource (s, path)
- , _channel (0)
+ : Source (s, DataType::AUDIO, path, flags)
+ , AudioSource (s, path)
+ , FileSource (s, DataType::AUDIO, path, embedded, flags)
{
_is_embedded = false;
@@ -114,16 +112,15 @@ AudioFileSource::AudioFileSource (Session& s, ustring path, Source::Flag flags,
/** Constructor used for existing internal-to-session files. File must exist. */
AudioFileSource::AudioFileSource (Session& s, const XMLNode& node, bool must_exist)
- : AudioSource (s, node)
- /* _channel is set in set_state() or init() */
+ : Source (s, node)
+ , AudioSource (s, node)
+ , FileSource (s, node, must_exist)
{
if (set_state (node)) {
throw failed_constructor ();
}
- string foo = _name;
-
- if (init (foo, must_exist)) {
+ if (init (_name, must_exist)) {
throw failed_constructor ();
}
}
@@ -136,37 +133,13 @@ AudioFileSource::~AudioFileSource ()
}
}
-bool
-AudioFileSource::determine_embeddedness (ustring path)
-{
- return (path.find("/") == 0);
-}
-
-bool
-AudioFileSource::removable () const
-{
- return (_flags & Removable) && ((_flags & RemoveAtDestroy) || ((_flags & RemovableIfEmpty) && length() == 0));
-}
-
int
-AudioFileSource::init (ustring pathstr, bool must_exist)
+AudioFileSource::init (const ustring& pathstr, bool must_exist)
{
- _length = 0;
- _timeline_position = 0;
_peaks_built = false;
-
- if (!find (pathstr, must_exist, _file_is_new, _channel)) {
- throw non_existent_source ();
- }
-
- if (_file_is_new && must_exist) {
- return -1;
- }
-
- return 0;
+ return FileSource::init (pathstr, must_exist);
}
-
ustring
AudioFileSource::peak_path (ustring audio_path)
{
@@ -282,46 +255,22 @@ AudioFileSource::get_state ()
int
AudioFileSource::set_state (const XMLNode& node)
{
- const XMLProperty* prop;
-
- if (AudioSource::set_state (node)) {
+ if (Source::set_state (node)) {
return -1;
}
- 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 {
- _is_embedded = false;
+ if (AudioSource::set_state (node)) {
+ return -1;
}
-
- if ((prop = node.property (X_("destructive"))) != 0) {
- /* old style, from the period when we had DestructiveFileSource */
- _flags = Flag (_flags | Destructive);
+
+ if (FileSource::set_state (node)) {
+ return -1;
}
return 0;
}
void
-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) {
- return;
- }
-
- _flags = Flag (_flags | Removable | RemoveAtDestroy);
-}
-
-void
AudioFileSource::mark_streaming_write_completed ()
{
if (!writable()) {
@@ -339,262 +288,10 @@ AudioFileSource::mark_streaming_write_completed ()
}
}
-void
-AudioFileSource::mark_take (ustring id)
-{
- if (writable()) {
- _take_id = id;
- }
-}
-
int
-AudioFileSource::move_to_trash (const ustring& trash_dir_name)
+AudioFileSource::move_dependents_to_trash()
{
- if (is_embedded()) {
- cerr << "tried to move an embedded region to trash" << endl;
- return -1;
- }
-
- if (!writable()) {
- return -1;
- }
-
- /* don't move the file across filesystems, just stick it in the
- trash_dir_name directory on whichever filesystem it was already on
- */
-
- ustring newpath;
- newpath = Glib::path_get_dirname (_path);
- newpath = Glib::path_get_dirname (newpath);
-
- newpath += string("/") + trash_dir_name + "/";
- newpath += Glib::path_get_basename (_path);
-
- /* the new path already exists, try versioning */
- if (access (newpath.c_str(), F_OK) == 0) {
- char buf[PATH_MAX+1];
- int version = 1;
- ustring newpath_v;
-
- snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
- newpath_v = buf;
-
- while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
- snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
- newpath_v = buf;
- }
-
- if (version == 999) {
- PBD::error << string_compose (
- _("there are already 1000 files with names like %1; versioning discontinued"),
- newpath)
- << endmsg;
- } else {
- newpath = newpath_v;
- }
- }
-
- if (::rename (_path.c_str(), newpath.c_str()) != 0) {
- PBD::error << string_compose (
- _("cannot rename audio file source from %1 to %2 (%3)"),
- _path, newpath, strerror (errno)) << endmsg;
- return -1;
- }
-
- if (::unlink (peakpath.c_str()) != 0) {
- error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
- peakpath, _path, strerror (errno))
- << endmsg;
- /* try to back out */
- rename (newpath.c_str(), _path.c_str());
- return -1;
- }
-
- _path = newpath;
- peakpath = "";
-
- /* file can not be removed twice, since the operation is not idempotent */
- _flags = Flag (_flags & ~(RemoveAtDestroy|Removable|RemovableIfEmpty));
-
- return 0;
-}
-
-bool
-AudioFileSource::find (ustring& pathstr, bool must_exist, bool& isnew, uint16_t& chan)
-{
- ustring::size_type pos;
- bool ret = false;
-
- isnew = false;
-
- if (pathstr[0] != '/') {
-
- /* non-absolute pathname: find pathstr in search path */
-
- vector<ustring> dirs;
- int cnt;
- ustring fullpath;
- ustring keeppath;
-
- if (search_path.length() == 0) {
- error << _("FileSource: search path not set") << endmsg;
- goto out;
- }
-
- split (search_path, dirs, ':');
-
- cnt = 0;
-
- for (vector<ustring>::iterator i = dirs.begin(); i != dirs.end(); ++i) {
- fullpath = *i;
- if (fullpath[fullpath.length()-1] != '/') {
- fullpath += '/';
- }
-
- fullpath += pathstr;
-
- /* i (paul) made a nasty design error by using ':' as a special character in
- Ardour 0.99 .. this hack tries to make things sort of work.
- */
-
- if ((pos = pathstr.find_last_of (':')) != ustring::npos) {
-
- if (Glib::file_test (fullpath, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
-
- /* its a real file, no problem */
-
- keeppath = fullpath;
- ++cnt;
-
- } else {
-
- if (must_exist) {
-
- /* might be an older session using file:channel syntax. see if the version
- without the :suffix exists
- */
-
- ustring shorter = pathstr.substr (0, pos);
- fullpath = *i;
-
- if (fullpath[fullpath.length()-1] != '/') {
- fullpath += '/';
- }
-
- fullpath += shorter;
-
- if (Glib::file_test (pathstr, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
- chan = atoi (pathstr.substr (pos+1));
- pathstr = shorter;
- keeppath = fullpath;
- ++cnt;
- }
-
- } else {
-
- /* new derived file (e.g. for timefx) being created in a newer session */
-
- }
- }
-
- } else {
-
- if (Glib::file_test (fullpath, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
- keeppath = fullpath;
- ++cnt;
- }
- }
- }
-
- if (cnt > 1) {
-
- error << string_compose (_("FileSource: \"%1\" is ambigous when searching %2\n\t"), pathstr, search_path) << endmsg;
- goto out;
-
- } else if (cnt == 0) {
-
- if (must_exist) {
- error << string_compose(_("Filesource: cannot find required file (%1): while searching %2"), pathstr, search_path) << endmsg;
- goto out;
- } else {
- isnew = true;
- }
- }
-
- /* Current find() is unable to parse relative path names to yet non-existant
- sources. QuickFix(tm) */
- if (keeppath == "") {
- if (must_exist) {
- error << "AudioFileSource::find(), keeppath = \"\", but the file must exist" << endl;
- } else {
- keeppath = pathstr;
- }
- }
-
- _name = pathstr;
- _path = keeppath;
- ret = true;
-
- } else {
-
- /* external files and/or very very old style sessions include full paths */
-
- /* ugh, handle ':' situation */
-
- if ((pos = pathstr.find_last_of (':')) != ustring::npos) {
-
- ustring shorter = pathstr.substr (0, pos);
-
- if (Glib::file_test (shorter, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
- chan = atoi (pathstr.substr (pos+1));
- pathstr = shorter;
- }
- }
-
- _path = pathstr;
-
- if (is_embedded()) {
- _name = pathstr;
- } else {
- _name = pathstr.substr (pathstr.find_last_of ('/') + 1);
- }
-
- 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;
- goto out;
- }
-
- if (errno != ENOENT) {
- error << string_compose(_("Filesource: cannot check for existing file (%1): %2"), _path, strerror (errno)) << endmsg;
- goto out;
- }
-
- /* a new file */
-
- isnew = true;
- ret = true;
-
- } else {
-
- /* already exists */
-
- ret = true;
-
- }
- }
-
- out:
- return ret;
-}
-
-void
-AudioFileSource::set_search_path (ustring p)
-{
- search_path = p;
+ return ::unlink (peakpath.c_str());
}
void
@@ -604,55 +301,6 @@ AudioFileSource::set_header_position_offset (nframes_t offset)
HeaderPositionOffsetChanged ();
}
-void
-AudioFileSource::set_timeline_position (int64_t pos)
-{
- _timeline_position = pos;
-}
-
-void
-AudioFileSource::set_allow_remove_if_empty (bool yn)
-{
- if (!writable()) {
- return;
- }
-
- if (yn) {
- _flags = Flag (_flags | RemovableIfEmpty);
- } else {
- _flags = Flag (_flags & ~RemovableIfEmpty);
- }
-}
-
-int
-AudioFileSource::set_source_name (ustring newname, bool destructive)
-{
- Glib::Mutex::Lock lm (_lock);
- ustring oldpath = _path;
- ustring newpath = Session::change_audio_path_by_name (oldpath, _name, newname, destructive);
-
- if (newpath.empty()) {
- error << string_compose (_("programming error: %1"), "cannot generate a changed audio path") << endmsg;
- return -1;
- }
-
- // Test whether newpath exists, if yes notify the user but continue.
- if (access(newpath.c_str(),F_OK) == 0) {
- error << _("Programming error! Ardour tried to rename a file over another file! It's safe to continue working, but please report this to the developers.") << endmsg;
- return -1;
- }
-
- if (rename (oldpath.c_str(), newpath.c_str()) != 0) {
- error << string_compose (_("cannot rename audio file %1 to %2"), _name, newpath) << endmsg;
- return -1;
- }
-
- _name = Glib::path_get_basename (newpath);
- _path = newpath;
-
- return rename_peakfile (peak_path (_path));
-}
-
bool
AudioFileSource::is_empty (Session& s, ustring path)
{
@@ -678,7 +326,7 @@ AudioFileSource::setup_peakfile ()
}
bool
-AudioFileSource::safe_file_extension(ustring file)
+AudioFileSource::safe_audio_file_extension(const ustring& file)
{
const char* suffixes[] = {
".wav", ".WAV",
@@ -715,19 +363,6 @@ AudioFileSource::safe_file_extension(ustring file)
return false;
}
-void
-AudioFileSource::mark_immutable ()
-{
- /* destructive sources stay writable, and their other flags don't
- change.
- */
-
- if (!(_flags & Destructive)) {
- _flags = Flag (_flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy|CanRename));
- }
-}
-
-
Sample*
AudioFileSource::get_interleave_buffer (nframes_t size)
{
diff --git a/libs/ardour/audiosource.cc b/libs/ardour/audiosource.cc
index 8d710b247a..7b56d1891e 100644
--- a/libs/ardour/audiosource.cc
+++ b/libs/ardour/audiosource.cc
@@ -56,7 +56,7 @@ bool AudioSource::_build_peakfiles = false;
#define _FPP 256
AudioSource::AudioSource (Session& s, ustring name)
- : Source (s, name, DataType::AUDIO)
+ : Source (s, DataType::AUDIO, name)
{
_peaks_built = false;
_peak_byte_max = 0;
@@ -118,8 +118,6 @@ AudioSource::set_state (const XMLNode& node)
{
const XMLProperty* prop;
- Source::set_state (node);
-
if ((prop = node.property ("captured-for")) != 0) {
_captured_for = prop->value();
}
@@ -913,11 +911,3 @@ AudioSource::available_peaks (double zoom_factor) const
return (end/sizeof(PeakData)) * _FPP;
}
-void
-AudioSource::update_length (nframes_t pos, nframes_t cnt)
-{
- if (pos + cnt > _length) {
- _length = pos+cnt;
- }
-}
-
diff --git a/libs/ardour/configuration.cc b/libs/ardour/configuration.cc
index 1a78848a34..d322ab4e49 100644
--- a/libs/ardour/configuration.cc
+++ b/libs/ardour/configuration.cc
@@ -88,7 +88,7 @@ Configuration::load_state ()
/* load system configuration first */
- if ( find_file_in_search_path (ardour_search_path() + system_config_search_path(),
+ if (find_file_in_search_path (ardour_search_path() + system_config_search_path(),
"ardour_system.rc", system_rc_file) )
{
XMLTree tree;
diff --git a/libs/ardour/file_source.cc b/libs/ardour/file_source.cc
new file mode 100644
index 0000000000..ed9c80338a
--- /dev/null
+++ b/libs/ardour/file_source.cc
@@ -0,0 +1,419 @@
+/*
+ Copyright (C) 2006-2009 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <vector>
+
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <stdio.h> // for rename(), sigh
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <pbd/convert.h>
+#include <pbd/basename.h>
+#include <pbd/mountpoint.h>
+#include <pbd/stl_delete.h>
+#include <pbd/strsplit.h>
+#include <pbd/shortpath.h>
+#include <pbd/enumwriter.h>
+
+#include <glibmm/miscutils.h>
+#include <glibmm/fileutils.h>
+#include <glibmm/thread.h>
+
+#include <ardour/file_source.h>
+#include <ardour/session.h>
+#include <ardour/session_directory.h>
+#include <ardour/source_factory.h>
+#include <ardour/filename_extensions.h>
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace PBD;
+using namespace Glib;
+
+static const std::string PATH_SEP = "/"; // I don't do windows
+
+map<DataType, ustring> FileSource::search_paths;
+
+FileSource::FileSource (Session& session, DataType type,
+ const ustring& path, bool embedded, Source::Flag flag)
+ : Source(session, type, path, flag)
+ , _path(path)
+ , _file_is_new(true)
+ , _channel (0)
+ , _is_embedded(embedded)
+{
+}
+
+FileSource::FileSource (Session& session, const XMLNode& node, bool must_exist)
+ : Source(session, node)
+ , _file_is_new(false)
+{
+ _path = _name;
+ _is_embedded = (_path.find(PATH_SEP) != string::npos);
+}
+
+bool
+FileSource::removable () const
+{
+ return (_flags & Removable)
+ && ( (_flags & RemoveAtDestroy)
+ || ((_flags & RemovableIfEmpty) && length() == 0));
+}
+
+int
+FileSource::init (const ustring& pathstr, bool must_exist)
+{
+ _length = 0;
+ _timeline_position = 0;
+
+ if (!find (_type, pathstr, must_exist, _file_is_new, _channel)) {
+ throw MissingSource ();
+ }
+
+ if (_file_is_new && must_exist) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+FileSource::set_state (const XMLNode& node)
+{
+ const XMLProperty* prop;
+
+ if ((prop = node.property (X_("channel"))) != 0) {
+ _channel = atoi (prop->value());
+ } else {
+ _channel = 0;
+ }
+
+ _is_embedded = (_name.find(PATH_SEP) == string::npos);
+
+ return 0;
+}
+
+void
+FileSource::mark_take (const ustring& id)
+{
+ if (writable ()) {
+ _take_id = id;
+ }
+}
+
+int
+FileSource::move_to_trash (const ustring& trash_dir_name)
+{
+ if (is_embedded()) {
+ cerr << "tried to move an embedded region to trash" << endl;
+ return -1;
+ }
+
+ if (!writable()) {
+ return -1;
+ }
+
+ /* don't move the file across filesystems, just stick it in the
+ trash_dir_name directory on whichever filesystem it was already on
+ */
+
+ ustring newpath;
+ newpath = Glib::path_get_dirname (_path);
+ newpath = Glib::path_get_dirname (newpath);
+
+ newpath += string(PATH_SEP) + trash_dir_name + PATH_SEP;
+ newpath += Glib::path_get_basename (_path);
+
+ /* the new path already exists, try versioning */
+ if (access (newpath.c_str(), F_OK) == 0) {
+ char buf[PATH_MAX+1];
+ int version = 1;
+ ustring newpath_v;
+
+ snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
+ newpath_v = buf;
+
+ while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
+ snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
+ newpath_v = buf;
+ }
+
+ if (version == 999) {
+ PBD::error << string_compose (
+ _("there are already 1000 files with names like %1; versioning discontinued"),
+ newpath) << endmsg;
+ } else {
+ newpath = newpath_v;
+ }
+ }
+
+ if (::rename (_path.c_str(), newpath.c_str()) != 0) {
+ PBD::error << string_compose (
+ _("cannot rename file source from %1 to %2 (%3)"),
+ _path, newpath, strerror (errno)) << endmsg;
+ return -1;
+ }
+
+ if (move_dependents_to_trash() != 0) {
+ /* try to back out */
+ rename (newpath.c_str(), _path.c_str());
+ return -1;
+ }
+
+ _path = newpath;
+
+ /* file can not be removed twice, since the operation is not idempotent */
+ _flags = Flag (_flags & ~(RemoveAtDestroy|Removable|RemovableIfEmpty));
+
+ return 0;
+}
+
+/** Find the actual source file based on \a path.
+ *
+ * If the source is embedded, \a path should be a filename (no slashes).
+ * If the source is external, \a path should be a full path.
+ * In either case, _path is set to the complete absolute path of the source file.
+ * \return true iff the file was found.
+ */
+bool
+FileSource::find (DataType type, const ustring& path, bool must_exist, bool& isnew, uint16_t& chan)
+{
+ Glib::ustring search_path = search_paths[type];
+
+ ustring pathstr = path;
+ ustring::size_type pos;
+ bool ret = false;
+
+ isnew = false;
+
+ if (pathstr[0] != '/') {
+
+ /* non-absolute pathname: find pathstr in search path */
+
+ vector<ustring> dirs;
+ int cnt;
+ ustring fullpath;
+ ustring keeppath;
+
+ if (search_path.length() == 0) {
+ error << _("FileSource: search path not set") << endmsg;
+ goto out;
+ }
+
+ split (search_path, dirs, ':');
+
+ cnt = 0;
+
+ for (vector<ustring>::iterator i = dirs.begin(); i != dirs.end(); ++i) {
+ fullpath = *i;
+ if (fullpath[fullpath.length()-1] != '/') {
+ fullpath += '/';
+ }
+
+ fullpath += pathstr;
+
+ /* i (paul) made a nasty design error by using ':' as a special character in
+ Ardour 0.99 .. this hack tries to make things sort of work.
+ */
+
+ if ((pos = pathstr.find_last_of (':')) != ustring::npos) {
+
+ if (Glib::file_test (fullpath, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
+
+ /* its a real file, no problem */
+
+ keeppath = fullpath;
+ ++cnt;
+
+ } else {
+
+ if (must_exist) {
+
+ /* might be an older session using file:channel syntax. see if the version
+ without the :suffix exists
+ */
+
+ ustring shorter = pathstr.substr (0, pos);
+ fullpath = *i;
+
+ if (fullpath[fullpath.length()-1] != '/') {
+ fullpath += '/';
+ }
+
+ fullpath += shorter;
+
+ if (Glib::file_test (pathstr, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
+ chan = atoi (pathstr.substr (pos+1));
+ pathstr = shorter;
+ keeppath = fullpath;
+ ++cnt;
+ }
+
+ } else {
+
+ /* new derived file (e.g. for timefx) being created in a newer session */
+
+ }
+ }
+
+ } else {
+
+ if (Glib::file_test (fullpath, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
+ keeppath = fullpath;
+ ++cnt;
+ }
+ }
+ }
+
+ if (cnt > 1) {
+
+ error << string_compose (
+ _("FileSource: \"%1\" is ambigous when searching %2\n\t"),
+ pathstr, search_path) << endmsg;
+ goto out;
+
+ } else if (cnt == 0) {
+
+ if (must_exist) {
+ error << string_compose(
+ _("Filesource: cannot find required file (%1): while searching %2"),
+ pathstr, search_path) << endmsg;
+ goto out;
+ } else {
+ isnew = true;
+ }
+ }
+
+ /* Current find() is unable to parse relative path names to yet non-existant
+ sources. QuickFix(tm) */
+ if (keeppath == "") {
+ if (must_exist) {
+ error << "FileSource::find(), keeppath = \"\", but the file must exist" << endl;
+ } else {
+ keeppath = pathstr;
+ }
+ }
+
+ _path = keeppath;
+
+ ret = true;
+
+ } else {
+
+ /* external files and/or very very old style sessions include full paths */
+
+ /* ugh, handle ':' situation */
+
+ if ((pos = pathstr.find_last_of (':')) != ustring::npos) {
+
+ ustring shorter = pathstr.substr (0, pos);
+
+ if (Glib::file_test (shorter, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
+ chan = atoi (pathstr.substr (pos+1));
+ pathstr = shorter;
+ }
+ }
+
+ _path = 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;
+ goto out;
+ }
+
+ if (errno != ENOENT) {
+ error << string_compose(
+ _("Filesource: cannot check for existing file (%1): %2"),
+ _path, strerror (errno)) << endmsg;
+ goto out;
+ }
+
+ /* a new file */
+ isnew = true;
+ ret = true;
+
+ } else {
+
+ /* already exists */
+ ret = true;
+ }
+ }
+
+ if (_is_embedded) {
+ _name = Glib::path_get_basename (_name);
+ }
+
+out:
+ return ret;
+}
+
+int
+FileSource::set_source_name (const ustring& newname, bool destructive)
+{
+ Glib::Mutex::Lock lm (_lock);
+ ustring oldpath = _path;
+ ustring newpath = Session::change_source_path_by_name (oldpath, _name, newname, destructive);
+
+ if (newpath.empty()) {
+ error << string_compose (_("programming error: %1"), "cannot generate a changed file path") << endmsg;
+ return -1;
+ }
+
+ // Test whether newpath exists, if yes notify the user but continue.
+ if (access(newpath.c_str(),F_OK) == 0) {
+ error << _("Programming error! Ardour tried to rename a file over another file! It's safe to continue working, but please report this to the developers.") << endmsg;
+ return -1;
+ }
+
+ if (rename (oldpath.c_str(), newpath.c_str()) != 0) {
+ error << string_compose (_("cannot rename audio file %1 to %2"), _name, newpath) << endmsg;
+ return -1;
+ }
+
+ _name = Glib::path_get_basename (newpath);
+ _path = newpath;
+
+ return 0;
+}
+
+void
+FileSource::set_search_path (DataType type, const ustring& p)
+{
+ search_paths[type] = p;
+}
+
+void
+FileSource::mark_immutable ()
+{
+ /* destructive sources stay writable, and their other flags don't change. */
+ if (!(_flags & Destructive)) {
+ _flags = Flag (_flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy|CanRename));
+ }
+}
+
diff --git a/libs/ardour/filter.cc b/libs/ardour/filter.cc
index 0075555773..30393a145d 100644
--- a/libs/ardour/filter.cc
+++ b/libs/ardour/filter.cc
@@ -66,7 +66,9 @@ Filter::make_new_sources (boost::shared_ptr<Region> region, SourceList& nsrcs, s
try {
nsrcs.push_back (boost::dynamic_pointer_cast<Source> (
- SourceFactory::createWritable (region->data_type(), session, path, false, session.frame_rate())));
+ SourceFactory::createWritable (region->data_type(), session,
+ path, true,
+ false, session.frame_rate())));
}
catch (failed_constructor& err) {
diff --git a/libs/ardour/import.cc b/libs/ardour/import.cc
index f983352d58..92ecaec753 100644
--- a/libs/ardour/import.cc
+++ b/libs/ardour/import.cc
@@ -217,13 +217,10 @@ create_mono_sources_for_writing (const vector<string>& new_paths, Session& sess,
const DataType type = ((*i).rfind(".mid") != string::npos)
? DataType::MIDI : DataType::AUDIO;
- source = SourceFactory::createWritable (
- type,
- sess,
- i->c_str(),
+ source = SourceFactory::createWritable (type, sess,
+ i->c_str(), true,
false, // destructive
- samplerate
- );
+ samplerate);
}
catch (const failed_constructor& err)
{
@@ -365,7 +362,7 @@ write_midi_data_to_new_files (Evoral::SMF* source, Session::ImportStatus& status
}
} catch (...) {
- error << "Corrupt MIDI file " << source->path() << endl;
+ error << "Corrupt MIDI file " << source->file_path() << endl;
}
}
diff --git a/libs/ardour/midi_source.cc b/libs/ardour/midi_source.cc
index 03208eda02..b539d5b9d3 100644
--- a/libs/ardour/midi_source.cc
+++ b/libs/ardour/midi_source.cc
@@ -50,8 +50,7 @@ using namespace PBD;
sigc::signal<void,MidiSource *> MidiSource::MidiSourceCreated;
MidiSource::MidiSource (Session& s, string name, Source::Flag flags)
- : Source (s, name, DataType::MIDI, flags)
- , _timeline_position(0)
+ : Source (s, DataType::MIDI, name, flags)
, _read_data_count(0)
, _write_data_count(0)
, _converter(s, _timeline_position)
@@ -62,7 +61,6 @@ MidiSource::MidiSource (Session& s, string name, Source::Flag flags)
MidiSource::MidiSource (Session& s, const XMLNode& node)
: Source (s, node)
- , _timeline_position(0)
, _read_data_count(0)
, _write_data_count(0)
, _converter(s, _timeline_position)
@@ -98,8 +96,6 @@ MidiSource::set_state (const XMLNode& node)
{
const XMLProperty* prop;
- Source::set_state (node);
-
if ((prop = node.property ("captured-for")) != 0) {
_captured_for = prop->value();
}
@@ -161,10 +157,10 @@ MidiSource::file_changed (string path)
}
void
-MidiSource::set_timeline_position (nframes_t when)
+MidiSource::set_timeline_position (int64_t pos)
{
- _timeline_position = when;
- _converter.set_origin(when);
+ Source::set_timeline_position(pos);
+ _converter.set_origin(pos);
}
void
@@ -225,7 +221,8 @@ MidiSource::session_saved()
string newpath = _session.session_directory().midi_path().to_string() +"/"+ newname + ".mid";
boost::shared_ptr<MidiSource> newsrc = boost::dynamic_pointer_cast<MidiSource>(
- SourceFactory::createWritable(DataType::MIDI, _session, newpath, 1, 0, true));
+ SourceFactory::createWritable(DataType::MIDI, _session,
+ newpath, true, false, _session.frame_rate()));
newsrc->set_timeline_position(_timeline_position);
_model->write_to(newsrc);
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index a0b61f3b97..e55167ff08 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -2534,7 +2534,9 @@ Session::region_name (string& result, string base, bool newlevel)
char buf[16];
string subbase;
- assert(base.find("/") == string::npos);
+ if (base.find("/") != string::npos) {
+ base = base.substr(base.find_last_of("/") + 1);
+ }
if (base == "") {
@@ -2842,6 +2844,7 @@ Session::remove_region_from_region_list (boost::shared_ptr<Region> r)
}
/* Source Management */
+
void
Session::add_source (boost::shared_ptr<Source> source)
{
@@ -2912,7 +2915,6 @@ Session::source_by_id (const PBD::ID& id)
return source;
}
-
boost::shared_ptr<Source>
Session::source_by_path_and_channel (const Glib::ustring& path, uint16_t chn)
{
@@ -2920,26 +2922,19 @@ Session::source_by_path_and_channel (const Glib::ustring& path, uint16_t chn)
for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
cerr << "comparing " << path << " with " << i->second->name() << endl;
- boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(i->second);
+ boost::shared_ptr<AudioFileSource> afs
+ = boost::dynamic_pointer_cast<AudioFileSource>(i->second);
if (afs && afs->path() == path && chn == afs->channel()) {
return afs;
}
-
}
return boost::shared_ptr<Source>();
}
-Glib::ustring
-Session::peak_path (Glib::ustring base) const
-{
- sys::path peakfile_path(_session_dir->peak_path());
- peakfile_path /= basename_nosuffix (base) + peakfile_suffix;
- return peakfile_path.to_string();
-}
string
-Session::change_audio_path_by_name (string path, string oldname, string newname, bool destructive)
+Session::change_source_path_by_name (string path, string oldname, string newname, bool destructive)
{
string look_for;
string old_basename = PBD::basename_nosuffix (oldname);
@@ -2987,7 +2982,7 @@ Session::change_audio_path_by_name (string path, string oldname, string newname,
/* non-destructive file sources have a name of the form:
- /path/to/NAME-nnnnn(%[LR])?.wav
+ /path/to/NAME-nnnnn(%[LR])?.ext
the task here is to replace NAME with the new name.
*/
@@ -3025,7 +3020,7 @@ Session::change_audio_path_by_name (string path, string oldname, string newname,
if (postfix != string::npos) {
suffix = suffix.substr (postfix);
} else {
- error << "Logic error in Session::change_audio_path_by_name(), please report to the developers" << endl;
+ error << "Logic error in Session::change_source_path_by_name(), please report" << endl;
return "";
}
@@ -3052,8 +3047,42 @@ Session::change_audio_path_by_name (string path, string oldname, string newname,
return path;
}
+/** Return the full path (in some session directory) for a new embedded source.
+ * \a name must be a session-unique name that does not contain slashes
+ * (e.g. as returned by new_*_source_name)
+ */
string
-Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool destructive)
+Session::new_source_path_from_name (DataType type, const string& name)
+{
+ assert(name.find("/") == string::npos);
+
+ SessionDirectory sdir(get_best_session_directory_for_new_source());
+
+ sys::path p;
+ if (type == DataType::AUDIO) {
+ p = sdir.sound_path();
+ } else if (type == DataType::MIDI) {
+ p = sdir.midi_path();
+ } else {
+ error << "Unknown source type, unable to create file path" << endmsg;
+ return "";
+ }
+
+ p /= name;
+ return p.to_string();
+}
+
+Glib::ustring
+Session::peak_path (Glib::ustring base) const
+{
+ sys::path peakfile_path(_session_dir->peak_path());
+ peakfile_path /= basename_nosuffix (base) + peakfile_suffix;
+ return peakfile_path.to_string();
+}
+
+/** Return a unique name based on \a base for a new internal audio source */
+string
+Session::new_audio_source_name (const string& base, uint32_t nchan, uint32_t chan, bool destructive)
{
string spath;
uint32_t cnt;
@@ -3062,12 +3091,9 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool
string legalized;
buf[0] = '\0';
- legalized = legalize_for_path (name);
-
- /* find a "version" of the file name that doesn't exist in
- any of the possible directories.
- */
+ legalized = legalize_for_path (base);
+ // Find a "version" of the base name that doesn't exist in any of the possible directories.
for (cnt = (destructive ? ++destructive_index : 1); cnt <= limit; ++cnt) {
vector<space_and_path>::iterator i;
@@ -3080,18 +3106,24 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool
spath = sdir.sound_path().to_string();
if (destructive) {
+
if (nchan < 2) {
- snprintf (buf, sizeof(buf), "%s/T%04d-%s.wav", spath.c_str(), cnt, legalized.c_str());
+ snprintf (buf, sizeof(buf), "%s/T%04d-%s.wav",
+ spath.c_str(), cnt, legalized.c_str());
} else if (nchan == 2) {
if (chan == 0) {
- snprintf (buf, sizeof(buf), "%s/T%04d-%s%%L.wav", spath.c_str(), cnt, legalized.c_str());
+ snprintf (buf, sizeof(buf), "%s/T%04d-%s%%L.wav",
+ spath.c_str(), cnt, legalized.c_str());
} else {
- snprintf (buf, sizeof(buf), "%s/T%04d-%s%%R.wav", spath.c_str(), cnt, legalized.c_str());
+ snprintf (buf, sizeof(buf), "%s/T%04d-%s%%R.wav",
+ spath.c_str(), cnt, legalized.c_str());
}
} else if (nchan < 26) {
- snprintf (buf, sizeof(buf), "%s/T%04d-%s%%%c.wav", spath.c_str(), cnt, legalized.c_str(), 'a' + chan);
+ snprintf (buf, sizeof(buf), "%s/T%04d-%s%%%c.wav",
+ spath.c_str(), cnt, legalized.c_str(), 'a' + chan);
} else {
- snprintf (buf, sizeof(buf), "%s/T%04d-%s.wav", spath.c_str(), cnt, legalized.c_str());
+ snprintf (buf, sizeof(buf), "%s/T%04d-%s.wav",
+ spath.c_str(), cnt, legalized.c_str());
}
} else {
@@ -3125,173 +3157,42 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool
}
if (cnt > limit) {
- error << string_compose(_("There are already %1 recordings for %2, which I consider too many."), limit, name) << endmsg;
+ error << string_compose(
+ _("There are already %1 recordings for %2, which I consider too many."),
+ limit, base) << endmsg;
destroy ();
throw failed_constructor();
}
}
- /* we now have a unique name for the file, but figure out where to
- actually put it.
- */
-
- string foo = buf;
-
- SessionDirectory sdir(get_best_session_directory_for_new_source ());
-
- spath = sdir.sound_path().to_string();
- spath += '/';
-
- string::size_type pos = foo.find_last_of ('/');
-
- if (pos == string::npos) {
- spath += foo;
- } else {
- spath += foo.substr (pos + 1);
- }
-
- return spath;
+ return Glib::path_get_basename(buf);
}
+/** Create a new embedded audio source */
boost::shared_ptr<AudioFileSource>
Session::create_audio_source_for_session (AudioDiskstream& ds, uint32_t chan, bool destructive)
{
- string spath = audio_path_from_name (ds.name(), ds.n_channels().n_audio(), chan, destructive);
+ const size_t n_chans = ds.n_channels().n_audio();
+ const string name = new_audio_source_name (ds.name(), n_chans, chan, destructive);
+ const string path = new_source_path_from_name(DataType::AUDIO, name);
return boost::dynamic_pointer_cast<AudioFileSource> (
- SourceFactory::createWritable (DataType::AUDIO, *this, spath, destructive, frame_rate()));
+ SourceFactory::createWritable (
+ DataType::AUDIO, *this, path, true, destructive, frame_rate()));
}
-// FIXME: _terrible_ code duplication
+/** Return a unique name based on \a base for a new internal MIDI source */
string
-Session::change_midi_path_by_name (string path, string oldname, string newname, bool destructive)
+Session::new_midi_source_name (const string& base)
{
- string look_for;
- string old_basename = PBD::basename_nosuffix (oldname);
- string new_legalized = legalize_for_path (newname);
-
- /* note: we know (or assume) the old path is already valid */
-
- if (destructive) {
-
- /* destructive file sources have a name of the form:
-
- /path/to/Tnnnn-NAME(%[LR])?.wav
-
- the task here is to replace NAME with the new name.
- */
-
- /* find last slash */
-
- string dir;
- string prefix;
- string::size_type slash;
- string::size_type dash;
-
- if ((slash = path.find_last_of ('/')) == string::npos) {
- return "";
- }
-
- dir = path.substr (0, slash+1);
-
- /* '-' is not a legal character for the NAME part of the path */
-
- if ((dash = path.find_last_of ('-')) == string::npos) {
- return "";
- }
-
- prefix = path.substr (slash+1, dash-(slash+1));
-
- path = dir;
- path += prefix;
- path += '-';
- path += new_legalized;
- path += ".mid"; /* XXX gag me with a spoon */
-
- } else {
-
- /* non-destructive file sources have a name of the form:
-
- /path/to/NAME-nnnnn(%[LR])?.wav
-
- the task here is to replace NAME with the new name.
- */
-
- string dir;
- string suffix;
- string::size_type slash;
- string::size_type dash;
- string::size_type postfix;
-
- /* find last slash */
-
- if ((slash = path.find_last_of ('/')) == string::npos) {
- return "";
- }
-
- dir = path.substr (0, slash+1);
-
- /* '-' is not a legal character for the NAME part of the path */
-
- if ((dash = path.find_last_of ('-')) == string::npos) {
- return "";
- }
-
- suffix = path.substr (dash+1);
-
- // Suffix is now everything after the dash. Now we need to eliminate
- // the nnnnn part, which is done by either finding a '%' or a '.'
-
- postfix = suffix.find_last_of ("%");
- if (postfix == string::npos) {
- postfix = suffix.find_last_of ('.');
- }
-
- if (postfix != string::npos) {
- suffix = suffix.substr (postfix);
- } else {
- error << "Logic error in Session::change_midi_path_by_name(), please report to the developers" << endl;
- return "";
- }
-
- const uint32_t limit = 10000;
- char buf[PATH_MAX+1];
-
- for (uint32_t cnt = 1; cnt <= limit; ++cnt) {
-
- snprintf (buf, sizeof(buf), "%s%s-%u%s", dir.c_str(), newname.c_str(), cnt, suffix.c_str());
-
- if (access (buf, F_OK) != 0) {
- path = buf;
- break;
- }
- path = "";
- }
-
- if (path == "") {
- error << "FATAL ERROR! Could not find a " << endl;
- }
-
- }
-
- return path;
-}
-
-string
-Session::midi_path_from_name (string name)
-{
- string spath;
uint32_t cnt;
char buf[PATH_MAX+1];
const uint32_t limit = 10000;
string legalized;
buf[0] = '\0';
- legalized = legalize_for_path (name);
-
- /* find a "version" of the file name that doesn't exist in
- any of the possible directories.
- */
+ legalized = legalize_for_path (base);
+ // Find a "version" of the file name that doesn't exist in any of the possible directories.
for (cnt = 1; cnt <= limit; ++cnt) {
vector<space_and_path>::iterator i;
@@ -3302,12 +3203,9 @@ Session::midi_path_from_name (string name)
SessionDirectory sdir((*i).path);
sys::path p = sdir.midi_path();
-
p /= legalized;
- spath = p.to_string();
-
- snprintf (buf, sizeof(buf), "%s-%u.mid", spath.c_str(), cnt);
+ snprintf (buf, sizeof(buf), "%s-%u.mid", p.to_string().c_str(), cnt);
if (sys::exists (buf)) {
existing++;
@@ -3319,39 +3217,28 @@ Session::midi_path_from_name (string name)
}
if (cnt > limit) {
- error << string_compose(_("There are already %1 recordings for %2, which I consider too many."), limit, name) << endmsg;
+ error << string_compose(
+ _("There are already %1 recordings for %2, which I consider too many."),
+ limit, base) << endmsg;
+ destroy ();
throw failed_constructor();
}
}
- /* we now have a unique name for the file, but figure out where to
- actually put it.
- */
-
- string foo = buf;
-
- SessionDirectory sdir(get_best_session_directory_for_new_source ());
-
- spath = sdir.midi_path().to_string();
- spath += '/';
-
- string::size_type pos = foo.find_last_of ('/');
-
- if (pos == string::npos) {
- spath += foo;
- } else {
- spath += foo.substr (pos + 1);
- }
-
- return spath;
+ return Glib::path_get_basename(buf);
}
+
+/** Create a new embedded MIDI source */
boost::shared_ptr<MidiSource>
Session::create_midi_source_for_session (MidiDiskstream& ds)
{
- string mpath = midi_path_from_name (ds.name());
+ const string name = new_midi_source_name (ds.name());
+ const string path = new_source_path_from_name (DataType::MIDI, name);
- return boost::dynamic_pointer_cast<SMFSource> (SourceFactory::createWritable (DataType::MIDI, *this, mpath, false, frame_rate()));
+ return boost::dynamic_pointer_cast<SMFSource> (
+ SourceFactory::createWritable (
+ DataType::MIDI, *this, path, true, false, frame_rate()));
}
@@ -4130,7 +4017,7 @@ Session::write_one_track (AudioTrack& track, nframes_t start, nframes_t end,
try {
fsource = boost::dynamic_pointer_cast<AudioFileSource> (
- SourceFactory::createWritable (DataType::AUDIO, *this, buf, false, frame_rate()));
+ SourceFactory::createWritable (DataType::AUDIO, *this, buf, true, false, frame_rate()));
}
catch (failed_constructor& err) {
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index ce6878b881..3f9a481340 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -414,12 +414,7 @@ Session::setup_raid_path (string path)
SearchPath sound_search_path;
SearchPath midi_search_path;
- for (
- SearchPath::const_iterator i = search_path.begin();
- i != search_path.end();
- ++i
- )
- {
+ for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
sp.path = (*i).to_string ();
sp.blocks = 0; // not needed
session_dirs.push_back (sp);
@@ -430,14 +425,11 @@ Session::setup_raid_path (string path)
midi_search_path += sdir.midi_path ();
}
- // set the AudioFileSource and SMFSource search path
-
- AudioFileSource::set_search_path (sound_search_path.to_string ());
- SMFSource::set_search_path (midi_search_path.to_string ());
-
+ // set the search path for each data type
+ FileSource::set_search_path (DataType::AUDIO, sound_search_path.to_string ());
+ SMFSource::set_search_path (DataType::MIDI, midi_search_path.to_string ());
// reset the round-robin soundfile path thingie
-
last_rr_session_dir = session_dirs.begin();
}
@@ -997,16 +989,11 @@ Session::state(bool full_state)
for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
- /* Don't save information about AudioFileSources that are empty */
+ /* Don't save information about non-destructive file sources that are empty */
+ /* FIXME: MIDI breaks if this is made FileSource like it should be... */
boost::shared_ptr<AudioFileSource> fs;
-
if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (siter->second)) != 0) {
-
- /* Don't save sources that are empty, unless they're destructive (which are OK
- if they are empty, because we will re-use them every time.)
- */
-
if (!fs->destructive()) {
if (fs->length() == 0) {
continue;
@@ -1739,14 +1726,11 @@ Session::load_sources (const XMLNode& node)
set_dirty();
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
-
try {
if ((source = XMLSourceFactory (**niter)) == 0) {
error << _("Session: cannot create Source from XML description.") << endmsg;
}
- }
-
- catch (non_existent_source& err) {
+ } catch (MissingSource& err) {
warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
source = SourceFactory::createSilent (*this, **niter, max_frames, _current_frame_rate);
}
@@ -2622,9 +2606,9 @@ Session::cleanup_sources (Session::cleanup_report& rep)
*/
for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
- boost::shared_ptr<AudioFileSource> fs;
+ boost::shared_ptr<FileSource> fs;
- if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (i->second)) != 0) {
+ if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
all_sources.insert (fs->path());
}
}
diff --git a/libs/ardour/silentfilesource.cc b/libs/ardour/silentfilesource.cc
deleted file mode 100644
index b34944e342..0000000000
--- a/libs/ardour/silentfilesource.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- Copyright (C) 2007 Paul Davis
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include <ardour/silentfilesource.h>
-
-using namespace ARDOUR;
-
-SilentFileSource::SilentFileSource (Session& s, const XMLNode& node, nframes_t len, float sr)
- : AudioFileSource (s, node, false)
-{
- _length = len;
- _sample_rate = sr;
-}
-
-SilentFileSource::~SilentFileSource ()
-{
-}
-
-void
-SilentFileSource::set_length (nframes_t len)
-{
- _length = len;
-}
diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc
index d87293faed..be9b9dd3f1 100644
--- a/libs/ardour/smf_source.cc
+++ b/libs/ardour/smf_source.cc
@@ -45,32 +45,31 @@
#include "i18n.h"
using namespace ARDOUR;
-
-string SMFSource::_search_path;
+using namespace Glib;
/** Constructor used for new internal-to-session files. File cannot exist. */
-SMFSource::SMFSource(Session& s, std::string path, Source::Flag flags)
- : MidiSource(s, region_name_from_path(path, false))
+SMFSource::SMFSource (Session& s, const ustring& path, bool embedded, Source::Flag flags)
+ : Source(s, DataType::MIDI, path, flags)
+ , MidiSource(s, path)
+ , FileSource(s, DataType::MIDI, path, embedded, flags)
, Evoral::SMF()
- , _allow_remove_if_empty(true)
, _last_ev_time_beats(0.0)
, _last_ev_time_frames(0)
{
- if (init(path, false)) {
+ if (init(_name, false)) {
throw failed_constructor ();
}
if (create(path)) {
throw failed_constructor ();
}
-
- assert(_name.find("/") == string::npos);
}
-/** Constructor used for existing internal-to-session files. File must exist. */
-SMFSource::SMFSource(Session& s, const XMLNode& node)
- : MidiSource(s, node)
- , _allow_remove_if_empty(true)
+/** Constructor used for existing internal-to-session files. */
+SMFSource::SMFSource (Session& s, const XMLNode& node, bool must_exist)
+ : Source(s, node)
+ , MidiSource(s, node)
+ , FileSource(s, node, must_exist)
, _last_ev_time_beats(0.0)
, _last_ev_time_frames(0)
{
@@ -85,8 +84,6 @@ SMFSource::SMFSource(Session& s, const XMLNode& node)
if (open(_path)) {
throw failed_constructor ();
}
-
- assert(_name.find("/") == string::npos);
}
SMFSource::~SMFSource ()
@@ -96,40 +93,12 @@ SMFSource::~SMFSource ()
}
}
-bool
-SMFSource::removable () const
-{
- return (_flags & Removable) && ((_flags & RemoveAtDestroy) ||
- ((_flags & RemovableIfEmpty) && is_empty()));
-}
-
-int
-SMFSource::init (string pathstr, bool must_exist)
-{
- bool is_new = false;
-
- if (!find (pathstr, must_exist, is_new)) {
- cerr << "cannot find " << pathstr << " with me = " << must_exist << endl;
- return -1;
- }
-
- if (is_new && must_exist) {
- return -1;
- }
-
- assert(_name.find("/") == string::npos);
- return 0;
-}
-
/** All stamps in audio frames */
nframes_t
SMFSource::read_unlocked (MidiRingBuffer<nframes_t>& dst, nframes_t start, nframes_t dur,
nframes_t stamp_offset, nframes_t negative_stamp_offset) const
{
- //cerr << "SMF read_unlocked " << name() << " read "
- //<< start << ", count=" << dur << ", offset=" << stamp_offset << endl;
-
- int ret;
+ int ret = 0;
uint64_t time = 0; // in SMF ticks, 1 tick per _ppqn
_read_data_count = 0;
@@ -266,7 +235,7 @@ SMFSource::write_unlocked (MidiRingBuffer<nframes_t>& src, nframes_t dur)
/** Append an event with a timestamp in beats (double) */
void
-SMFSource::append_event_unlocked_beats(const Evoral::Event<double>& ev)
+SMFSource::append_event_unlocked_beats (const Evoral::Event<double>& ev)
{
if (ev.size() == 0) {
return;
@@ -297,7 +266,7 @@ SMFSource::append_event_unlocked_beats(const Evoral::Event<double>& ev)
/** Append an event with a timestamp in frames (nframes_t) */
void
-SMFSource::append_event_unlocked_frames(const Evoral::Event<nframes_t>& ev)
+SMFSource::append_event_unlocked_frames (const Evoral::Event<nframes_t>& ev)
{
if (ev.size() == 0) {
return;
@@ -330,49 +299,31 @@ SMFSource::append_event_unlocked_frames(const Evoral::Event<nframes_t>& ev)
}
}
-
XMLNode&
SMFSource::get_state ()
{
- XMLNode& root (MidiSource::get_state());
- char buf[16];
- snprintf (buf, sizeof (buf), "0x%x", (int)_flags);
- root.add_property ("flags", buf);
- return root;
+ return MidiSource::get_state();
}
int
SMFSource::set_state (const XMLNode& node)
{
- const XMLProperty* prop;
+ if (Source::set_state (node)) {
+ return -1;
+ }
if (MidiSource::set_state (node)) {
return -1;
}
-
- if ((prop = node.property (X_("flags"))) != 0) {
- int ival;
- sscanf (prop->value().c_str(), "0x%x", &ival);
- _flags = Flag (ival);
- } else {
- _flags = Flag (0);
+
+ if (FileSource::set_state (node)) {
+ return -1;
}
- assert(_name.find("/") == string::npos);
-
return 0;
}
void
-SMFSource::mark_for_remove ()
-{
- if (!writable()) {
- return;
- }
- _flags = Flag (_flags | RemoveAtDestroy);
-}
-
-void
SMFSource::mark_streaming_midi_write_started (NoteMode mode, nframes_t start_frame)
{
MidiSource::mark_streaming_midi_write_started (mode, start_frame);
@@ -394,212 +345,14 @@ SMFSource::mark_streaming_write_completed ()
Evoral::SMF::end_write ();
}
-void
-SMFSource::mark_take (string id)
-{
- if (writable()) {
- _take_id = id;
- }
-}
-
-int
-SMFSource::move_to_trash (const string trash_dir_name)
-{
- if (!writable()) {
- return -1;
- }
-
- /* don't move the file across filesystems, just stick it in the
- trash_dir_name directory on whichever filesystem it was already on
- */
-
- Glib::ustring newpath;
- newpath = Glib::path_get_dirname (_path);
- newpath = Glib::path_get_dirname (newpath);
-
- newpath += string("/") + trash_dir_name + "/";
- newpath += Glib::path_get_basename (_path);
-
- /* the new path already exists, try versioning */
- if (access (newpath.c_str(), F_OK) == 0) {
- char buf[PATH_MAX+1];
- int version = 1;
- string newpath_v;
-
- snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
- newpath_v = buf;
-
- while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
- snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
- newpath_v = buf;
- }
-
- if (version == 999) {
- PBD::error << string_compose (
- _("there are already 1000 files with names like %1; versioning discontinued"),
- newpath) << endmsg;
- } else {
- newpath = newpath_v;
- }
- }
-
- if (::rename (_path.c_str(), newpath.c_str()) != 0) {
- PBD::error << string_compose (
- _("cannot rename midi file source from %1 to %2 (%3)"),
- _path, newpath, strerror (errno)) << endmsg;
- return -1;
- }
-
- _path = newpath;
-
- /* file can not be removed twice, since the operation is not idempotent */
- _flags = Flag (_flags & ~(RemoveAtDestroy|Removable|RemovableIfEmpty));
-
- return 0;
-}
-
bool
-SMFSource::safe_file_extension(const Glib::ustring& file)
+SMFSource::safe_midi_file_extension (const Glib::ustring& file)
{
return (file.rfind(".mid") != Glib::ustring::npos);
}
-// FIXME: Merge this with audiofilesource somehow (make a generic filesource?)
-bool
-SMFSource::find (string pathstr, bool must_exist, bool& isnew)
-{
- bool ret = false;
-
- isnew = false;
-
- if (pathstr[0] != '/') {
-
- /* non-absolute pathname: find pathstr in search path */
-
- vector<string> dirs;
- int cnt;
- string fullpath;
- string keeppath;
-
- if (_search_path.length() == 0) {
- PBD::error << _("FileSource: search path not set") << endmsg;
- goto out;
- }
-
- split (_search_path, dirs, ':');
-
- cnt = 0;
-
- for (vector<string>::iterator i = dirs.begin(); i != dirs.end(); ++i) {
- fullpath = *i;
- if (fullpath[fullpath.length()-1] != '/') {
- fullpath += '/';
- }
- fullpath += pathstr;
-
- if (access (fullpath.c_str(), R_OK) == 0) {
- keeppath = fullpath;
- ++cnt;
- }
- }
-
- if (cnt > 1) {
-
- PBD::error << string_compose (_("FileSource: \"%1\" is ambigous when searching %2\n\t"), pathstr, _search_path) << endmsg;
- goto out;
-
- } else if (cnt == 0) {
-
- if (must_exist) {
- PBD::error << string_compose(_("Filesource: cannot find required file (%1): while searching %2"), pathstr, _search_path) << endmsg;
- goto out;
- } else {
- isnew = true;
- }
- }
-
- _name = pathstr;
- _path = keeppath;
- ret = true;
-
- } else {
-
- /* external files and/or very very old style sessions include full paths */
-
- _path = pathstr;
- _name = pathstr.substr (pathstr.find_last_of ('/') + 1);
-
- if (access (_path.c_str(), R_OK) != 0) {
-
- /* file does not exist or we cannot read it */
-
- if (must_exist) {
- PBD::error << string_compose(_("Filesource: cannot find required file (%1): %2"), _path, strerror (errno)) << endmsg;
- goto out;
- }
-
- if (errno != ENOENT) {
- PBD::error << string_compose(_("Filesource: cannot check for existing file (%1): %2"), _path, strerror (errno)) << endmsg;
- goto out;
- }
-
- /* a new file */
-
- isnew = true;
- ret = true;
-
- } else {
-
- /* already exists */
-
- ret = true;
- }
- }
-
- out:
- return ret;
-}
-
-void
-SMFSource::set_search_path (string p)
-{
- _search_path = p;
-}
-
-
-void
-SMFSource::set_allow_remove_if_empty (bool yn)
-{
- if (writable()) {
- _allow_remove_if_empty = yn;
- }
-}
-
-int
-SMFSource::set_source_name (string newname, bool destructive)
-{
- //Glib::Mutex::Lock lm (_lock); FIXME
- string oldpath = _path;
- string newpath = Session::change_midi_path_by_name (oldpath, _name, newname, destructive);
-
- if (newpath.empty()) {
- PBD::error << string_compose (_("programming error: %1"), "cannot generate a changed midi path") << endmsg;
- return -1;
- }
-
- if (rename (oldpath.c_str(), newpath.c_str()) != 0) {
- PBD::error << string_compose (_("cannot rename midi file for %1 to %2"), _name, newpath) << endmsg;
- return -1;
- }
-
- _name = Glib::path_get_basename (newpath);
- _path = newpath;
-
- return 0;
-}
-
void
-SMFSource::load_model(bool lock, bool force_reload)
+SMFSource::load_model (bool lock, bool force_reload)
{
if (_writing) {
return;
@@ -662,7 +415,7 @@ SMFSource::load_model(bool lock, bool force_reload)
#define LINEAR_INTERPOLATION_MODE_WORKS_PROPERLY 0
void
-SMFSource::set_default_controls_interpolation()
+SMFSource::set_default_controls_interpolation ()
{
// set interpolation style to defaults, can be changed by the GUI later
Evoral::ControlSet::Controls controls = _model->controls();
@@ -679,14 +432,14 @@ SMFSource::set_default_controls_interpolation()
void
-SMFSource::destroy_model()
+SMFSource::destroy_model ()
{
//cerr << _name << " destroying model " << _model.get() << endl;
_model.reset();
}
void
-SMFSource::flush_midi()
+SMFSource::flush_midi ()
{
Evoral::SMF::end_write();
}
diff --git a/libs/ardour/sndfilesource.cc b/libs/ardour/sndfilesource.cc
index 8d89f2aa92..d651d40970 100644
--- a/libs/ardour/sndfilesource.cc
+++ b/libs/ardour/sndfilesource.cc
@@ -50,38 +50,40 @@ const Source::Flag SndFileSource::default_writable_flags = Source::Flag (
Source::CanRename );
SndFileSource::SndFileSource (Session& s, const XMLNode& node)
- : AudioFileSource (s, node)
+ : Source(s, node)
+ , AudioFileSource (s, node)
{
- init ();
+ init_sndfile ();
if (open()) {
throw failed_constructor ();
}
}
-SndFileSource::SndFileSource (Session& s, ustring path, int chn, Flag flags)
- /* files created this way are never writable or removable */
- : AudioFileSource (s, path, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
+/** Files created this way are never writable or removable */
+SndFileSource::SndFileSource (Session& s, const ustring& path, bool embedded, int chn, Flag flags)
+ : Source(s, DataType::AUDIO, path, flags)
+ , AudioFileSource (s, path, embedded,
+ Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
{
_channel = chn;
- init ();
+ init_sndfile ();
if (open()) {
throw failed_constructor ();
}
}
-SndFileSource::SndFileSource (Session& s, ustring path, SampleFormat sfmt, HeaderFormat hf, nframes_t rate, Flag flags)
- : AudioFileSource (s, path, flags, sfmt, hf)
+/** This constructor is used to construct new files, not open existing ones. */
+SndFileSource::SndFileSource (Session& s, const ustring& path, bool embedded,
+ SampleFormat sfmt, HeaderFormat hf, nframes_t rate, Flag flags)
+ : Source(s, DataType::AUDIO, path, flags)
+ , AudioFileSource (s, path, embedded, flags, sfmt, hf)
{
int fmt = 0;
- init ();
-
- /* this constructor is used to construct new files, not open
- existing ones.
- */
+ init_sndfile ();
_file_is_new = true;
@@ -161,7 +163,7 @@ SndFileSource::SndFileSource (Session& s, ustring path, SampleFormat sfmt, Heade
}
void
-SndFileSource::init ()
+SndFileSource::init_sndfile ()
{
ustring file;
@@ -191,7 +193,8 @@ SndFileSource::init ()
_timeline_position = header_position_offset;
}
- AudioFileSource::HeaderPositionOffsetChanged.connect (mem_fun (*this, &SndFileSource::handle_header_position_change));
+ AudioFileSource::HeaderPositionOffsetChanged.connect (
+ mem_fun (*this, &SndFileSource::handle_header_position_change));
}
int
diff --git a/libs/ardour/source.cc b/libs/ardour/source.cc
index aaae432570..a0ee2ac706 100644
--- a/libs/ardour/source.cc
+++ b/libs/ardour/source.cc
@@ -46,10 +46,11 @@
using namespace std;
using namespace ARDOUR;
-Source::Source (Session& s, const string& name, DataType type, Flag flags)
+Source::Source (Session& s, DataType type, const string& name, Flag flags)
: SessionObject(s, name)
, _type(type)
, _flags(flags)
+ , _timeline_position(0)
{
_analysed = false;
_timestamp = 0;
@@ -61,6 +62,7 @@ Source::Source (Session& s, const XMLNode& node)
: SessionObject(s, "unnamed source")
, _type(DataType::AUDIO)
, _flags (Flag (Writable|CanRename))
+ , _timeline_position(0)
{
_timestamp = 0;
_length = 0;
@@ -83,7 +85,7 @@ Source::get_state ()
XMLNode *node = new XMLNode ("Source");
char buf[64];
- node->add_property ("name", _name);
+ node->add_property ("name", name());
node->add_property ("type", _type.to_string());
node->add_property (X_("flags"), enum_2_string (_flags));
_id.print (buf, sizeof (buf));
@@ -128,6 +130,11 @@ Source::set_state (const XMLNode& node)
_flags = Flag (0);
}
+
+ /* old style, from the period when we had DestructiveFileSource */
+ if ((prop = node.property (X_("destructive"))) != 0) {
+ _flags = Flag (_flags | Destructive);
+ }
return 0;
}
@@ -136,7 +143,7 @@ void
Source::update_length (nframes_t pos, nframes_t cnt)
{
if (pos + cnt > _length) {
- _length = pos+cnt;
+ _length = pos + cnt;
}
}
@@ -272,3 +279,36 @@ Source::check_for_analysis_data_on_disk ()
return ok;
}
+void
+Source::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) {
+ return;
+ }
+
+ _flags = Flag (_flags | Removable | RemoveAtDestroy);
+}
+
+void
+Source::set_timeline_position (int64_t pos)
+{
+ _timeline_position = pos;
+}
+
+void
+Source::set_allow_remove_if_empty (bool yn)
+{
+ if (!writable()) {
+ return;
+ }
+
+ if (yn) {
+ _flags = Flag (_flags | RemovableIfEmpty);
+ } else {
+ _flags = Flag (_flags & ~RemovableIfEmpty);
+ }
+}
+
diff --git a/libs/ardour/source_factory.cc b/libs/ardour/source_factory.cc
index 2d2d6917bd..db5e7d313b 100644
--- a/libs/ardour/source_factory.cc
+++ b/libs/ardour/source_factory.cc
@@ -179,7 +179,8 @@ SourceFactory::create (Session& s, const XMLNode& node, bool defer_peaks)
}
boost::shared_ptr<Source>
-SourceFactory::createReadable (DataType type, Session& s, string path, int chn, Source::Flag flags, bool announce, bool defer_peaks)
+SourceFactory::createReadable (DataType type, Session& s, const string& path, bool embedded,
+ int chn, Source::Flag flags, bool announce, bool defer_peaks)
{
if (type == DataType::AUDIO) {
@@ -187,7 +188,7 @@ SourceFactory::createReadable (DataType type, Session& s, string path, int chn,
try {
- boost::shared_ptr<Source> ret (new SndFileSource (s, path, chn, flags));
+ boost::shared_ptr<Source> ret (new SndFileSource (s, path, embedded, chn, flags));
if (setup_peakfile (ret, defer_peaks)) {
return boost::shared_ptr<Source>();
@@ -203,7 +204,7 @@ SourceFactory::createReadable (DataType type, Session& s, string path, int chn,
catch (failed_constructor& err) {
#ifdef USE_COREAUDIO_FOR_FILES
- boost::shared_ptr<Source> ret (new CoreAudioSource (s, path, chn, flags));
+ boost::shared_ptr<Source> ret (new CoreAudioSource (s, path, embedded, chn, flags));
if (setup_peakfile (ret, defer_peaks)) {
return boost::shared_ptr<Source>();
}
@@ -224,8 +225,7 @@ SourceFactory::createReadable (DataType type, Session& s, string path, int chn,
} else if (type == DataType::MIDI) {
- // FIXME: flags?
- boost::shared_ptr<Source> ret (new SMFSource (s, path, SMFSource::Flag(0)));
+ boost::shared_ptr<Source> ret (new SMFSource (s, path, embedded, SMFSource::Flag(0)));
if (announce) {
SourceCreated (ret);
@@ -239,12 +239,13 @@ SourceFactory::createReadable (DataType type, Session& s, string path, int chn,
}
boost::shared_ptr<Source>
-SourceFactory::createWritable (DataType type, Session& s, std::string path, bool destructive, nframes_t rate, bool announce, bool defer_peaks)
+SourceFactory::createWritable (DataType type, Session& s, const std::string& path, bool embedded,
+ bool destructive, nframes_t rate, bool announce, bool defer_peaks)
{
/* this might throw failed_constructor(), which is OK */
if (type == DataType::AUDIO) {
- boost::shared_ptr<Source> ret (new SndFileSource (s, path,
+ boost::shared_ptr<Source> ret (new SndFileSource (s, path, embedded,
Config->get_native_file_data_format(),
Config->get_native_file_header_format(),
rate,
@@ -265,7 +266,7 @@ SourceFactory::createWritable (DataType type, Session& s, std::string path, bool
} else if (type == DataType::MIDI) {
- boost::shared_ptr<Source> ret (new SMFSource (s, path));
+ boost::shared_ptr<Source> ret (new SMFSource (s, path, embedded, Source::Flag(0)));
// no analysis data - this is a new file
@@ -278,3 +279,4 @@ SourceFactory::createWritable (DataType type, Session& s, std::string path, bool
return boost::shared_ptr<Source> ();
}
+
diff --git a/libs/evoral/evoral/SMF.hpp b/libs/evoral/evoral/SMF.hpp
index 0be2a4b8a7..4a6b21870b 100644
--- a/libs/evoral/evoral/SMF.hpp
+++ b/libs/evoral/evoral/SMF.hpp
@@ -47,7 +47,7 @@ public:
int create(const std::string& path, int track=1, uint16_t ppqn=19200) THROW_FILE_ERROR;
void close() THROW_FILE_ERROR;
- const std::string& path() const { return _path; };
+ const std::string& file_path() const { return _file_path; };
void seek_to_start() const;
int seek_to_track(int track);
@@ -65,7 +65,7 @@ public:
void flush() {};
private:
- std::string _path;
+ std::string _file_path;
smf_t* _smf;
smf_track_t* _smf_track;
bool _empty; ///< true iff file contains(non-empty) events
diff --git a/libs/evoral/src/SMF.cpp b/libs/evoral/src/SMF.cpp
index d7d052e3f0..372c37c0bb 100644
--- a/libs/evoral/src/SMF.cpp
+++ b/libs/evoral/src/SMF.cpp
@@ -80,8 +80,8 @@ SMF::open(const std::string& path, int track) THROW_FILE_ERROR
smf_delete(_smf);
}
- _path = path;
- _smf = smf_load(_path.c_str());
+ _file_path = path;
+ _smf = smf_load(_file_path.c_str());
if (_smf == NULL) {
return -1;
}
@@ -117,7 +117,7 @@ SMF::create(const std::string& path, int track, uint16_t ppqn) THROW_FILE_ERROR
smf_delete(_smf);
}
- _path = path;
+ _file_path = path;
_smf = smf_new();
if (smf_set_ppqn(_smf, ppqn) != 0) {
@@ -148,7 +148,7 @@ void
SMF::close() THROW_FILE_ERROR
{
if (_smf) {
- if (smf_save(_smf, _path.c_str()) != 0) {
+ if (smf_save(_smf, _file_path.c_str()) != 0) {
throw FileError();
}
smf_delete(_smf);
@@ -258,7 +258,7 @@ SMF::begin_write()
void
SMF::end_write() THROW_FILE_ERROR
{
- if (smf_save(_smf, _path.c_str()) != 0)
+ if (smf_save(_smf, _file_path.c_str()) != 0)
throw FileError();
}