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:
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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 ();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 ()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user