remove entire "stub" file concept; open new audio and MIDI files on demand (at first...
authorPaul Davis <paul@linuxaudiosystems.com>
Wed, 2 Mar 2011 17:05:16 +0000 (17:05 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Wed, 2 Mar 2011 17:05:16 +0000 (17:05 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@9038 d708f5d6-7413-0410-9779-e7cbd77b26cf

17 files changed:
libs/ardour/ardour/directory_names.h
libs/ardour/ardour/file_source.h
libs/ardour/ardour/midi_source.h
libs/ardour/ardour/session.h
libs/ardour/ardour/session_directory.h
libs/ardour/ardour/smf_source.h
libs/ardour/audio_diskstream.cc
libs/ardour/directory_names.cc
libs/ardour/file_source.cc
libs/ardour/midi_diskstream.cc
libs/ardour/midi_model.cc
libs/ardour/midi_source.cc
libs/ardour/session.cc
libs/ardour/session_directory.cc
libs/ardour/session_state.cc
libs/ardour/smf_source.cc
libs/ardour/sndfilesource.cc

index 0d330cd5a533598be7cf484cf76c2c058161981d..db87d347aa2cd6e41505183e07d76d2bc93125ba 100644 (file)
@@ -19,7 +19,6 @@ extern const char* const templates_dir_name;
 extern const char* const route_templates_dir_name;
 extern const char* const surfaces_dir_name;
 extern const char* const user_config_dir_name;
-extern const char* const stub_dir_name;
 extern const char* const panner_dir_name;
 
 };
index 23b8b8f8c89c3b5d01b7af3b020ccbeb757b3148..01fa6adb749e645cdcf3e42200436a5217b8de0c 100644 (file)
@@ -48,12 +48,6 @@ public:
        
        const std::string& path() const { return _path; }
 
-        int  unstubify ();
-        void stubify ();
-        bool is_stub () const;
-
-        static bool is_stub_path (const std::string& path);
-
        virtual bool safe_file_extension (const std::string& path) const = 0;
 
        int  move_to_trash (const std::string& trash_dir_name);
@@ -104,7 +98,8 @@ protected:
        uint16_t    _channel;
        bool        _within_session;
         std::string _origin;
-
+        bool        _open;
+        
         void prevent_deletion ();
 };
 
index 4cfba10930703a5ad627eea815ea3d89a2a2da17..a1738a2aa94458f3e33a8dd2251fe2cf3d0c16e0 100644 (file)
@@ -78,7 +78,7 @@ class MidiSource : virtual public Source, public boost::enable_shared_from_this<
        virtual framecnt_t length (framepos_t pos) const;
        virtual void       update_length (framepos_t pos, framecnt_t cnt);
 
-       virtual void mark_streaming_midi_write_started (NoteMode mode, framepos_t start_time);
+       virtual void mark_streaming_midi_write_started (NoteMode mode);
        virtual void mark_streaming_write_started ();
        virtual void mark_streaming_write_completed ();
        void mark_write_starting_now ();
index bf3df2f0a8467a32477e2deada9b487e3845a518..c7a72a4e636899b37c2716700dac60b36a60e404 100644 (file)
@@ -187,7 +187,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
        std::string peak_path_from_audio_path (std::string) const;
        std::string new_audio_source_name (const std::string&, uint32_t nchans, uint32_t chan, bool destructive);
        std::string new_midi_source_name (const std::string&);
-       std::string new_source_path_from_name (DataType type, const std::string&, bool as_stub = false);
+       std::string new_source_path_from_name (DataType type, const std::string&);
        RouteList new_route_from_template (uint32_t how_many, const std::string& template_path);
 
        void process (pframes_t nframes);
@@ -543,10 +543,10 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
        static PBD::Signal0<int> AskAboutPendingState;
 
        boost::shared_ptr<AudioFileSource> create_audio_source_for_session (
-               size_t, std::string const &, uint32_t, bool destructive, bool as_stub = false);
+               size_t, std::string const &, uint32_t, bool destructive);
        
        boost::shared_ptr<MidiSource> create_midi_source_for_session (
-               Track*, std::string const &, bool as_stub = false);
+               Track*, std::string const &);
 
        boost::shared_ptr<Source> source_by_id (const PBD::ID&);
        boost::shared_ptr<Source> source_by_path_and_channel (const std::string&, uint16_t);
