mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-20 05:36:31 +01:00
tentative fix for losing (empty) MIDI files. Incomplete because testing shows issues with some workflows
This commit is contained in:
parent
dbc34ab4da
commit
c96ec968c7
4 changed files with 29 additions and 9 deletions
|
|
@ -47,7 +47,8 @@ class LIBARDOUR_API Source : public SessionObject
|
||||||
RemovableIfEmpty = 0x10,
|
RemovableIfEmpty = 0x10,
|
||||||
RemoveAtDestroy = 0x20,
|
RemoveAtDestroy = 0x20,
|
||||||
NoPeakFile = 0x40,
|
NoPeakFile = 0x40,
|
||||||
Destructive = 0x80
|
Destructive = 0x80,
|
||||||
|
Empty = 0x100, /* used for MIDI only */
|
||||||
};
|
};
|
||||||
|
|
||||||
Source (Session&, DataType type, const std::string& name, Flag flags=Flag(0));
|
Source (Session&, DataType type, const std::string& name, Flag flags=Flag(0));
|
||||||
|
|
|
||||||
|
|
@ -443,6 +443,7 @@ setup_enum_writer ()
|
||||||
REGISTER_CLASS_ENUM (Source, RemoveAtDestroy);
|
REGISTER_CLASS_ENUM (Source, RemoveAtDestroy);
|
||||||
REGISTER_CLASS_ENUM (Source, NoPeakFile);
|
REGISTER_CLASS_ENUM (Source, NoPeakFile);
|
||||||
REGISTER_CLASS_ENUM (Source, Destructive);
|
REGISTER_CLASS_ENUM (Source, Destructive);
|
||||||
|
REGISTER_CLASS_ENUM (Source, Empty);
|
||||||
REGISTER_BITS (_Source_Flag);
|
REGISTER_BITS (_Source_Flag);
|
||||||
|
|
||||||
REGISTER_ENUM (FadeLinear);
|
REGISTER_ENUM (FadeLinear);
|
||||||
|
|
|
||||||
|
|
@ -3761,7 +3761,11 @@ Session::create_midi_source_by_stealing_name (boost::shared_ptr<Track> track)
|
||||||
return boost::shared_ptr<MidiSource>();
|
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> (
|
return boost::dynamic_pointer_cast<SMFSource> (
|
||||||
SourceFactory::createWritable (
|
SourceFactory::createWritable (
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,8 @@ SMFSource::SMFSource (Session& s, const string& path, Source::Flag flags)
|
||||||
assert (!Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
|
assert (!Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
|
||||||
existence_check ();
|
existence_check ();
|
||||||
|
|
||||||
|
_flags = Source::Flag (_flags | Empty);
|
||||||
|
|
||||||
/* file is not opened until write */
|
/* file is not opened until write */
|
||||||
|
|
||||||
if (flags & Writable) {
|
if (flags & Writable) {
|
||||||
|
|
@ -132,12 +134,23 @@ SMFSource::SMFSource (Session& s, const XMLNode& node, bool must_exist)
|
||||||
throw failed_constructor ();
|
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 ();
|
throw failed_constructor ();
|
||||||
}
|
}
|
||||||
|
|
||||||
assert (Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
|
if (!(_flags & Source::Empty)) {
|
||||||
existence_check ();
|
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)) {
|
if (open(_path)) {
|
||||||
throw failed_constructor ();
|
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);
|
Evoral::SMF::append_event_delta(delta_time_ticks, ev.size(), ev.buffer(), event_id);
|
||||||
_last_ev_time_beats = ev.time();
|
_last_ev_time_beats = ev.time();
|
||||||
|
_flags = Source::Flag (_flags & ~Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Append an event with a timestamp in frames (framepos_t) */
|
/** 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);
|
Evoral::SMF::append_event_delta(delta_time_ticks, ev.size(), ev.buffer(), event_id);
|
||||||
_last_ev_time_frames = ev.time();
|
_last_ev_time_frames = ev.time();
|
||||||
|
_flags = Source::Flag (_flags & ~Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
XMLNode&
|
XMLNode&
|
||||||
|
|
@ -668,10 +683,12 @@ SMFSource::destroy_model ()
|
||||||
void
|
void
|
||||||
SMFSource::flush_midi ()
|
SMFSource::flush_midi ()
|
||||||
{
|
{
|
||||||
if (!writable() || (writable() && !_open)) {
|
if (!writable() || _length_beats == 0.0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ensure_disk_file ();
|
||||||
|
|
||||||
Evoral::SMF::end_write ();
|
Evoral::SMF::end_write ();
|
||||||
/* data in the file means its no longer removable */
|
/* data in the file means its no longer removable */
|
||||||
mark_nonremovable ();
|
mark_nonremovable ();
|
||||||
|
|
@ -703,9 +720,6 @@ SMFSource::ensure_disk_file ()
|
||||||
if (!_open) {
|
if (!_open) {
|
||||||
open_for_write ();
|
open_for_write ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Flush, which will definitely put something on disk */
|
|
||||||
flush_midi ();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue