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();
* 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());
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>
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);
/* 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());
}
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);
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);
}
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; }
int use_copy_playlist ();
/* stateful */
-
XMLNode& get_state(void);
int set_state(const XMLNode& node);
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);
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);
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();
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 ();
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);
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 ()
{
_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 */
}
}
-/** 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
}
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();
}
}
}
+
+ 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);
}
}
+
+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)
{
_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();
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);
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);
const nframes_t oldlen = _length;
update_length(oldlen, cnt);
- ViewDataRangeReady (oldlen, cnt); /* EMIT SIGNAL */
+ ViewDataRangeReady (_timeline_position + oldlen, cnt); /* EMIT SIGNAL */
return cnt;
}
}
printf("\n");*/
+ assert(ev.time() >= 0);
+
assert(ev.time() >= _last_ev_time);
// FIXME: assumes tempo never changes after start
_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 ()
{