virtual void load_model(bool lock=true, bool force_reload=false) = 0;
virtual void destroy_model() = 0;
- /** This must be called with the source lock held whenever the
- * source/model contents have been changed (reset iterators/cache/etc).
- */
- void invalidate();
-
void set_note_mode(NoteMode mode);
boost::shared_ptr<MidiModel> model() { return _model; }
boost::shared_ptr<MidiModel> _model;
bool _writing;
- mutable Evoral::Sequence<Evoral::MusicalTime>::const_iterator _model_iter;
- mutable bool _model_iter_valid;
-
- mutable double _length_beats;
- mutable framepos_t _last_read_end;
+ mutable double _length_beats;
/** The total duration of the current capture. */
framepos_t _capture_length;
/* Update our filtered parameters list after a change to a parameter's AutoState */
boost::shared_ptr<AutomationControl> ac = model()->automation_control (p);
- assert (ac);
-
- if (ac->alist()->automation_state() == Play) {
+ if (!ac || ac->alist()->automation_state() == Play) {
+ /* It should be "impossible" for ac to be NULL, but if it is, don't
+ filter the parameter so events aren't lost. */
_filtered_parameters.erase (p);
} else {
_filtered_parameters.insert (p);
}
-
- /* the source will have an iterator into the model, and that iterator will have been set up
- for a given set of filtered_parameters, so now that we've changed that list we must invalidate
- the iterator.
- */
- Glib::Threads::Mutex::Lock lm (midi_source(0)->mutex());
- midi_source(0)->invalidate ();
}
/** This is called when a trim drag has resulted in a -ve _start time for this region.
MidiSource::MidiSource (Session& s, string name, Source::Flag flags)
: Source(s, DataType::MIDI, name, flags)
, _writing(false)
- , _model_iter_valid(false)
, _length_beats(0.0)
- , _last_read_end(0)
, _capture_length(0)
, _capture_loop_length(0)
{
MidiSource::MidiSource (Session& s, const XMLNode& node)
: Source(s, node)
, _writing(false)
- , _model_iter_valid(false)
, _length_beats(0.0)
- , _last_read_end(0)
, _capture_length(0)
, _capture_loop_length(0)
{
// You're not the boss of me!
}
-void
-MidiSource::invalidate ()
-{
- _model_iter_valid = false;
- _model_iter.invalidate();
-}
-
/** @param filtered A set of parameters whose MIDI messages will not be returned */
framecnt_t
MidiSource::midi_read (Evoral::EventSink<framepos_t>& dst, framepos_t source_start,
source_start, start, cnt, tracker, name()));
if (_model) {
- Evoral::Sequence<double>::const_iterator& i = _model_iter;
-
- // If the cached iterator is invalid, search for the first event past start
- if (_last_read_end == 0 || start != _last_read_end || !_model_iter_valid) {
- DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("*** %1 search for relevant iterator for %1 / %2\n", _name, source_start, start));
- for (i = _model->begin(0, false, filtered); i != _model->end(); ++i) {
- if (converter.to(i->time()) >= start) {
- DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("***\tstop iterator search @ %1\n", i->time()));
- break;
- }
- }
- _model_iter_valid = true;
- } else {
- DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("*** %1 use cachediterator for %1 / %2\n", _name, source_start, start));
- }
-
- _last_read_end = start + cnt;
-
// Read events up to end
- for (; i != _model->end(); ++i) {
+ const double start_beats = converter.from(start);
+ for (Evoral::Sequence<double>::const_iterator i = _model->begin(start_beats, false, filtered);
+ i != _model->end();
+ ++i) {
const framecnt_t time_frames = converter.to(i->time());
if (time_frames < start + cnt) {
/* convert event times to session frames by adding on the source start position in session frames */
const framecnt_t ret = write_unlocked (source, source_start, cnt);
- if (cnt == max_framecnt) {
- _last_read_end = 0;
- } else {
+ if (cnt != max_framecnt) {
_capture_length += cnt;
}