Fix the horrible mess that was anything related to sources and paths.
authorDavid Robillard <d@drobilla.net>
Tue, 17 Feb 2009 02:11:49 +0000 (02:11 +0000)
committerDavid Robillard <d@drobilla.net>
Tue, 17 Feb 2009 02:11:49 +0000 (02:11 +0000)
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

33 files changed:
gtk2_ardour/editor_audio_import.cc
gtk2_ardour/editor_export_audio.cc
gtk2_ardour/sfdb_ui.cc
libs/ardour/SConscript
libs/ardour/ardour/audiofilesource.h
libs/ardour/ardour/audiosource.h
libs/ardour/ardour/file_source.h [new file with mode: 0644]
libs/ardour/ardour/midi_source.h
libs/ardour/ardour/route.h
libs/ardour/ardour/session.h
libs/ardour/ardour/silentfilesource.h
libs/ardour/ardour/smf_source.h
libs/ardour/ardour/sndfilesource.h
libs/ardour/ardour/source.h
libs/ardour/ardour/source_factory.h
libs/ardour/audio_diskstream.cc
libs/ardour/audio_library.cc
libs/ardour/audiofilesource.cc
libs/ardour/audiosource.cc
libs/ardour/configuration.cc
libs/ardour/file_source.cc [new file with mode: 0644]
libs/ardour/filter.cc
libs/ardour/import.cc
libs/ardour/midi_source.cc
libs/ardour/session.cc
libs/ardour/session_state.cc
libs/ardour/silentfilesource.cc [deleted file]
libs/ardour/smf_source.cc
libs/ardour/sndfilesource.cc
libs/ardour/source.cc
libs/ardour/source_factory.cc
libs/evoral/evoral/SMF.hpp
libs/evoral/src/SMF.cpp

index b36d1a314e5ee614b6c7c3978cbf4389c2ee41fe..ab5cea3f7b1908a21f7231e55bc55d6e7e3d36ce 100644 (file)
@@ -672,9 +672,10 @@ Editor::embed_sndfiles (vector<Glib::ustring> paths, bool multifile,
                                if ((s = session->source_by_path_and_channel (path, n)) == 0) {
 
                                        source = boost::dynamic_pointer_cast<AudioFileSource> (
-                                                       SourceFactory::createReadable (DataType::AUDIO, *session, path,  n,
+                                                       SourceFactory::createReadable (DataType::AUDIO, *session,
+                                                                       path, false, n,
                                                                        (mode == ImportAsTapeTrack
-                                                                               ? Source::Destructive
+                                                                               ? Source::Destructive
                                                                                : Source::Flag (0)),
                                                                        true, true));
                                } else {
index 621482f0f165ae10b2944f4dc4a9e7743e5c2bf4..7586a813cfeae8230f3fdcbe84d427a806244648 100644 (file)
@@ -204,7 +204,10 @@ Editor::write_region (string path, boost::shared_ptr<AudioRegion> region)
                
                        
                        try {
-                               fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (DataType::AUDIO, *session, path, false, session->frame_rate()));
+                               fs = boost::dynamic_pointer_cast<AudioFileSource> (
+                                               SourceFactory::createWritable (DataType::AUDIO, *session,
+                                                               path, true,
+                                                               false, session->frame_rate()));
                        }
                        
                        catch (failed_constructor& err) {
@@ -340,7 +343,10 @@ Editor::write_audio_range (AudioPlaylist& playlist, const ChanCount& count, list
                path = s;
                
                try {
-                       fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (DataType::AUDIO, *session, path, false, session->frame_rate()));
+                       fs = boost::dynamic_pointer_cast<AudioFileSource> (
+                                       SourceFactory::createWritable (DataType::AUDIO, *session,
+                                                       path, true,
+                                                       false, session->frame_rate()));
                }
                
                catch (failed_constructor& err) {
index 141ce51a9cb5c79ae78255ae0f396f5821d96650..bb95da5c0064e91be34ff0595ce247a9ebb894b8 100644 (file)
@@ -332,8 +332,8 @@ SoundFileBox::audition ()
        for (int n = 0; n < sf_info.channels; ++n) {
                try {
                        afs = boost::dynamic_pointer_cast<AudioFileSource> (
-                                       SourceFactory::createReadable (DataType::AUDIO, *_session, path, 
-                                                       n, Source::Flag (0), false));
+                                       SourceFactory::createReadable (DataType::AUDIO, *_session,
+                                                       path, false, n, Source::Flag (0), false));
                        
                        srclist.push_back(afs);
                        
@@ -639,13 +639,13 @@ SoundFileBrowser::meter ()
 bool
 SoundFileBrowser::on_audio_filter (const FileFilter::Info& filter_info)
 {
-       return AudioFileSource::safe_file_extension (filter_info.filename);
+       return AudioFileSource::safe_audio_file_extension (filter_info.filename);
 }
 
 bool
 SoundFileBrowser::on_midi_filter (const FileFilter::Info& filter_info)
 {
-       return SMFSource::safe_file_extension (filter_info.filename);
+       return SMFSource::safe_midi_file_extension (filter_info.filename);
 }
 
 void
@@ -1096,7 +1096,7 @@ SoundFileOmega::check_info (const vector<ustring>& paths, bool& same_size, bool&
                                src_needed = true;
                        }
 
-               } else if (SMFSource::safe_file_extension (*i)) {
+               } else if (SMFSource::safe_midi_file_extension (*i)) {
 
                        Evoral::SMFReader reader(*i);
                        if (reader.num_tracks() > 1) {
index 83b7d659b5676604cf5bf3bcb8920e1f60973a33..d30c276840ad1f593c5d5d34326964310d186f4c 100644 (file)
@@ -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
index 249651c3cf20a71c5bacbeaaebad6a4e698c4be9..2b59de63ca425026e5e8ccf97d677e9c73487559 100644 (file)
 #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];
index 43273301b1bf2f3db2fbc7ae518d3e6067bc1eb5..eff21b898c7ffc284fbe153c99cda7e2a6f4a473 100644 (file)
@@ -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 (file)
index 0000000..0d6cae9
--- /dev/null
@@ -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__ */
+
index 0dedb3282da89fb186f263ef741bad1c41cee515..0bc431a8d8ba0918cbb7a00a08a323a132cfda00 100644 (file)
@@ -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()
        
index 98b7fa0d641dae7cdab0aff477576563db507329..217ce36fe9759e8bd61776b9f4bd39493fbc89b1 100644 (file)
@@ -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&);
index ef67d0cc79fc86030f01ff8a819589cb04587374..2e56e997225a06e44d353c2e17fedb673beb6338 100644 (file)
@@ -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 ();
 
index cbb123139a78b3c6b0b71f072f1289c0fd35b57d..ad433e5f94ecb0987acfb9009352ea8b1d9ba5a4 100644 (file)
 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
index 4855cb6e319c69399273f37f61982265d0128dc4..259328c5fae428c316b68c5e827f26a7d347d341 100644 (file)
 
 */
 
-#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__ */
 
index acb03391a4f3df4d71b559324ab5a8f33db5f377..5154a7a80c6469685cc86e797ec629d75e277c17 100644 (file)
@@ -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);
 
index 137aad5fbeec6c8594989b9f4ff8526f8cd611bc..7b5fc43659f45d6ec3856b44097da7be398adc34 100644 (file)
@@ -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;
        
index 5370ad845df2c648dd006f2fbf57a9c8328fd8e4..69aa641657e976e34766e9a582a7de31c05f3952 100644 (file)
@@ -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;
index 78f5ee29e2e8a490c82eb304741bf8d5c6178683..ed8027ec59204a342a7d32816de33d627f0fde88 100644 (file)
@@ -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) {
index cd473d933feaab53b249d0274a4451ea46f88860..42ec5378307f08fc92d5c5a492649072080d067a 100644 (file)
@@ -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);
index 434b64e88d7890084c6b1ec1fd621ee70f11cf9a..d1371ad0fb831120c014529d3bc0f6485162c1d2 100644 (file)
@@ -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,45 +255,21 @@ 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 ()
 {
@@ -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)
 {
index 8d710b247a0bb496d042d7c9f3fe2214da2c6c57..7b56d1891ef156a5ba4270904198a96818e1ea28 100644 (file)
@@ -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;
-       }
-}
-
index 1a78848a345162dbfaa24fdeea7ced6df222bc0b..d322ab4e499a41c1ac09d1f81dcaf8dd4494b558 100644 (file)
@@ -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 (file)
index 0000000..ed9c803
--- /dev/null
@@ -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));
+       }
+}
+
index 007555577305381fdb1ed3a59f663b7385f445d1..30393a145db4d6b52f22a7af3b63dedfa7c2be80 100644 (file)
@@ -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) {
index f983352d58d999c9c99cf84bfd19c15b9eaf3d9e..92ecaec75305693c16571498d8e703bbda839ec5 100644 (file)
@@ -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;
        }
 }
 
