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
This commit is contained in:
David Robillard
2007-10-07 07:20:09 +00:00
parent 7d2efe25ac
commit 49763a55c9
13 changed files with 67 additions and 61 deletions

View File

@@ -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());

View File

@@ -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<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion>
@@ -439,22 +439,19 @@ MidiStreamView::update_rec_regions (boost::shared_ptr<MidiModel> 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<MidiModel> 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<MidiModel> 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<SMFSource> src (boost::dynamic_pointer_cast<SMFSource>(weak_src.lock()));
//cerr << src.get() << " MIDI READY: " << start << " * " << dur
// << " -- " << data->size() << " events!" << endl;
this->update_rec_regions (src->model(), start, dur);
}

View File

@@ -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> playlist () { return _playlist; }

View File

@@ -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);

View File

@@ -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);

View File

@@ -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();

View File

@@ -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 ();

View File

@@ -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);

View File

@@ -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 */
}

View File

@@ -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

View File

@@ -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();

View File

@@ -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<DiskstreamList> 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)
{

View File

@@ -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 ()
{