@@ -1472,7 +1472,6 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
        void add_session_range_location (framepos_t, framepos_t);
 
        void setup_midi_machine_control ();
-       void cleanup_stubfiles ();
 
        void route_order_key_changed ();
 
index b7de1c8f0fcaae9e5296782b616e1978a81662a6..49ef879ea1efd9c7ec6dbc173c5f77e50585d7f0 100644 (file)
@@ -51,17 +51,6 @@ public:
         */
        const PBD::sys::path sound_path () const;
 
-       /**
-        * @return the absolute path to the directory in which
-        * the session stores STUB audio files.
-        *
-        * If the session is an older session with an existing
-        * "sounds" directory then it will return a path to that
-        * directory otherwise it will return the new location
-        * of root_path()/interchange/session_name/audiofiles/.stubs
-        */
-       const PBD::sys::path sound_stub_path () const;
-
        /**
         * @return the absolute path to the directory in which
         * the session stores MIDI files, ie
@@ -69,13 +58,6 @@ public:
         */
        const PBD::sys::path midi_path () const;
 
-       /**
-        * @return the absolute path to the directory in which
-        * the session stores STUB MIDI files, ie
-        * root_path()/interchange/session_name/midifiles/.stubs
-        */
-       const PBD::sys::path midi_stub_path () const;
-
        /**
         * @return the absolute path to the directory in which
         * the session stores MIDNAM patch files, ie
index 32163551a0cfd4293b03b26405c4dff54195d050..b0186d690d34d58699d0c6dc7240d81cd705604e 100644 (file)
@@ -54,7 +54,7 @@ public:
        void append_event_unlocked_beats (const Evoral::Event<Evoral::MusicalTime>& ev);
        void append_event_unlocked_frames (const Evoral::Event<framepos_t>& ev, framepos_t source_start);
 
-       void mark_streaming_midi_write_started (NoteMode mode, framepos_t start_time);
+       void mark_streaming_midi_write_started (NoteMode mode);
        void mark_streaming_write_completed ();
 
        XMLNode& get_state ();
@@ -73,6 +73,8 @@ public:
         void set_path (const std::string& newpath);
         
   private:
+        int open_for_write ();
+
        framecnt_t read_unlocked (Evoral::EventSink<framepos_t>& dst,
                                  framepos_t position,
                                  framepos_t start,
index 2c0dcb3e97a77dcf571d8d4cfa201f6fcad8ea07..f4b27f6e6a0987f91c667a39a66e2a8395d3b86c 100644 (file)
@@ -1425,9 +1425,6 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo
 
                if (s) {
                        srcs.push_back (s);
-                        if (s->unstubify ()) {
-                                error << string_compose (_("Could not move capture file from %1"), s->path()) << endmsg;
-                        }
                        s->update_header (capture_info.front()->start, when, twhen);
                        s->set_captured_for (_name.val());
                        s->mark_immutable ();
@@ -1903,13 +1900,8 @@ AudioDiskstream::use_new_write_source (uint32_t n)
        ChannelInfo* chan = (*c)[n];
 
        try {
-                /* file starts off as a stub file, it will be converted
-                   when we're done with a capture pass.
-                */
-
                if ((chan->write_source = _session.create_audio_source_for_session (n_channels().n_audio(), 
-                                                                                    name(), n, destructive(), 
-                                                                                    true)) == 0) {
+                                                                                    name(), n, destructive())) == 0) {
                        throw failed_constructor();
                }
        }
index 247dd04978bf03153563e6263941bc7d042c85c2..32e46d995183968a560eed3d27a6f313ab411c3a 100644 (file)
@@ -16,7 +16,6 @@ const char* const templates_dir_name = X_("templates");
 const char* const route_templates_dir_name = X_("route_templates");
 const char* const surfaces_dir_name = X_("surfaces");
 const char* const user_config_dir_name = X_("ardour3");
-const char* const stub_dir_name = X_(".stubs");
 const char* const panner_dir_name = X_("panners");
 
 }
