tentative fix for losing (empty) MIDI files. Incomplete because testing shows issues...
authorPaul Davis <paul@linuxaudiosystems.com>
Thu, 28 Aug 2014 18:01:52 +0000 (14:01 -0400)
committerPaul Davis <paul@linuxaudiosystems.com>
Mon, 15 Sep 2014 18:09:12 +0000 (14:09 -0400)
libs/ardour/ardour/source.h
libs/ardour/enums.cc
libs/ardour/session.cc
libs/ardour/smf_source.cc

index 78b3cfaa2110f369f80fc2b336fe996e55f7e30a..afb6430242b7404ce33755d388c0fd4da75dff77 100644 (file)
@@ -47,7 +47,8 @@ class LIBARDOUR_API Source : public SessionObject
                RemovableIfEmpty = 0x10,
                RemoveAtDestroy = 0x20,
                NoPeakFile = 0x40,
-               Destructive = 0x80
+               Destructive = 0x80,
+               Empty = 0x100, /* used for MIDI only */
        };
 
        Source (Session&, DataType type, const std::string& name, Flag flags=Flag(0));
index 9d6d37b5f8d76f871a9ae9f15cb5af87cc3d6af0..78168c2bfde9b127b7fa6c534a6a51162c1f2764 100644 (file)
@@ -443,6 +443,7 @@ setup_enum_writer ()
        REGISTER_CLASS_ENUM (Source, RemoveAtDestroy);
        REGISTER_CLASS_ENUM (Source, NoPeakFile);
        REGISTER_CLASS_ENUM (Source, Destructive);
+       REGISTER_CLASS_ENUM (Source, Empty);
        REGISTER_BITS (_Source_Flag);
 
        REGISTER_ENUM (FadeLinear);
index 5bc609356a6d46b8a0e8ba749a4a43db6e7de3b1..c3710738639f32b3a4a464720ba54a815827a02e 100644 (file)
@@ -3761,7 +3761,11 @@ Session::create_midi_source_by_stealing_name (boost::shared_ptr<Track> track)
                return boost::shared_ptr<MidiSource>();
        }
 
-       const string path = new_midi_source_path (name);
+       /* MIDI files are small, just put them in the first location of the
+          session source search path.
+       */
+
+       const string path = Glib::build_filename (source_search_path (DataType::MIDI).front(), name);
 
        return boost::dynamic_pointer_cast<SMFSource> (
                SourceFactory::createWritable (
index 6ec7c5a78ce8318afc8890ea14df380769b91bbf..59f4c240d95d07b285ff1c8ffc2bcf6655825877 100644 (file)
@@ -72,6 +72,8 @@ SMFSource::SMFSource (Session& s, const string& path, Source::Flag flags)
         assert (!Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
        existence_check ();
 
+       _flags = Source::Flag (_flags | Empty);
+
        /* file is not opened until write */
 
        if (flags & Writable) {
@@ -132,12 +134,23 @@ SMFSource::SMFSource (Session& s, const XMLNode& node, bool must_exist)
                throw failed_constructor ();
        }
 
-       if (init (_path, true)) {
+       /* we expect the file to exist, but if no MIDI data was ever added
+          it will have been removed at last session close. so, we don't
+          require it to exist if it was marked Empty.
+       */
+
+       if (init (_path, !(_flags & Source::Empty))) {
                throw failed_constructor ();
        }
 
-        assert (Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
-       existence_check ();
+       if (!(_flags & Source::Empty)) {
+               assert (Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
+               existence_check ();
+       } else {
+               assert (_flags & Source::Writable);
+               /* file will be opened on write */
+               return;
+       }
 
        if (open(_path)) {
                throw failed_constructor ();
@@ -380,6 +393,7 @@ SMFSource::append_event_unlocked_beats (const Evoral::Event<double>& ev)
 
        Evoral::SMF::append_event_delta(delta_time_ticks, ev.size(), ev.buffer(), event_id);
        _last_ev_time_beats = ev.time();
+       _flags = Source::Flag (_flags & ~Empty);
 }
 
 /** Append an event with a timestamp in frames (framepos_t) */
@@ -426,6 +440,7 @@ SMFSource::append_event_unlocked_frames (const Evoral::Event<framepos_t>& ev, fr
 
        Evoral::SMF::append_event_delta(delta_time_ticks, ev.size(), ev.buffer(), event_id);
        _last_ev_time_frames = ev.time();
+       _flags = Source::Flag (_flags & ~Empty);
 }
 
 XMLNode&
@@ -668,10 +683,12 @@ SMFSource::destroy_model ()
 void
 SMFSource::flush_midi ()
 {
-       if (!writable() || (writable() && !_open)) {
+       if (!writable() || _length_beats == 0.0) {
                return;
        }
 
+       ensure_disk_file ();
+
        Evoral::SMF::end_write ();
        /* data in the file means its no longer removable */
        mark_nonremovable ();
@@ -703,9 +720,6 @@ SMFSource::ensure_disk_file ()
                if (!_open) {
                        open_for_write ();
                }
-
-               /* Flush, which will definitely put something on disk */
-               flush_midi ();
        }
 }