+ boost::shared_ptr<Playlist> pl (playlist());
+
+ if (!pl) {
+ return;
+ }
+
+ const framepos_t old_pos = _position;
+ const framepos_t old_length = _length;
+ const framepos_t old_start = _start;
+
+ PropertyChange s_and_l;
+
+ if (position_lock_style() == AudioTime) {
+ recompute_position_from_lock_style (0);
+
+ /*
+ set _start to new position in tempo map.
+
+ The user probably expects the region contents to maintain audio position as the
+ tempo changes, but AFAICT this requires modifying the src file to use
+ SMPTE timestamps with the current disk read model (?).
+
+ We could arguably use _start to set _start_beats here,
+ resulting in viewport-like behaviour (the contents maintain
+ their musical position while the region is stationary).
+
+ For now, the musical position at the region start is retained, but subsequent events
+ will maintain their beat distance according to the map.
+ */
+ _start = _position - _session.tempo_map().frame_at_pulse (pulse() - (_start_beats.val().to_double() / 4.0));
+
+ /* _length doesn't change for audio-locked regions. update length_beats to match. */
+ _length_beats = Evoral::Beats (_session.tempo_map().quarter_note_at_frame (_position + _length) - _session.tempo_map().quarter_note_at_frame (_position));
+
+ s_and_l.add (Properties::start);
+ s_and_l.add (Properties::length_beats);
+
+ send_change (s_and_l);
+ return;
+ }
+
+ Region::update_after_tempo_map_change (false);
+
+ /* _start has now been updated. */
+ _length = _session.tempo_map().frame_at_pulse (pulse() + (_length_beats.val().to_double() / 4.0)) - _position;
+
+ if (old_start != _start) {
+ s_and_l.add (Properties::start);
+ }
+ if (old_length != _length) {
+ s_and_l.add (Properties::length);
+ }
+ if (old_pos != _position) {
+ s_and_l.add (Properties::position);
+ }
+
+ send_change (s_and_l);
+}
+
+void
+MidiRegion::update_length_beats (const int32_t sub_num)
+{
+ _length_beats = Evoral::Beats (_session.tempo_map().exact_qn_at_frame (_position + _length, sub_num) - (pulse() * 4.0));
+}
+
+void
+MidiRegion::set_position_internal (framepos_t pos, bool allow_bbt_recompute, const int32_t sub_num)
+{
+ Region::set_position_internal (pos, allow_bbt_recompute, sub_num);
+
+ /* don't clobber _start _length and _length_beats if session loading.*/
+ if (!_session.loading()) {
+ return;
+ }
+
+ /* set _start to new position in tempo map */
+ _start = _position - _session.tempo_map().frame_at_pulse (pulse() - (_start_beats.val().to_double() / 4.0));
+
+ /* in construction from src */
+ if (_length_beats == Evoral::Beats()) {
+ update_length_beats (sub_num);
+ }
+
+ if (position_lock_style() == AudioTime) {
+ _length_beats = Evoral::Beats (_session.tempo_map().quarter_note_at_frame (_position + _length) - _session.tempo_map().quarter_note_at_frame (_position));
+ } else {