index bf68e2ec1590881fe6681db1df81a080d03b6572..5522031d691d6438db88fc9f513adc311bca9635 100644 (file)
@@ -60,6 +60,7 @@ FileSource::FileSource (Session& session, DataType type, const string& path, con
        , _file_is_new(true)
        , _channel (0)
         , _origin (origin)
+        , _open (false)
 {
        set_within_session_from_path (path);
 
@@ -99,11 +100,10 @@ FileSource::prevent_deletion ()
 bool
 FileSource::removable () const
 {
-        bool r = (_path.find (stub_dir_name) != string::npos) ||
-                ((_flags & Removable)
-                 && ((_flags & RemoveAtDestroy) || 
-                     ((_flags & RemovableIfEmpty) && empty() == 0)));
-
+        bool r = ((_flags & Removable)
+                  && ((_flags & RemoveAtDestroy) || 
+                      ((_flags & RemovableIfEmpty) && empty() == 0)));
+        
         return r;
 }
 
@@ -537,44 +537,6 @@ FileSource::set_within_session_from_path (const std::string& path)
        _within_session = _session.path_is_within_session (path);
 }
 
-bool
-FileSource::is_stub_path (const std::string& path)
-{
-        return path.find (stub_dir_name) != string::npos;
-}
-
-bool
-FileSource::is_stub () const
-{
-        return is_stub_path (_path);
-}
-
-int
-FileSource::unstubify ()
-{
-        string::size_type pos = _path.find (stub_dir_name);
-
-        if (pos == string::npos || (_flags & Destructive)) {
-                return 0;
-        }
-
-        vector<string> v;
-
-        v.push_back (Glib::path_get_dirname (Glib::path_get_dirname (_path)));
-       v.push_back (Glib::path_get_basename(_path));
-        
-        string newpath = Glib::build_filename (v);
-
-        if (::rename (_path.c_str(), newpath.c_str()) != 0) {
-                error << string_compose (_("rename from %1 to %2 failed: %3)"), _path, newpath, strerror (errno)) << endmsg;
-                return -1;
-        }
-
-        set_path (newpath);
-
-        return 0;
-}
-
 void
 FileSource::set_path (const std::string& newpath)
 {
index 09b3ae1a407123ed1dc9b44f50deb35c683f0eac..4bdcbef2b69f4867dce460d8dc6480138048cb57 100644 (file)
@@ -981,10 +981,6 @@ MidiDiskstream::transport_stopped_wallclock (struct tm& /*when*/, time_t /*twhen
                        const double total_capture_beats = converter.from(total_capture);
                        _write_source->set_length_beats(total_capture_beats);
 
-                       /* make it not a stub anymore */
-
-                       _write_source->unstubify ();
-
                        /* we will want to be able to keep (over)writing the source
                           but we don't want it to be removable. this also differs
                           from the audio situation, where the source at this point
@@ -1366,13 +1362,8 @@ MidiDiskstream::use_new_write_source (uint32_t n)
        _write_source.reset();
 
        try {
-               /* file starts off as a stub file, it will be converted
-                  when we're done with a capture pass, or when "stolen"
-                  by the GUI.
-               */
-
                _write_source = boost::dynamic_pointer_cast<SMFSource>(
-                       _session.create_midi_source_for_session (0, name (), true));
+                       _session.create_midi_source_for_session (0, name ()));
 
                if (!_write_source) {
                        throw failed_constructor();
@@ -1385,8 +1376,6 @@ MidiDiskstream::use_new_write_source (uint32_t n)
                return -1;
        }
 
-       _write_source->mark_streaming_midi_write_started (_note_mode, _session.transport_frame());
-
        return 0;
 }
 
@@ -1403,8 +1392,6 @@ MidiDiskstream::steal_write_sources()
 
        boost::dynamic_pointer_cast<MidiSource>(_write_source)->session_saved ();
 
-       /* make it visible/present */
-       _write_source->unstubify ();
        /* never let it go away */
        _write_source->mark_nonremovable ();
 
index 2cdf6b45da375f1bf079c9ab0814ca488489fb1e..b7b781cec982e43f2b3cd112dc2170879a6008be 100644 (file)
@@ -1335,7 +1335,7 @@ MidiModel::write_to (boost::shared_ptr<MidiSource> source)
        assert (ms);
        
        source->drop_model();
-       source->mark_streaming_midi_write_started (note_mode(), ms->timeline_position ());
+       source->mark_streaming_midi_write_started (note_mode());
 
        for (Evoral::Sequence<TimeType>::const_iterator i = begin(0, true); i != end(); ++i) {
                source->append_event_unlocked_beats(*i);
@@ -1365,7 +1365,7 @@ MidiModel::sync_to_source ()
        boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
        assert (ms);
        
-       ms->mark_streaming_midi_write_started (note_mode(), ms->timeline_position());
+       ms->mark_streaming_midi_write_started (note_mode());
 
        for (Evoral::Sequence<TimeType>::const_iterator i = begin(0, true); i != end(); ++i) {
                ms->append_event_unlocked_beats(*i);
@@ -1400,7 +1400,7 @@ MidiModel::write_section_to (boost::shared_ptr<MidiSource> source, Evoral::Music
        assert (ms);
        
        source->drop_model();
-       source->mark_streaming_midi_write_started (note_mode(), ms->timeline_position());
+       source->mark_streaming_midi_write_started (note_mode());
 
        for (Evoral::Sequence<TimeType>::const_iterator i = begin(0, true); i != end(); ++i) {
                const Evoral::Event<Evoral::MusicalTime>& ev (*i);
index 16ff6ac7ac21f55185e18859e77db24617b195c4..719c2a3affb07148dc8d408f61a8b23661e3d9da 100644 (file)
@@ -265,11 +265,11 @@ MidiSource::midi_write (MidiRingBuffer<framepos_t>& source, framepos_t source_st
 }
 
 void
-MidiSource::mark_streaming_midi_write_started (NoteMode mode, framepos_t start_frame)
+MidiSource::mark_streaming_midi_write_started (NoteMode mode)
 {
        if (_model) {
-               _model->set_note_mode(mode);
-               _model->start_write();
+               _model->set_note_mode (mode);
+               _model->start_write ();
        }
 
        _writing = true;
@@ -297,7 +297,7 @@ void
 MidiSource::mark_streaming_write_started ()
 {
        NoteMode note_mode = _model ? _model->note_mode() : Sustained;
-       mark_streaming_midi_write_started(note_mode, _session.transport_frame());
+       mark_streaming_midi_write_started (note_mode);
 }
 
 void
index c554996a4970ed5c9f921baba00c7ea429f8d913..f1f2919b5f7244f2fe18c8f0c4e58c929cc65d1a 100644 (file)
@@ -238,10 +238,6 @@ Session::destroy ()
 
        delete state_tree;
 
-       /* remove all stubfiles that might still be lurking */
-
-       cleanup_stubfiles ();
-
        /* reset dynamic state version back to default */
 
        Stateful::loading_state_version = 0;
@@ -2878,7 +2874,7 @@ Session::change_source_path_by_name (string path, string oldname, string newname
  *         (e.g. as returned by new_*_source_name)
  */
 string
-Session::new_source_path_from_name (DataType type, const string& name, bool as_stub)
+Session::new_source_path_from_name (DataType type, const string& name)
 {
        assert(name.find("/") == string::npos);
 
@@ -2886,9 +2882,9 @@ Session::new_source_path_from_name (DataType type, const string& name, bool as_s
 
        sys::path p;
        if (type == DataType::AUDIO) {
-               p = (as_stub ? sdir.sound_stub_path() : sdir.sound_path());
+               p = sdir.sound_path();
        } else if (type == DataType::MIDI) {
-               p = (as_stub ? sdir.midi_stub_path() : sdir.midi_path());
+               p = sdir.midi_path();
        } else {
                error << "Unknown source type, unable to create file path" << endmsg;
                return "";
@@ -2968,7 +2964,6 @@ Session::new_audio_source_name (const string& base, uint32_t nchan, uint32_t cha
                        SessionDirectory sdir((*i).path);
 
                        string spath = sdir.sound_path().to_string();
-                       string spath_stubs = sdir.sound_stub_path().to_string();
 
                        /* note that we search *without* the extension so that
                           we don't end up both "Audio 1-1.wav" and "Audio 1-1.caf" 
@@ -2976,8 +2971,7 @@ Session::new_audio_source_name (const string& base, uint32_t nchan, uint32_t cha
                           a file format change.
                        */
 
-                       if (matching_unsuffixed_filename_exists_in (spath, buf) ||
-                           matching_unsuffixed_filename_exists_in (spath_stubs, buf)) {
+                       if (matching_unsuffixed_filename_exists_in (spath, buf)) {
                                existing++;
                                break;
                        }
@@ -3001,10 +2995,10 @@ Session::new_audio_source_name (const string& base, uint32_t nchan, uint32_t cha
 
 /** Create a new within-session audio source */
 boost::shared_ptr<AudioFileSource>
-Session::create_audio_source_for_session (size_t n_chans, string const & n, uint32_t chan, bool destructive, bool as_stub)
+Session::create_audio_source_for_session (size_t n_chans, string const & n, uint32_t chan, bool destructive)
 {
        const string name    = new_audio_source_name (n, n_chans, chan, destructive);
-       const string path    = new_source_path_from_name(DataType::AUDIO, name, as_stub);
+       const string path    = new_source_path_from_name(DataType::AUDIO, name);
 
        return boost::dynamic_pointer_cast<AudioFileSource> (
                SourceFactory::createWritable (DataType::AUDIO, *this, path, string(), destructive, frame_rate()));
@@ -3061,7 +3055,7 @@ Session::new_midi_source_name (const string& base)
 
 /** Create a new within-session MIDI source */
 boost::shared_ptr<MidiSource>
-Session::create_midi_source_for_session (Track* track, string const & n, bool as_stub)
+Session::create_midi_source_for_session (Track* track, string const & n)
 {
        /* try to use the existing write source for the track, to keep numbering sane 
         */
@@ -3080,7 +3074,7 @@ Session::create_midi_source_for_session (Track* track, string const & n, bool as
        }
 
        const string name = new_midi_source_name (n);
-       const string path = new_source_path_from_name (DataType::MIDI, name, as_stub);
+       const string path = new_source_path_from_name (DataType::MIDI, name);
 
        return boost::dynamic_pointer_cast<SMFSource> (
                SourceFactory::createWritable (
index 1948a5a9b98655a1308c9f9efa1ceff7c20d6158..8996b74f61de46b31936d951ae337b98d60283c2 100644 (file)
@@ -101,27 +101,12 @@ SessionDirectory::sound_path () const
        return sources_root() / sound_dir_name;
 }
 
-const path
-SessionDirectory::sound_stub_path () const
-{
-       if(is_directory (old_sound_path ())) return old_sound_path();
-
-       // the new style sound directory
-       return sources_root() / sound_dir_name / stub_dir_name;
-}
-
 const path
 SessionDirectory::midi_path () const
 {
        return sources_root() / midi_dir_name;
 }
 
-const path
-SessionDirectory::midi_stub_path () const
-{
-       return sources_root() / midi_dir_name / stub_dir_name;
-}
-
 const path
 SessionDirectory::midi_patch_path () const
 {
index 82ee766b2338eb8b73db530b48b9e301b8f95b68..8d83cefeeb6120042493bd7a3403687f940463fd 100644 (file)
@@ -467,13 +467,6 @@ Session::ensure_subdirs ()
                return -1;
        }
 
-       dir = session_directory().sound_stub_path().to_string();
-
-       if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
-               error << string_compose(_("Session: cannot create session stub sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
-               return -1;
-       }
-
        dir = session_directory().midi_path().to_string();
 
        if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
@@ -481,13 +474,6 @@ Session::ensure_subdirs ()
                return -1;
        }
 
-       dir = session_directory().midi_stub_path().to_string();
-
-       if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
-               error << string_compose(_("Session: cannot create session stub midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
-               return -1;
-       }
-
        dir = session_directory().dead_path().to_string();
 
        if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
@@ -1236,8 +1222,6 @@ Session::set_state (const XMLNode& node, int version)
 
        setup_raid_path(_session_dir->root_path().to_string());
 
-       cleanup_stubfiles ();
-       
        if ((prop = node.property (X_("id-counter"))) != 0) {
                uint64_t x;
                sscanf (prop->value().c_str(), "%" PRIu64, &x);
@@ -2416,16 +2400,12 @@ Session::commit_reversible_command (Command *cmd)
 }
 
 static bool
-accept_all_non_stub_audio_files (const string& path, void */*arg*/)
+accept_all_audio_files (const string& path, void */*arg*/)
 { 
         if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
                 return false;
         }
 
-        if (FileSource::is_stub_path (path)) {
-                return false;
-        }
-
         if (!AudioFileSource::safe_audio_file_extension (path)) {
                 return false;
         }
@@ -2434,16 +2414,12 @@ accept_all_non_stub_audio_files (const string& path, void */*arg*/)
 }
 
 static bool
-accept_all_non_stub_midi_files (const string& path, void */*arg*/)
+accept_all_midi_files (const string& path, void */*arg*/)
 {
         if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
                 return false;
         }
 
-        if (FileSource::is_stub_path (path)) {
-                return false;
-        }
-
        return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
                 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
                 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
@@ -2686,8 +2662,8 @@ Session::cleanup_sources (CleanupReport& rep)
                i = nexti;
        }
 
-       candidates = scanner (audio_path, accept_all_non_stub_audio_files, (void *) 0, true, true);
-       candidates2 = scanner (midi_path, accept_all_non_stub_midi_files, (void *) 0, true, true);
+       candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
+       candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
 
         /* merge them */
 
@@ -2718,22 +2694,18 @@ Session::cleanup_sources (CleanupReport& rep)
                 ++tmp;
 
                if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
-                        if (!fs->is_stub()) {
-                                if (playlists->source_use_count (fs) != 0) {
-                                        all_sources.insert (fs->path());
-                                } else {
-                                        
-                                        /* we might not remove this source from disk, because it may be used
-                                           by other snapshots, but its not being used in this version
-                                           so lets get rid of it now, along with any representative regions
-                                           in the region list.
-                                        */
-
-                                        cerr << "Source " << i->second->name() << "ID " << i->second->id() << " not used, remove from source list and also all regions\n";
-                                        
-                                        RegionFactory::remove_regions_using_source (i->second);
-                                        sources.erase (i);
-                                }
+                        if (playlists->source_use_count (fs) != 0) {
+                                all_sources.insert (fs->path());
+                        } else {
+                                
+                                /* we might not remove this source from disk, because it may be used
+                                   by other snapshots, but its not being used in this version
+                                   so lets get rid of it now, along with any representative regions
+                                   in the region list.
+                                */
+                                
+                                RegionFactory::remove_regions_using_source (i->second);
+                                sources.erase (i);
                         }
                }
 
@@ -2920,45 +2892,6 @@ Session::cleanup_trash_sources (CleanupReport& rep)
        return 0;
 }
 
-void
-Session::cleanup_stubfiles ()
-{
-       vector<space_and_path>::iterator i;
-
-       for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
-
-                string dir;
-                string lname = legalize_for_path (_name);
-
-                vector<string> v;
-
-                /* XXX this is a hack caused by semantic conflicts
-                   between space_and_path and the SessionDirectory concept.
-                */
-
-                v.push_back ((*i).path);
-                v.push_back ("interchange");
-                v.push_back (lname);
-                v.push_back ("audiofiles");
-                v.push_back (stub_dir_name);
-
-                dir = Glib::build_filename (v);
-                
-                clear_directory (dir);
-
-                v.clear ();
-                v.push_back ((*i).path);
-                v.push_back ("interchange");
-                v.push_back (lname);
-                v.push_back ("midifiles");
-                v.push_back (stub_dir_name);
-
-                dir = Glib::build_filename (v);
-
-                clear_directory (dir);
-       }
-}
-
 void
 Session::set_dirty ()
 {
index f134ff53351be085c73cc790eb35fec230fc21bc..c686ae3d27705e3ac86475bad6ff7a6bcdf3cfb3 100644 (file)
@@ -65,10 +65,8 @@ SMFSource::SMFSource (Session& s, const string& path, Source::Flag flags)
        if (init(_path, false)) {
                throw failed_constructor ();
        }
-
-       if (create(path)) {
-               throw failed_constructor ();
-       }
+        
+        /* file is not opened until write */
 }
 
 /** Constructor used for existing internal-to-session files. */
@@ -92,6 +90,8 @@ SMFSource::SMFSource (Session& s, const XMLNode& node, bool must_exist)
        if (open(_path)) {
                throw failed_constructor ();
        }
+
+        _open = true;
 }
 
 SMFSource::~SMFSource ()
@@ -101,6 +101,16 @@ SMFSource::~SMFSource ()
        }
 }
 
+int
+SMFSource::open_for_write ()
+{
+       if (create (_path)) {
+                return -1;
+        } 
+        _open = true;
+        return 0;
+}
+
 /** All stamps in audio frames */
 framecnt_t
 SMFSource::read_unlocked (Evoral::EventSink<framepos_t>& destination, framepos_t const source_start,
@@ -110,6 +120,11 @@ SMFSource::read_unlocked (Evoral::EventSink<framepos_t>& destination, framepos_t
        int      ret  = 0;
        uint64_t time = 0; // in SMF ticks, 1 tick per _ppqn
 
+        if (writable() && !_open) {
+                /* nothing to read since nothing has ben written */
+                return duration;
+        }
+
        DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("SMF read_unlocked: start %1 duration %2\n", start, duration));
 
        _read_data_count = 0;
@@ -206,6 +221,15 @@ SMFSource::read_unlocked (Evoral::EventSink<framepos_t>& destination, framepos_t
 framecnt_t
 SMFSource::write_unlocked (MidiRingBuffer<framepos_t>& source, framepos_t position, framecnt_t duration)
 {
+        if (!_open && open_for_write()) {
+                error << string_compose (_("cannot open MIDI file %1 for write"), _path) << endmsg;
+                return 0;
+        }
+
+        if (!_writing) {
+                mark_streaming_write_started ();
+        }
+
        _write_data_count = 0;
 
        framepos_t        time;
@@ -387,10 +411,11 @@ SMFSource::set_state (const XMLNode& node, int version)
 }
 
 void
-SMFSource::mark_streaming_midi_write_started (NoteMode mode, framepos_t start_frame)
+SMFSource::mark_streaming_midi_write_started (NoteMode mode)
 {
-       Glib::Mutex::Lock lm (_lock);
-       MidiSource::mark_streaming_midi_write_started (mode, start_frame);
+        /* CALLER MUST HOLD LOCK */
+
+       MidiSource::mark_streaming_midi_write_started (mode);
        Evoral::SMF::begin_write ();
        _last_ev_time_beats = 0.0;
        _last_ev_time_frames = 0;
@@ -444,6 +469,10 @@ SMFSource::load_model (bool lock, bool force_reload)
                _model->clear();
        }
 
+        if (writable() && !_open) {
+                return;
+        }
+
        _model->start_write();
        Evoral::SMF::seek_to_start();
 
@@ -533,7 +562,7 @@ SMFSource::destroy_model ()
 void
 SMFSource::flush_midi ()
 {
-       if (!writable()) {
+       if (!writable() || (writable() && !_open)) {
                return;
        }
 
index 20d6067c36f745b3294cff5c30327585cc8a3822..8fad3b37059873a1c1d291ada94d4859d7ccb509 100644 (file)
@@ -89,7 +89,7 @@ SndFileSource::SndFileSource (Session& s, const string& path, const string& orig
 {
        int fmt = 0;
 
-       init_sndfile ();
+        init_sndfile ();
 
        _file_is_new = true;
 
@@ -143,37 +143,9 @@ SndFileSource::SndFileSource (Session& s, const string& path, const string& orig
        _info.channels = 1;
        _info.samplerate = rate;
        _info.format = fmt;
-
-       if (open()) {
-               throw failed_constructor();
-       }
-
-       if (writable() && (_flags & Broadcast)) {
-
-               SNDFILE* sf = _descriptor->allocate ();
-               if (sf == 0) {
-                       error << string_compose (_("could not allocate file %1"), _path) << endmsg;
-                       throw failed_constructor ();
-               }
-
-               if (!_broadcast_info) {
-                       _broadcast_info = new BroadcastInfo;
-               }
-
-               _broadcast_info->set_from_session (s, header_position_offset);
-               _broadcast_info->set_description (string_compose ("BWF %1", _name));
-
-               if (!_broadcast_info->write_to_file (sf)) {
-                       error << string_compose (_("cannot set broadcast info for audio file %1 (%2); dropping broadcast info for this file"),
-                                                  _path, _broadcast_info->get_error())
-                             << endmsg;
-                       _flags = Flag (_flags & ~Broadcast);
-                       delete _broadcast_info;
-                       _broadcast_info = 0;
-               }
-
-               _descriptor->release ();
-       }
+        
+        /* do not open the file here - do that in write_unlocked() as needed
+         */
 }
 
 void
@@ -181,6 +153,8 @@ SndFileSource::init_sndfile ()
 {
        string file;
 
+        _descriptor = 0;
+
        // lets try to keep the object initalizations here at the top
        xfade_buf = 0;
        _broadcast_info = 0;
@@ -253,9 +227,29 @@ SndFileSource::open ()
 
        if (writable()) {
                sf_command (sf, SFC_SET_UPDATE_HEADER_AUTO, 0, SF_FALSE);
-       }
+                
+                if (_flags & Broadcast) {
+                        
+                        if (!_broadcast_info) {
+                                _broadcast_info = new BroadcastInfo;
+                        }
+                        
+                        _broadcast_info->set_from_session (_session, header_position_offset);
+                        _broadcast_info->set_description (string_compose ("BWF %1", _name));
+                        
+                        if (!_broadcast_info->write_to_file (sf)) {
+                                error << string_compose (_("cannot set broadcast info for audio file %1 (%2); dropping broadcast info for this file"),
+                                                         _path, _broadcast_info->get_error())
+                                      << endmsg;
+                                _flags = Flag (_flags & ~Broadcast);
+                                delete _broadcast_info;
+                                _broadcast_info = 0;
+                        }
+                }
+        }
 
-       _descriptor->release ();
+        _descriptor->release ();
+        _open = true;
        return 0;
 }
 
@@ -280,7 +274,14 @@ SndFileSource::read_unlocked (Sample *dst, framepos_t start, framecnt_t cnt) con
        uint32_t real_cnt;
        framepos_t file_cnt;
 
+        if (writable() && !_open) {
+                /* file has not been opened yet - nothing written to it */
+                memset (dst, 0, sizeof (Sample) * cnt);
+                return cnt;
+        }
+
        SNDFILE* sf = _descriptor->allocate ();
+
        if (sf == 0) {
                error << string_compose (_("could not allocate file %1 for reading."), _path) << endmsg;
                return 0;
@@ -357,6 +358,10 @@ SndFileSource::read_unlocked (Sample *dst, framepos_t start, framecnt_t cnt) con
 framecnt_t
 SndFileSource::write_unlocked (Sample *data, framecnt_t cnt)
 {
+        if (!_open && open()) {
+                return 0; // failure
+        }
+
        if (destructive()) {
                return destructive_write_unlocked (data, cnt);
        } else {
@@ -511,6 +516,11 @@ SndFileSource::flush_header ()
                return -1;
        }
 
+        if (!_open) {
+               warning << string_compose (_("attempt to flush an un-opened audio file source (%1)"), _path) << endmsg;
+               return -1;
+        }
+
        SNDFILE* sf = _descriptor->allocate ();
        if (sf == 0) {
                error << string_compose (_("could not allocate file %1 to write header"), _path) << endmsg;
@@ -531,6 +541,11 @@ SndFileSource::setup_broadcast_info (framepos_t /*when*/, struct tm& now, time_t
                return -1;
        }
 
+        if (!_open) {
+               warning << string_compose (_("attempt to set BWF info for an un-opened audio file source (%1)"), _path) << endmsg;
+               return -1;
+        }
+
        if (!(_flags & Broadcast)) {
                return 0;
        }