diff options
-rw-r--r-- | libs/ardour/ardour/midi_diskstream.h | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_source.h | 10 | ||||
-rw-r--r-- | libs/ardour/ardour/smf_source.h | 1 | ||||
-rw-r--r-- | libs/ardour/midi_diskstream.cc | 69 | ||||
-rw-r--r-- | libs/ardour/midi_source.cc | 18 | ||||
-rw-r--r-- | libs/ardour/midi_stretch.cc | 2 | ||||
-rw-r--r-- | libs/ardour/smf_source.cc | 32 | ||||
-rw-r--r-- | libs/evoral/evoral/Sequence.hpp | 9 | ||||
-rw-r--r-- | libs/evoral/src/Sequence.cpp | 19 | ||||
-rw-r--r-- | libs/gtkmm2ext/stateful_button.cc | 1 |
10 files changed, 101 insertions, 61 deletions
diff --git a/libs/ardour/ardour/midi_diskstream.h b/libs/ardour/ardour/midi_diskstream.h index 59f849afd7..b7f3de3887 100644 --- a/libs/ardour/ardour/midi_diskstream.h +++ b/libs/ardour/ardour/midi_diskstream.h @@ -186,7 +186,6 @@ class MidiDiskstream : public Diskstream MidiRingBuffer<framepos_t>* _capture_buf; MidiPort* _source_port; boost::shared_ptr<SMFSource> _write_source; - framepos_t _last_flush_frame; NoteMode _note_mode; volatile gint _frames_written_to_ringbuffer; volatile gint _frames_read_from_ringbuffer; diff --git a/libs/ardour/ardour/midi_source.h b/libs/ardour/ardour/midi_source.h index a7b47efe21..735a38faa5 100644 --- a/libs/ardour/ardour/midi_source.h +++ b/libs/ardour/ardour/midi_source.h @@ -83,6 +83,13 @@ class MidiSource : virtual public Source, public boost::enable_shared_from_this< virtual void mark_streaming_write_completed (); void mark_write_starting_now (); + /* like ::mark_streaming_write_completed() but with more arguments to + * allow control over MIDI-specific behaviour. Expected to be used only + * when recording actual MIDI input, rather then when importing files + * etc. + */ + virtual void mark_midi_streaming_write_completed (Evoral::Sequence<Evoral::MusicalTime>::StuckNoteOption, Evoral::MusicalTime when = 0); + virtual void session_saved(); std::string captured_for() const { return _captured_for; } @@ -91,6 +98,9 @@ class MidiSource : virtual public Source, public boost::enable_shared_from_this< uint32_t read_data_count() const { return _read_data_count; } uint32_t write_data_count() const { return _write_data_count; } + framepos_t last_write_end() const { return _last_write_end; } + void set_last_write_end (framepos_t pos) { _last_write_end = pos; } + static PBD::Signal1<void,MidiSource*> MidiSourceCreated; XMLNode& get_state (); diff --git a/libs/ardour/ardour/smf_source.h b/libs/ardour/ardour/smf_source.h index cf97efe414..eb1bcaca9a 100644 --- a/libs/ardour/ardour/smf_source.h +++ b/libs/ardour/ardour/smf_source.h @@ -56,6 +56,7 @@ public: void mark_streaming_midi_write_started (NoteMode mode); void mark_streaming_write_completed (); + void mark_midi_streaming_write_completed (Evoral::Sequence<Evoral::MusicalTime>::StuckNoteOption, Evoral::MusicalTime when = 0); XMLNode& get_state (); int set_state (const XMLNode&, int version); diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc index 8ccdd9420e..6a75537f9a 100644 --- a/libs/ardour/midi_diskstream.cc +++ b/libs/ardour/midi_diskstream.cc @@ -74,7 +74,6 @@ MidiDiskstream::MidiDiskstream (Session &sess, const string &name, Diskstream::F , _playback_buf(0) , _capture_buf(0) , _source_port(0) - , _last_flush_frame(0) , _note_mode(Sustained) , _frames_written_to_ringbuffer(0) , _frames_read_from_ringbuffer(0) @@ -95,7 +94,6 @@ MidiDiskstream::MidiDiskstream (Session& sess, const XMLNode& node) , _playback_buf(0) , _capture_buf(0) , _source_port(0) - , _last_flush_frame(0) , _note_mode(Sustained) , _frames_written_to_ringbuffer(0) , _frames_read_from_ringbuffer(0) @@ -203,7 +201,9 @@ MidiDiskstream::non_realtime_input_change () seek (_session.transport_frame()); } - _last_flush_frame = _session.transport_frame(); + if (_write_source) { + _write_source->set_last_write_end (_session.transport_frame()); + } } int @@ -861,20 +861,27 @@ MidiDiskstream::do_refill () int MidiDiskstream::do_flush (RunContext /*context*/, bool force_flush) { - uint32_t to_write; - int32_t ret = 0; + framecnt_t to_write; framecnt_t total; + int32_t ret = 0; + + if (!_write_source) { + return 0; + } + + assert (!destructive()); cerr << name() << " flushing to disk, bufspace = " << _capture_buf->read_space() - << " transport @ " << _session.transport_frame() << " last flush @ " << _last_flush_frame + << " transport @ " << _session.transport_frame() << endl; _write_data_count = 0; - total = _session.transport_frame() - _last_flush_frame; + total = _session.transport_frame() - _write_source->last_write_end(); - if (total == 0 || _capture_buf->read_space() == 0 - || (!force_flush && (total < disk_io_chunk_frames && was_recording))) { + if (total == 0 || + _capture_buf->read_space() == 0 || + (!force_flush && (total < disk_io_chunk_frames) && was_recording)) { cerr << "\tFlush shortcut because total = " << total << " capture read space = " << _capture_buf->read_space() << " force flush = " << force_flush @@ -898,35 +905,25 @@ MidiDiskstream::do_flush (RunContext /*context*/, bool force_flush) ret = 1; } - to_write = disk_io_chunk_frames; - - assert(!destructive()); + if (force_flush) { + /* push out everything we have, right now */ + to_write = max_framecnt; + } else { + to_write = disk_io_chunk_frames; + } - if (record_enabled() && - ((_session.transport_frame() - _last_flush_frame > disk_io_chunk_frames) || - force_flush)) { - if ((!_write_source) || _write_source->midi_write (*_capture_buf, get_capture_start_frame (0), to_write) != to_write) { + if (record_enabled() && ((total > disk_io_chunk_frames) || force_flush)) { + if (_write_source->midi_write (*_capture_buf, get_capture_start_frame (0), to_write) != to_write) { error << string_compose(_("MidiDiskstream %1: cannot write to disk"), _id) << endmsg; return -1; - } else { - cerr << "didn't write, _write_source = " << _write_source << endl; - _last_flush_frame = _session.transport_frame(); - } + } } else { cerr << "\tdidn't write to disk because recenabled = " << record_enabled() - << " last flush @ " << _last_flush_frame << " disk io " << disk_io_chunk_frames << " TF @ " << _session.transport_frame() + << " total = " << total << " TF @ " << _session.transport_frame() << " force = " << force_flush << endl; } out: - - if (ret == 0) { - if (_last_flush_frame > _session.transport_frame() || _last_flush_frame < capture_start_frame) { - _last_flush_frame = _session.transport_frame(); - cerr << name() << " set last flush frame to " << _last_flush_frame << endl; - } - } - return ret; } @@ -996,17 +993,17 @@ MidiDiskstream::transport_stopped_wallclock (struct tm& /*when*/, time_t /*twhen _write_source->set_timeline_position (capture_info.front()->start); _write_source->set_captured_for (_name); + /* set length in beats to entire capture length */ + + BeatsFramesConverter converter (_session.tempo_map(), capture_info.front()->start); + const double total_capture_beats = converter.from (total_capture); + _write_source->set_length_beats (total_capture_beats); + /* flush to disk: this step differs from the audio path, where all the data is already on disk. */ - _write_source->mark_streaming_write_completed (); - - /* set length in beats to entire capture length */ - - BeatsFramesConverter converter (_session.tempo_map(), capture_info.front()->start); - const double total_capture_beats = converter.from(total_capture); - _write_source->set_length_beats(total_capture_beats); + _write_source->mark_midi_streaming_write_completed (Evoral::Sequence<Evoral::MusicalTime>::ResolveStuckNotes, total_capture_beats); /* we will want to be able to keep (over)writing the source but we don't want it to be removable. this also differs diff --git a/libs/ardour/midi_source.cc b/libs/ardour/midi_source.cc index 404ac3a73d..42b4518655 100644 --- a/libs/ardour/midi_source.cc +++ b/libs/ardour/midi_source.cc @@ -267,7 +267,13 @@ MidiSource::midi_write (MidiRingBuffer<framepos_t>& source, framepos_t source_st Glib::Mutex::Lock lm (_lock); cerr << "MidiSource calling write unlocked\n"; const framecnt_t ret = write_unlocked (source, source_start, duration); - _last_write_end += duration; + + if (duration == max_framecnt) { + _last_read_end = 0; + } else { + _last_write_end += duration; + } + cerr << name() << " last write end now @ " << _last_write_end << endl; return ret; } @@ -311,15 +317,21 @@ MidiSource::mark_streaming_write_started () } void -MidiSource::mark_streaming_write_completed () +MidiSource::mark_midi_streaming_write_completed (Evoral::Sequence<Evoral::MusicalTime>::StuckNoteOption option, Evoral::MusicalTime end) { if (_model) { - _model->end_write (false); + _model->end_write (option, end); } _writing = false; } +void +MidiSource::mark_streaming_write_completed () +{ + mark_midi_streaming_write_completed (Evoral::Sequence<Evoral::MusicalTime>::DeleteStuckNotes); +} + boost::shared_ptr<MidiSource> MidiSource::clone (Evoral::MusicalTime begin, Evoral::MusicalTime end) { diff --git a/libs/ardour/midi_stretch.cc b/libs/ardour/midi_stretch.cc index 4dfab65fd4..d9ac1403a9 100644 --- a/libs/ardour/midi_stretch.cc +++ b/libs/ardour/midi_stretch.cc @@ -103,7 +103,7 @@ MidiStretch::run (boost::shared_ptr<Region> r, Progress* progress) new_model->append(ev, Evoral::next_event_id()); } - new_model->end_write (); + new_model->end_write (Evoral::Sequence<Evoral::MusicalTime>::DeleteStuckNotes); new_model->set_edited (true); new_src->copy_interpolation_from (src); diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc index 7d90b58859..9e777b6ae5 100644 --- a/libs/ardour/smf_source.cc +++ b/libs/ardour/smf_source.cc @@ -243,16 +243,21 @@ SMFSource::write_unlocked (MidiRingBuffer<framepos_t>& source, framepos_t positi cerr << "SMFSource::write unlocked, begins writing from src buffer with _last_write_end = " << _last_write_end << " dur = " << duration << endl; while (true) { - bool ret = source.peek ((uint8_t*)&time, sizeof (time)); - if (!ret || time > _last_write_end + duration) { - DEBUG_TRACE (DEBUG::MidiIO, string_compose ("SMFSource::write_unlocked: dropping event @ %1 because ret %4 or it is later than %2 + %3\n", - time, _last_write_end, duration, ret)); + bool ret; + + if (!(ret = source.peek ((uint8_t*)&time, sizeof (time)))) { + /* no more events to consider */ break; } - ret = source.read_prefix(&time, &type, &size); - if (!ret) { - cerr << "ERROR: Unable to read event prefix, corrupt MIDI ring buffer" << endl; + if ((duration != max_framecnt) && (time > (_last_write_end + duration))) { + DEBUG_TRACE (DEBUG::MidiIO, string_compose ("SMFSource::write_unlocked: dropping event @ %1 because it is later than %2 + %3\n", + time, _last_write_end, duration)); + break; + } + + if (!(ret = source.read_prefix (&time, &type, &size))) { + error << _("Unable to read event prefix, corrupt MIDI ring buffer") << endmsg; break; } @@ -263,7 +268,7 @@ SMFSource::write_unlocked (MidiRingBuffer<framepos_t>& source, framepos_t positi ret = source.read_contents(size, buf); if (!ret) { - cerr << "ERROR: Read time/size but not buffer, corrupt MIDI ring buffer" << endl; + error << _("Read time/size but not buffer, corrupt MIDI ring buffer") << endmsg; break; } @@ -431,8 +436,14 @@ SMFSource::mark_streaming_midi_write_started (NoteMode mode) void SMFSource::mark_streaming_write_completed () { + mark_midi_streaming_write_completed (Evoral::Sequence<Evoral::MusicalTime>::DeleteStuckNotes); +} + +void +SMFSource::mark_midi_streaming_write_completed (Evoral::Sequence<Evoral::MusicalTime>::StuckNoteOption stuck_notes_option, Evoral::MusicalTime when) +{ Glib::Mutex::Lock lm (_lock); - MidiSource::mark_streaming_write_completed(); + MidiSource::mark_midi_streaming_write_completed (stuck_notes_option, when); if (!writable()) { return; @@ -551,8 +562,7 @@ SMFSource::load_model (bool lock, bool force_reload) have_event_id = false; } - _model->end_write (_length_beats, false, true); - //_model->end_write (false); + _model->end_write (Evoral::Sequence<Evoral::MusicalTime>::ResolveStuckNotes, _length_beats); _model->set_edited (false); _model_iter = _model->begin(); diff --git a/libs/evoral/evoral/Sequence.hpp b/libs/evoral/evoral/Sequence.hpp index 298ef48e52..98d4b190b1 100644 --- a/libs/evoral/evoral/Sequence.hpp +++ b/libs/evoral/evoral/Sequence.hpp @@ -97,7 +97,14 @@ public: void start_write(); bool writing() const { return _writing; } - void end_write (Time when=0, bool delete_stuck=false, bool resolve=false); + + enum StuckNoteOption { + Relax, + DeleteStuckNotes, + ResolveStuckNotes + }; + + void end_write (StuckNoteOption, Time when = 0); void append(const Event<Time>& ev, Evoral::event_id_t evid); diff --git a/libs/evoral/src/Sequence.cpp b/libs/evoral/src/Sequence.cpp index 3d0fe771fb..d1fd64382b 100644 --- a/libs/evoral/src/Sequence.cpp +++ b/libs/evoral/src/Sequence.cpp @@ -623,7 +623,7 @@ Sequence<Time>::start_write() */ template<typename Time> void -Sequence<Time>::end_write (Time when, bool delete_stuck, bool resolve) +Sequence<Time>::end_write (StuckNoteOption option, Time when) { WriteLock lock(write_lock()); @@ -631,11 +631,7 @@ Sequence<Time>::end_write (Time when, bool delete_stuck, bool resolve) return; } - if (resolve) { - assert (!delete_stuck); - } - - DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 : end_write (%2 notes)\n", this, _notes.size())); + DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 : end_write (%2 notes) delete stuck option %3 @ %4\n", this, _notes.size(), option, when)); if (!_percussive) { @@ -643,11 +639,17 @@ Sequence<Time>::end_write (Time when, bool delete_stuck, bool resolve) typename Notes::iterator next = n; ++next; + cerr << "!!!!!!! note length = " << (*n)->length() << endl; + if ((*n)->length() == 0) { - if (delete_stuck) { + switch (option) { + case Relax: + break; + case DeleteStuckNotes: cerr << "WARNING: Stuck note lost: " << (*n)->note() << endl; _notes.erase(n); - } else if (resolve) { + break; + case ResolveStuckNotes: if (when <= (*n)->time()) { cerr << "WARNING: Stuck note resolution - end time @ " << when << " is before note on: " << (**n) << endl; @@ -656,6 +658,7 @@ Sequence<Time>::end_write (Time when, bool delete_stuck, bool resolve) (*n)->set_length (when - (*n)->time()); cerr << "WARNING: resolved note-on with no note-off to generate " << (**n) << endl; } + break; } } diff --git a/libs/gtkmm2ext/stateful_button.cc b/libs/gtkmm2ext/stateful_button.cc index 0548b8392b..3880a1b35c 100644 --- a/libs/gtkmm2ext/stateful_button.cc +++ b/libs/gtkmm2ext/stateful_button.cc @@ -111,6 +111,7 @@ StateButton::avoid_prelight_on_style_changed (const Glib::RefPtr<Gtk::Style>& /* gtk_widget_modify_style (GTK_WIDGET(child->gobj()), rcstyle); } + g_object_unref (rcstyle); style_changing = false; } |