X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fmidi_region.cc;h=dc7293f7b5c1c3cca72e1b2a8070f9f105655a44;hb=499e7907337da36d6d0440c22a2f63e3ada7c439;hp=cff7ab2ed8577da96fd293172b402d12c408e217;hpb=ec12fccf088951c05dfa7c672d759c8ef99a57c2;p=ardour.git diff --git a/libs/ardour/midi_region.cc b/libs/ardour/midi_region.cc index cff7ab2ed8..dc7293f7b5 100644 --- a/libs/ardour/midi_region.cc +++ b/libs/ardour/midi_region.cc @@ -44,6 +44,7 @@ #include "ardour/source_factory.h" #include "ardour/tempo.h" #include "ardour/types.h" +#include "ardour/evoral_types_convert.h" #include "pbd/i18n.h" #include @@ -80,6 +81,7 @@ MidiRegion::MidiRegion (const SourceList& srcs) : Region (srcs) , _start_beats (Properties::start_beats, 0.0) , _length_beats (Properties::length_beats, midi_source(0)->length_beats().to_double()) + , _ignore_shift (false) { register_properties (); midi_source(0)->ModelChanged.connect_same_thread (_source_connection, boost::bind (&MidiRegion::model_changed, this)); @@ -92,6 +94,7 @@ MidiRegion::MidiRegion (boost::shared_ptr other) : Region (other) , _start_beats (Properties::start_beats, other->_start_beats) , _length_beats (Properties::length_beats, other->_length_beats) + , _ignore_shift (false) { //update_length_beats (); register_properties (); @@ -102,16 +105,21 @@ MidiRegion::MidiRegion (boost::shared_ptr other) } /** Create a new MidiRegion that is part of an existing one */ -MidiRegion::MidiRegion (boost::shared_ptr other, frameoffset_t offset, const int32_t sub_num) - : Region (other, offset, sub_num) - , _start_beats (Properties::start_beats, 0.0) +MidiRegion::MidiRegion (boost::shared_ptr other, MusicFrame offset) + : Region (other, offset) + , _start_beats (Properties::start_beats, other->_start_beats) , _length_beats (Properties::length_beats, other->_length_beats) + , _ignore_shift (false) { - _start_beats = (_session.tempo_map().exact_qn_at_frame (other->_position + offset, sub_num) - (other->pulse() * 4.0)) + other->_start_beats; - update_length_beats (sub_num); register_properties (); + const double offset_quarter_note = _session.tempo_map().exact_qn_at_frame (other->_position + offset.frame, offset.division) - other->_quarter_note; + if (offset.frame != 0) { + _start_beats = other->_start_beats + offset_quarter_note; + _length_beats = other->_length_beats - offset_quarter_note; + } + assert(_name.val().find("/") == string::npos); midi_source(0)->ModelChanged.connect_same_thread (_source_connection, boost::bind (&MidiRegion::model_changed, this)); model_changed (); @@ -176,10 +184,18 @@ MidiRegion::clone (boost::shared_ptr newsrc) const Evoral::Beats const bend = bfc.from (_start + _length); { + boost::shared_ptr ms = midi_source(0); + Source::Lock lm (ms->mutex()); + + if (!ms->model()) { + ms->load_model (lm); + } + /* Lock our source since we'll be reading from it. write_to() will - take a lock on newsrc. */ - Source::Lock lm (midi_source(0)->mutex()); - if (midi_source(0)->write_to (lm, newsrc, bbegin, bend)) { + take a lock on newsrc. + */ + + if (ms->write_to (lm, newsrc, bbegin, bend)) { return boost::shared_ptr (); } } @@ -191,12 +207,13 @@ MidiRegion::clone (boost::shared_ptr newsrc) const plist.add (Properties::start, _start); plist.add (Properties::start_beats, _start_beats); plist.add (Properties::length, _length); + plist.add (Properties::position, _position); plist.add (Properties::beat, _beat); plist.add (Properties::length_beats, _length_beats); plist.add (Properties::layer, 0); boost::shared_ptr ret (boost::dynamic_pointer_cast (RegionFactory::create (newsrc, plist, true))); - ret->set_pulse (pulse()); + ret->set_quarter_note (quarter_note()); return ret; } @@ -213,10 +230,11 @@ MidiRegion::post_set (const PropertyChange& pc) so disallow (this has been set from XML state anyway). */ if (!_session.loading()) { - /* update non-musically */ update_length_beats (0); } - } else if (pc.contains (Properties::start) && !pc.contains (Properties::start_beats)) { + } + + if (pc.contains (Properties::start) && !pc.contains (Properties::start_beats)) { set_start_beats_from_start_frames (); } } @@ -224,7 +242,9 @@ MidiRegion::post_set (const PropertyChange& pc) void MidiRegion::set_start_beats_from_start_frames () { - _start_beats = (pulse() * 4.0) - _session.tempo_map().quarter_note_at_frame (_position - _start); + if (position_lock_style() == AudioTime) { + _start_beats = quarter_note() - _session.tempo_map().quarter_note_at_frame (_position - _start); + } } void @@ -266,11 +286,10 @@ MidiRegion::update_after_tempo_map_change (bool /* send */) For now, the musical position at the region start is retained, but subsequent events will maintain their beat distance according to the map. */ - _start = _session.tempo_map().frame_at_quarter_note (pulse() * 4.0) - - _session.tempo_map().frame_at_quarter_note ((pulse() * 4.0) - start_beats()); + _start = _session.tempo_map().frames_between_quarter_notes (quarter_note() - start_beats(), quarter_note()); /* _length doesn't change for audio-locked regions. update length_beats to match. */ - _length_beats = _session.tempo_map().quarter_note_at_frame (_position + _length) - _session.tempo_map().quarter_note_at_frame (_position); + _length_beats = _session.tempo_map().quarter_note_at_frame (_position + _length) - quarter_note(); s_and_l.add (Properties::start); s_and_l.add (Properties::length_beats); @@ -282,7 +301,7 @@ MidiRegion::update_after_tempo_map_change (bool /* send */) Region::update_after_tempo_map_change (false); /* _start has now been updated. */ - _length = _session.tempo_map().frame_at_pulse (pulse() + (_length_beats / 4.0)) - _position; + _length = max ((framecnt_t) 1, _session.tempo_map().frames_between_quarter_notes (quarter_note(), quarter_note() + _length_beats)); if (old_start != _start) { s_and_l.add (Properties::start); @@ -300,7 +319,7 @@ MidiRegion::update_after_tempo_map_change (bool /* send */) void MidiRegion::update_length_beats (const int32_t sub_num) { - _length_beats = _session.tempo_map().exact_qn_at_frame (_position + _length, sub_num) - (pulse() * 4.0); + _length_beats = _session.tempo_map().exact_qn_at_frame (_position + _length, sub_num) - quarter_note(); } void @@ -314,8 +333,7 @@ MidiRegion::set_position_internal (framepos_t pos, bool allow_bbt_recompute, con } /* set _start to new position in tempo map */ - _start = _session.tempo_map().frame_at_quarter_note (pulse() * 4.0) - - _session.tempo_map().frame_at_quarter_note ((pulse() * 4.0) - start_beats()); + _start = _session.tempo_map().frames_between_quarter_notes (quarter_note() - start_beats(), quarter_note()); /* in construction from src */ if (_length_beats == 0.0) { @@ -323,12 +341,30 @@ MidiRegion::set_position_internal (framepos_t pos, bool allow_bbt_recompute, con } if (position_lock_style() == AudioTime) { - _length_beats = _session.tempo_map().quarter_note_at_frame (_position + _length) - _session.tempo_map().quarter_note_at_frame (_position); + _length_beats = _session.tempo_map().quarter_note_at_frame (_position + _length) - quarter_note(); + } else { + /* leave _length_beats alone, and change _length to reflect the state of things + at the new position (tempo map may dictate a different number of frames). + */ + Region::set_length_internal (_session.tempo_map().frames_between_quarter_notes (quarter_note(), quarter_note() + length_beats()), sub_num); + } +} + +void +MidiRegion::set_position_music_internal (double qn) +{ + Region::set_position_music_internal (qn); + /* set _start to new position in tempo map */ + _start = _session.tempo_map().frames_between_quarter_notes (quarter_note() - start_beats(), quarter_note()); + + if (position_lock_style() == AudioTime) { + _length_beats = _session.tempo_map().quarter_note_at_frame (_position + _length) - quarter_note(); + } else { /* leave _length_beats alone, and change _length to reflect the state of things at the new position (tempo map may dictate a different number of frames). */ - Region::set_length_internal (_session.tempo_map().frame_at_quarter_note ((pulse() * 4.0) + length_beats()) - _position, sub_num); + _length = _session.tempo_map().frames_between_quarter_notes (quarter_note(), quarter_note() + length_beats()); } } @@ -412,8 +448,7 @@ MidiRegion::_read_at (const SourceList& /*srcs*/, << " _position = " << _position << " _start = " << _start << " intoffset = " << internal_offset - << " pulse = " << pulse() - << " start_pulse = " << start_pulse() + << " quarter_note = " << quarter_note() << " start_beat = " << _start_beats << endl; #endif @@ -431,7 +466,7 @@ MidiRegion::_read_at (const SourceList& /*srcs*/, tracker, filter, _filtered_parameters, - pulse(), + quarter_note(), _start_beats ) != to_read) { return 0; /* "read nothing" */ @@ -451,13 +486,6 @@ MidiRegion::set_state (const XMLNode& node, int version) { int ret = Region::set_state (node, version); - if (ret == 0) { - /* set length beats to the frame (non-musical) */ - if (position_lock_style() == AudioTime) { - update_length_beats (0); - } - } - return ret; } @@ -561,6 +589,27 @@ MidiRegion::model_changed () midi_source()->AutomationStateChanged.connect_same_thread ( _model_connection, boost::bind (&MidiRegion::model_automation_state_changed, this, _1) ); + + model()->ContentsShifted.connect_same_thread (_model_shift_connection, boost::bind (&MidiRegion::model_shifted, this, _1)); +} +void +MidiRegion::model_shifted (double qn_distance) +{ + if (!model()) { + return; + } + + if (!_ignore_shift) { + PropertyChange what_changed; + _start_beats += qn_distance; + framepos_t const new_start = _session.tempo_map().frames_between_quarter_notes (_quarter_note - _start_beats, _quarter_note); + _start = new_start; + what_changed.add (Properties::start); + what_changed.add (Properties::start_beats); + send_change (what_changed); + } else { + _ignore_shift = false; + } } void @@ -596,7 +645,10 @@ MidiRegion::fix_negative_start () { BeatsFramesConverter c (_session.tempo_map(), _position); - model()->insert_silence_at_start (c.from (-_start)); + _ignore_shift = true; + + model()->insert_silence_at_start (Evoral::Beats (- _start_beats)); + _start = 0; _start_beats = 0.0; } @@ -605,9 +657,8 @@ void MidiRegion::set_start_internal (framecnt_t s, const int32_t sub_num) { Region::set_start_internal (s, sub_num); - if (position_lock_style() == AudioTime) { - set_start_beats_from_start_frames (); - } + + set_start_beats_from_start_frames (); } void @@ -631,15 +682,14 @@ MidiRegion::trim_to_internal (framepos_t position, framecnt_t length, const int3 if (_position != position) { const double pos_qn = _session.tempo_map().exact_qn_at_frame (position, sub_num); - const double old_pos_qn = pulse() * 4.0; + const double old_pos_qn = quarter_note(); /* sets _pulse to new position.*/ set_position_internal (position, true, sub_num); what_changed.add (Properties::position); double new_start_qn = start_beats() + (pos_qn - old_pos_qn); - const framepos_t new_start = _session.tempo_map().frame_at_quarter_note (pos_qn) - - _session.tempo_map().frame_at_quarter_note (pos_qn - new_start_qn); + framepos_t new_start = _session.tempo_map().frames_between_quarter_notes (pos_qn - new_start_qn, pos_qn); if (!verify_start_and_length (new_start, length)) { return;