From: David Robillard Date: Sun, 7 Oct 2007 07:20:09 +0000 (+0000) Subject: Fix several MIDI timestamp related problems: X-Git-Tag: 3.0-alpha5~4496 X-Git-Url: https://main.carlh.net/gitweb/?a=commitdiff_plain;h=49763a55c9bcbff2cb7844f36df777bbfadab172;p=ardour.git Fix several MIDI timestamp related problems: Fix recording MIDI regions that start at t != 0. Fix display of MIDI events in regions that start at t != 0. Fix recording after relocating an already rec-armed MIDI track. git-svn-id: svn://localhost/ardour2/trunk@2528 d708f5d6-7413-0410-9779-e7cbd77b26cf --- diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index 5defec6413..7dcba64bae 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -90,8 +90,8 @@ MidiRegionView::init (Gdk::Color& basic_color, bool wfd) if (wfd) midi_region()->midi_source(0)->load_model(); - const Meter& m = trackview.session().tempo_map().meter_at(_region->start()); - const Tempo& t = trackview.session().tempo_map().tempo_at(_region->start()); + const Meter& m = trackview.session().tempo_map().meter_at(_region->position()); + const Tempo& t = trackview.session().tempo_map().tempo_at(_region->position()); _default_note_length = m.frames_per_bar(t, trackview.session().frame_rate()) / m.beats_per_bar(); @@ -596,7 +596,7 @@ MidiRegionView::extend_active_notes() * event arrives, to properly display the note. */ void -MidiRegionView::add_note (const Note& note, bool copy_note) +MidiRegionView::add_note(const Note& note, bool copy_note) { assert(note.time() >= 0); //assert(note.time() < _region->length()); diff --git a/gtk2_ardour/midi_streamview.cc b/gtk2_ardour/midi_streamview.cc index 73f14a2e40..a2b4229650 100644 --- a/gtk2_ardour/midi_streamview.cc +++ b/gtk2_ardour/midi_streamview.cc @@ -304,7 +304,7 @@ MidiStreamView::setup_rec_box () jack_nframes_t start = 0; if (rec_regions.size() > 0) { - start = rec_regions.back().first->start() + _trackview.get_diskstream()->get_captured_frames(rec_regions.size()-1); + start = rec_regions.back().first->position() + _trackview.get_diskstream()->get_captured_frames(rec_regions.size()-1); } boost::shared_ptr region (boost::dynamic_pointer_cast @@ -439,22 +439,19 @@ MidiStreamView::update_rec_regions (boost::shared_ptr data, nframes_t nframes_t origlen = region->length(); - //cerr << "MIDI URR: " << start << " * " << dur - // << " (origlen " << origlen << ")" << endl; - if (region == rec_regions.back().first && rec_active) { - if (start >= region->start()) { - - nframes_t nlen = start + dur - region->start(); + if (start >= region->midi_source(0)->timeline_position()) { + + nframes_t nlen = start + dur - region->position(); if (nlen != region->length()) { - + region->freeze (); region->set_position (_trackview.get_diskstream()->get_capture_start_frame(n), this); - region->set_length (nlen, this); + region->set_length (start + dur - region->position(), this); region->thaw ("updated"); - + if (origlen == 1) { /* our special initial length */ iter->second = add_region_view_internal (region, false); @@ -468,14 +465,17 @@ MidiStreamView::update_rec_regions (boost::shared_ptr data, nframes_t /* draw events */ MidiRegionView* mrv = (MidiRegionView*)iter->second; - // FIXME: slow for (size_t i=0; i < data->n_notes(); ++i) { + const Note& note = data->note_at(i); - if (note.time() > start + dur) + + if (note.time() + region->position() < start) + continue; + + if (note.time() + region->position() > start + dur) break; - if (note.time() >= start) - mrv->add_note(note, true); + mrv->add_note(note, true); if (note.duration() > 0 && note.end_time() >= start) mrv->resolve_note(note.note(), note.end_time()); @@ -490,17 +490,16 @@ MidiStreamView::update_rec_regions (boost::shared_ptr data, nframes_t } mrv->extend_active_notes(); - } } } else { - + nframes_t nlen = _trackview.get_diskstream()->get_captured_frames(n); if (nlen != region->length()) { - if (region->source(0)->length() >= region->start() + nlen) { + if (region->source(0)->length() >= region->position() + nlen) { region->freeze (); region->set_position (_trackview.get_diskstream()->get_capture_start_frame(n), this); @@ -537,9 +536,6 @@ MidiStreamView::rec_data_range_ready (jack_nframes_t start, jack_nframes_t dur, boost::shared_ptr src (boost::dynamic_pointer_cast(weak_src.lock())); - //cerr << src.get() << " MIDI READY: " << start << " * " << dur - // << " -- " << data->size() << " events!" << endl; - this->update_rec_regions (src->model(), start, dur); } diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h index 9842ea0060..2a5c94dd68 100644 --- a/libs/ardour/ardour/diskstream.h +++ b/libs/ardour/ardour/diskstream.h @@ -101,6 +101,7 @@ class Diskstream : public SessionObject void set_speed (double); void non_realtime_set_speed (); + virtual void non_realtime_locate (nframes_t location) {}; virtual void playlist_modified (); boost::shared_ptr playlist () { return _playlist; } diff --git a/libs/ardour/ardour/midi_diskstream.h b/libs/ardour/ardour/midi_diskstream.h index 53c7a7e22c..d08f00b72f 100644 --- a/libs/ardour/ardour/midi_diskstream.h +++ b/libs/ardour/ardour/midi_diskstream.h @@ -79,7 +79,6 @@ class MidiDiskstream : public Diskstream int use_copy_playlist (); /* stateful */ - XMLNode& get_state(void); int set_state(const XMLNode& node); @@ -107,6 +106,7 @@ class MidiDiskstream : public Diskstream int rename_write_sources (); void reset_write_sources (bool, bool force = false); void non_realtime_input_change (); + void non_realtime_locate (nframes_t location); protected: int seek (nframes_t which_sample, bool complete_refill = false); diff --git a/libs/ardour/ardour/midi_model.h b/libs/ardour/ardour/midi_model.h index 6337ca8e65..28a747683c 100644 --- a/libs/ardour/ardour/midi_model.h +++ b/libs/ardour/ardour/midi_model.h @@ -69,9 +69,6 @@ public: size_t read (MidiRingBuffer& dst, nframes_t start, nframes_t nframes, nframes_t stamp_offset) const; - /** Resizes vector if necessary (NOT realtime safe) */ - void append(const MidiBuffer& data); - /** Resizes vector if necessary (NOT realtime safe) */ void append(const MidiEvent& ev); diff --git a/libs/ardour/ardour/midi_source.h b/libs/ardour/ardour/midi_source.h index 95d2a38c4e..433e7ceee9 100644 --- a/libs/ardour/ardour/midi_source.h +++ b/libs/ardour/ardour/midi_source.h @@ -54,11 +54,12 @@ class MidiSource : public Source virtual void append_event_unlocked(const MidiEvent& ev) = 0; virtual void mark_for_remove() = 0; - virtual void mark_streaming_midi_write_started (NoteMode mode); + virtual void mark_streaming_midi_write_started (NoteMode mode, nframes_t start_time); virtual void mark_streaming_write_started (); virtual void mark_streaming_write_completed (); - void set_timeline_position (nframes_t when) { _timeline_position = when; } + uint64_t timeline_position () { return _timeline_position; } + void set_timeline_position (nframes_t when) { _timeline_position = when; } virtual void session_saved(); diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 8709fff148..540ad08011 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -1385,6 +1385,7 @@ class Session : public PBD::StatefulDestructible void realtime_stop (bool abort); void non_realtime_start_scrub (); void non_realtime_set_speed (); + void non_realtime_locate (); void non_realtime_stop (bool abort, int entry_request_count, bool& finished); void non_realtime_overwrite (int entry_request_count, bool& finished); void butler_transport_work (); diff --git a/libs/ardour/ardour/smf_source.h b/libs/ardour/ardour/smf_source.h index 302fb15838..bb3950f2ee 100644 --- a/libs/ardour/ardour/smf_source.h +++ b/libs/ardour/ardour/smf_source.h @@ -77,6 +77,7 @@ class SMFSource : public MidiSource { int move_to_trash (const string trash_dir_name); bool is_empty () const; + void mark_streaming_midi_write_started (NoteMode mode, nframes_t start_time); void mark_streaming_write_completed (); void mark_take (string); diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc index 54f4c10698..2b8f70a307 100644 --- a/libs/ardour/midi_diskstream.cc +++ b/libs/ardour/midi_diskstream.cc @@ -137,6 +137,14 @@ MidiDiskstream::~MidiDiskstream () Glib::Mutex::Lock lm (state_lock); } + +void +MidiDiskstream::non_realtime_locate (nframes_t position) +{ + _write_source->set_timeline_position (position); +} + + void MidiDiskstream::non_realtime_input_change () { @@ -1195,7 +1203,7 @@ MidiDiskstream::engage_record_enable () _source_port->request_monitor_input (!(Config->get_auto_input() && rolling)); } - _write_source->mark_streaming_midi_write_started (_note_mode); + _write_source->mark_streaming_midi_write_started (_note_mode, _session.transport_frame()); RecordEnableChanged (); /* EMIT SIGNAL */ } diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc index 7c02f5095f..d7167ed2ec 100644 --- a/libs/ardour/midi_model.cc +++ b/libs/ardour/midi_model.cc @@ -450,30 +450,6 @@ MidiModel::end_write(bool delete_stuck) } -/** Append contents of \a buf to model. NOT realtime safe. - * - * Timestamps of events in \a buf are expected to be relative to - * the start of this model (t=0) and MUST be monotonically increasing - * and MUST be >= the latest event currently in the model. - * - * Events in buf are deep copied. - */ -void -MidiModel::append(const MidiBuffer& buf) -{ - write_lock(); - - assert(_writing); - - for (MidiBuffer::const_iterator i = buf.begin(); i != buf.end(); ++i) { - assert(_notes.empty() || (*i).time() >= _notes.back().time()); - append(*i); - } - - write_unlock(); -} - - /** Append \a in_event to model. NOT realtime safe. * * Timestamps of events in \a buf are expected to be relative to diff --git a/libs/ardour/midi_source.cc b/libs/ardour/midi_source.cc index 4c97bb4e6d..f072c2a7ef 100644 --- a/libs/ardour/midi_source.cc +++ b/libs/ardour/midi_source.cc @@ -131,8 +131,10 @@ MidiSource::file_changed (string path) } void -MidiSource::mark_streaming_midi_write_started (NoteMode mode) +MidiSource::mark_streaming_midi_write_started (NoteMode mode, nframes_t start_frame) { + set_timeline_position(start_frame); // why do I have a feeling this can break somehow... + if (_model) { _model->set_note_mode(mode); _model->start_write(); diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index c122989b68..2776fbf41d 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -238,8 +238,12 @@ Session::butler_transport_work () } } } + + if (post_transport_work & PostTransportLocate) { + non_realtime_locate (); + } - if (post_transport_work & (PostTransportStop|PostTransportLocate)) { + if (post_transport_work & PostTransportStop) { non_realtime_stop (post_transport_work & PostTransportAbort, on_entry, finished); if (!finished) { g_atomic_int_dec_and_test (&butler_should_do_transport_work); @@ -288,6 +292,18 @@ Session::non_realtime_overwrite (int on_entry, bool& finished) } } + +void +Session::non_realtime_locate () +{ + boost::shared_ptr dsl = diskstreams.reader(); + + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { + (*i)->non_realtime_locate (_transport_frame); + } +} + + void Session::non_realtime_stop (bool abort, int on_entry, bool& finished) { diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc index 4ad8f80b4b..3bc53cb538 100644 --- a/libs/ardour/smf_source.cc +++ b/libs/ardour/smf_source.cc @@ -159,7 +159,6 @@ SMFSource::open() _track_size = 4; // Write a tentative header just to pad things out so writing happens in the right spot - set_timeline_position(0); flush_header(); write_footer(); seek_to_end(); @@ -403,7 +402,7 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt) while (true) { bool ret = src.full_peek(sizeof(double), (Byte*)&time); - if (!ret || time > _length + cnt) + if (!ret || time - _timeline_position > _length + cnt) break; ret = src.read_prefix(&time, &size); @@ -423,10 +422,9 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt) assert(time >= _timeline_position); time -= _timeline_position; - assert(time >= _last_ev_time); const MidiEvent ev(time, size, buf); - append_event_unlocked(MidiEvent(ev)); + append_event_unlocked(ev); if (_model) _model->append(ev); @@ -438,7 +436,7 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt) const nframes_t oldlen = _length; update_length(oldlen, cnt); - ViewDataRangeReady (oldlen, cnt); /* EMIT SIGNAL */ + ViewDataRangeReady (_timeline_position + oldlen, cnt); /* EMIT SIGNAL */ return cnt; } @@ -453,6 +451,8 @@ SMFSource::append_event_unlocked(const MidiEvent& ev) } printf("\n");*/ + assert(ev.time() >= 0); + assert(ev.time() >= _last_ev_time); // FIXME: assumes tempo never changes after start @@ -516,6 +516,13 @@ SMFSource::mark_for_remove () _flags = Flag (_flags | RemoveAtDestroy); } +void +SMFSource::mark_streaming_midi_write_started (NoteMode mode, nframes_t start_frame) +{ + MidiSource::mark_streaming_midi_write_started (mode, start_frame); + _last_ev_time = 0; +} + void SMFSource::mark_streaming_write_completed () {