index 03208eda029244e16a1411d55c74c2834e211bd4..b539d5b9d392e6d0bf3b1bd7c9b37d5a3b61279b 100644 (file)
@@ -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);
index a0b61f3b97b8d681ccb87ba4d05d66e345a413dd..e55167ff0891a82ca2f45d69ba751e395a8a719f 100644 (file)
@@ -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) {
index ce6878b881066d1676360b8804c37137048232b9..3f9a48134067834e2c4bfbdd6c3c1424cc9c938b 100644 (file)
@@ -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 (file)
index b34944e..0000000
+++ /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;
-}
index d87293faed7e226b6734a6cedbd5cb5bef93e3f0..be9b9dd3f125033fbb73b069a69d428b6080ed87 100644 (file)
 #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,48 +299,30 @@ 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)
 {
@@ -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();
 }
index 8d89f2aa924fe4ce55fb856e30a16cd8c35556ce..d651d409707877bce949b554e75b51e706eb2ff0 100644 (file)
@@ -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
index aaae432570fbdb7f02bba2c43fe223103e35d114..a0ee2ac706497b8f905100462a3f26d8b15f2a6b 100644 (file)
 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);
+       }
+}
+
index 2d2d6917bdd6dc6b90a510e9795d9fb4088a7b50..db5e7d313b4e12e1066574ce05a81b67509af19b 100644 (file)
@@ -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> ();
 }
+
index 0be2a4b8a7d3dcfae5f8dfd66cb25fbba6fb5e11..4a6b21870b05312293e53dc0b95e5587b9d73ce2 100644 (file)
@@ -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
index d7d052e3f07081ea73db054abce374ea48a66ad6..372c37c0bb79b4ba5a493d8dd830dec5b6fc001f 100644 (file)
@@ -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();
 }