From 5c23faaa0d86b2d1b18d4f03565bad55c410fb7a Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 9 Dec 2010 21:34:46 +0000 Subject: Allow trim of midi regions to before the start of the source (better, this time). Fixes #3156. git-svn-id: svn://localhost/ardour2/branches/3.0@8229 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/ardour/midi_model.h | 56 +++++++++++------ libs/ardour/ardour/midi_region.h | 9 ++- libs/ardour/ardour/region.h | 4 ++ libs/ardour/enums.cc | 14 ++--- libs/ardour/midi_model.cc | 130 ++++++++++++++++++++++++--------------- libs/ardour/midi_region.cc | 16 ++++- libs/ardour/quantize.cc | 6 +- libs/ardour/region.cc | 27 +++----- libs/ardour/session_state.cc | 8 +-- libs/evoral/evoral/Event.hpp | 3 + libs/evoral/src/Event.cpp | 14 +++++ 11 files changed, 184 insertions(+), 103 deletions(-) (limited to 'libs') diff --git a/libs/ardour/ardour/midi_model.h b/libs/ardour/ardour/midi_model.h index 27ffa4d8a2..69dc452b62 100644 --- a/libs/ardour/ardour/midi_model.h +++ b/libs/ardour/ardour/midi_model.h @@ -58,6 +58,31 @@ public: class DiffCommand : public Command { public: + + DiffCommand (boost::shared_ptr m, const std::string& name); + + const std::string& name () const { return _name; } + + virtual void operator() () = 0; + virtual void undo () = 0; + + virtual int set_state (const XMLNode&, int version) = 0; + virtual XMLNode & get_state () = 0; + + boost::shared_ptr model() const { return _model; } + + protected: + boost::shared_ptr _model; + const std::string _name; + + }; + + class NoteDiffCommand : public DiffCommand { + public: + + NoteDiffCommand (boost::shared_ptr m, const std::string& name) : DiffCommand (m, name) {} + NoteDiffCommand (boost::shared_ptr m, const XMLNode& node); + enum Property { NoteNumber, Velocity, @@ -66,17 +91,12 @@ public: Channel }; - DiffCommand (boost::shared_ptr m, const std::string& name); - DiffCommand (boost::shared_ptr m, const XMLNode& node); - - const std::string& name() const { return _name; } - - void operator()(); - void undo(); + void operator() (); + void undo (); int set_state (const XMLNode&, int version); - XMLNode& get_state (); - + XMLNode & get_state (); + void add (const NotePtr note); void remove (const NotePtr note); void side_effect_remove (const NotePtr note); @@ -88,15 +108,11 @@ public: return !_added_notes.empty() || !_removed_notes.empty(); } - DiffCommand& operator+= (const DiffCommand& other); - boost::shared_ptr model() const { return _model; } - + NoteDiffCommand& operator+= (const NoteDiffCommand& other); + private: - boost::shared_ptr _model; - const std::string _name; - struct NoteChange { - DiffCommand::Property property; + NoteDiffCommand::Property property; NotePtr note; union { uint8_t old_value; @@ -124,9 +140,9 @@ public: NotePtr unmarshal_note(XMLNode *xml_note); }; - MidiModel::DiffCommand* new_diff_command(const std::string name="midi edit"); - void apply_command(Session& session, Command* cmd); - void apply_command_as_subcommand(Session& session, Command* cmd); + MidiModel::NoteDiffCommand* new_note_diff_command (const std::string name="midi edit"); + void apply_command (Session& session, Command* cmd); + void apply_command_as_subcommand (Session& session, Command* cmd); bool sync_to_source (); bool write_to(boost::shared_ptr source); @@ -151,6 +167,8 @@ public: boost::shared_ptr control_factory(const Evoral::Parameter& id); + void insert_silence_at_start (TimeType); + protected: int resolve_overlaps_unlocked (const NotePtr, void* arg = 0); diff --git a/libs/ardour/ardour/midi_region.h b/libs/ardour/ardour/midi_region.h index 853272d349..dae984c331 100644 --- a/libs/ardour/ardour/midi_region.h +++ b/libs/ardour/ardour/midi_region.h @@ -107,13 +107,20 @@ class MidiRegion : public Region boost::shared_ptr model() { return midi_source()->model(); } boost::shared_ptr model() const { return midi_source()->model(); } + void fix_negative_start (); + + protected: + + virtual bool can_trim_start_before_source_start () const { + return true; + } + private: friend class RegionFactory; MidiRegion (const SourceList&); MidiRegion (boost::shared_ptr, frameoffset_t offset = 0, bool offset_relative = true); - private: framecnt_t _read_at (const SourceList&, Evoral::EventSink& dst, framepos_t position, framecnt_t dur, diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h index 3ad61919b1..ed4923bc40 100644 --- a/libs/ardour/ardour/region.h +++ b/libs/ardour/ardour/region.h @@ -315,6 +315,10 @@ class Region /** Constructor for derived types only */ Region (Session& s, framepos_t start, framecnt_t length, const std::string& name, DataType); + virtual bool can_trim_start_before_source_start () const { + return false; + } + protected: void send_change (const PBD::PropertyChange&); void mid_thaw (const PBD::PropertyChange&); diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc index bde6d7a7fe..6f3dff17a9 100644 --- a/libs/ardour/enums.cc +++ b/libs/ardour/enums.cc @@ -112,7 +112,7 @@ setup_enum_writer () Delivery::Role _Delivery_Role; IO::Direction _IO_Direction; MuteMaster::MutePoint _MuteMaster_MutePoint; - MidiModel::DiffCommand::Property _MidiModel_DiffCommand_Property; + MidiModel::NoteDiffCommand::Property _MidiModel_NoteDiffCommand_Property; WaveformScale _WaveformScale; WaveformShape _WaveformShape; QuantizeType _QuantizeType; @@ -525,12 +525,12 @@ setup_enum_writer () REGISTER_CLASS_ENUM (IO, Output); REGISTER (_IO_Direction); - REGISTER_CLASS_ENUM (MidiModel::DiffCommand, NoteNumber); - REGISTER_CLASS_ENUM (MidiModel::DiffCommand, Channel); - REGISTER_CLASS_ENUM (MidiModel::DiffCommand, Velocity); - REGISTER_CLASS_ENUM (MidiModel::DiffCommand, StartTime); - REGISTER_CLASS_ENUM (MidiModel::DiffCommand, Length); - REGISTER (_MidiModel_DiffCommand_Property); + REGISTER_CLASS_ENUM (MidiModel::NoteDiffCommand, NoteNumber); + REGISTER_CLASS_ENUM (MidiModel::NoteDiffCommand, Channel); + REGISTER_CLASS_ENUM (MidiModel::NoteDiffCommand, Velocity); + REGISTER_CLASS_ENUM (MidiModel::NoteDiffCommand, StartTime); + REGISTER_CLASS_ENUM (MidiModel::NoteDiffCommand, Length); + REGISTER (_MidiModel_NoteDiffCommand_Property); REGISTER_ENUM(Linear); REGISTER_ENUM(Logarithmic); diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc index 8fbfde0ee7..e3d31df58d 100644 --- a/libs/ardour/midi_model.cc +++ b/libs/ardour/midi_model.cc @@ -33,6 +33,7 @@ #include "ardour/smf_source.h" #include "ardour/types.h" #include "ardour/session.h" +#include "ardour/midi_automation_list_binder.h" using namespace std; using namespace ARDOUR; @@ -44,20 +45,19 @@ MidiModel::MidiModel (boost::shared_ptr s) set_midi_source (s); } -/** Start a new Diff command. +/** Start a new NoteDiff command. * * This has no side-effects on the model or Session, the returned command * can be held on to for as long as the caller wishes, or discarded without * formality, until apply_command is called and ownership is taken. */ -MidiModel::DiffCommand* -MidiModel::new_diff_command(const string name) +MidiModel::NoteDiffCommand* +MidiModel::new_note_diff_command (const string name) { boost::shared_ptr ms = _midi_source.lock (); assert (ms); - DiffCommand* cmd = new DiffCommand (ms->model(), name); - return cmd; + return new NoteDiffCommand (ms->model(), name); } /** Apply a command. @@ -89,50 +89,50 @@ MidiModel::apply_command_as_subcommand(Session& session, Command* cmd) /************** DIFF COMMAND ********************/ -#define DIFF_COMMAND_ELEMENT "DiffCommand" +#define NOTE_DIFF_COMMAND_ELEMENT "NoteDiffCommand" #define DIFF_NOTES_ELEMENT "ChangedNotes" #define ADDED_NOTES_ELEMENT "AddedNotes" #define REMOVED_NOTES_ELEMENT "RemovedNotes" #define SIDE_EFFECT_REMOVALS_ELEMENT "SideEffectRemovals" MidiModel::DiffCommand::DiffCommand(boost::shared_ptr m, const std::string& name) - : Command(name) - , _model(m) - , _name(name) + : Command (name) + , _model (m) + , _name (name) { assert(_model); } -MidiModel::DiffCommand::DiffCommand(boost::shared_ptr m, const XMLNode& node) - : _model(m) +MidiModel::NoteDiffCommand::NoteDiffCommand (boost::shared_ptr m, const XMLNode& node) + : DiffCommand (m, "") { - assert(_model); - set_state(node, Stateful::loading_state_version); + assert (_model); + set_state (node, Stateful::loading_state_version); } void -MidiModel::DiffCommand::add(const NotePtr note) +MidiModel::NoteDiffCommand::add (const NotePtr note) { _removed_notes.remove(note); _added_notes.push_back(note); } void -MidiModel::DiffCommand::remove(const NotePtr note) +MidiModel::NoteDiffCommand::remove (const NotePtr note) { _added_notes.remove(note); _removed_notes.push_back(note); } void -MidiModel::DiffCommand::side_effect_remove(const NotePtr note) +MidiModel::NoteDiffCommand::side_effect_remove (const NotePtr note) { side_effect_removals.insert (note); } void -MidiModel::DiffCommand::change(const NotePtr note, Property prop, - uint8_t new_value) +MidiModel::NoteDiffCommand::change (const NotePtr note, Property prop, + uint8_t new_value) { NoteChange change; @@ -175,8 +175,8 @@ MidiModel::DiffCommand::change(const NotePtr note, Property prop, } void -MidiModel::DiffCommand::change(const NotePtr note, Property prop, - TimeType new_time) +MidiModel::NoteDiffCommand::change (const NotePtr note, Property prop, + TimeType new_time) { NoteChange change; @@ -184,7 +184,7 @@ MidiModel::DiffCommand::change(const NotePtr note, Property prop, case NoteNumber: case Channel: case Velocity: - fatal << "MidiModel::DiffCommand::change() with time argument called for note, channel or velocity" << endmsg; + fatal << "MidiModel::NoteDiffCommand::change() with time argument called for note, channel or velocity" << endmsg; break; case StartTime: @@ -208,8 +208,8 @@ MidiModel::DiffCommand::change(const NotePtr note, Property prop, _changes.push_back (change); } -MidiModel::DiffCommand& -MidiModel::DiffCommand::operator+= (const DiffCommand& other) +MidiModel::NoteDiffCommand & +MidiModel::NoteDiffCommand::operator+= (const NoteDiffCommand& other) { if (this == &other) { return *this; @@ -228,7 +228,7 @@ MidiModel::DiffCommand::operator+= (const DiffCommand& other) } void -MidiModel::DiffCommand::operator()() +MidiModel::NoteDiffCommand::operator() () { { MidiModel::WriteLock lock(_model->edit_lock()); @@ -293,7 +293,7 @@ MidiModel::DiffCommand::operator()() for (set::iterator i = temporary_removals.begin(); i != temporary_removals.end(); ++i) { - DiffCommand side_effects (model(), "side effects"); + NoteDiffCommand side_effects (model(), "side effects"); _model->add_note_unlocked (*i, &side_effects); *this += side_effects; } @@ -310,7 +310,7 @@ MidiModel::DiffCommand::operator()() } void -MidiModel::DiffCommand::undo() +MidiModel::NoteDiffCommand::undo () { { MidiModel::WriteLock lock(_model->edit_lock()); @@ -377,7 +377,7 @@ MidiModel::DiffCommand::undo() } XMLNode& -MidiModel::DiffCommand::marshal_note(const NotePtr note) +MidiModel::NoteDiffCommand::marshal_note(const NotePtr note) { XMLNode* xml_note = new XMLNode("note"); @@ -421,7 +421,7 @@ MidiModel::DiffCommand::marshal_note(const NotePtr note) } Evoral::Sequence::NotePtr -MidiModel::DiffCommand::unmarshal_note(XMLNode *xml_note) +MidiModel::NoteDiffCommand::unmarshal_note (XMLNode *xml_note) { unsigned int note; XMLProperty* prop; @@ -486,7 +486,7 @@ MidiModel::DiffCommand::unmarshal_note(XMLNode *xml_note) } XMLNode& -MidiModel::DiffCommand::marshal_change(const NoteChange& change) +MidiModel::NoteDiffCommand::marshal_change (const NoteChange& change) { XMLNode* xml_change = new XMLNode("Change"); @@ -521,8 +521,8 @@ MidiModel::DiffCommand::marshal_change(const NoteChange& change) return *xml_change; } -MidiModel::DiffCommand::NoteChange -MidiModel::DiffCommand::unmarshal_change(XMLNode *xml_change) +MidiModel::NoteDiffCommand::NoteChange +MidiModel::NoteDiffCommand::unmarshal_change (XMLNode *xml_change) { XMLProperty* prop; NoteChange change; @@ -584,9 +584,9 @@ MidiModel::DiffCommand::unmarshal_change(XMLNode *xml_change) } int -MidiModel::DiffCommand::set_state(const XMLNode& diff_command, int /*version*/) +MidiModel::NoteDiffCommand::set_state (const XMLNode& diff_command, int /*version*/) { - if (diff_command.name() != string(DIFF_COMMAND_ELEMENT)) { + if (diff_command.name() != string (NOTE_DIFF_COMMAND_ELEMENT)) { return 1; } @@ -597,7 +597,7 @@ MidiModel::DiffCommand::set_state(const XMLNode& diff_command, int /*version*/) if (added_notes) { XMLNodeList notes = added_notes->children(); transform(notes.begin(), notes.end(), back_inserter(_added_notes), - boost::bind (&DiffCommand::unmarshal_note, this, _1)); + boost::bind (&NoteDiffCommand::unmarshal_note, this, _1)); } @@ -608,7 +608,7 @@ MidiModel::DiffCommand::set_state(const XMLNode& diff_command, int /*version*/) if (removed_notes) { XMLNodeList notes = removed_notes->children(); transform(notes.begin(), notes.end(), back_inserter(_removed_notes), - boost::bind (&DiffCommand::unmarshal_note, this, _1)); + boost::bind (&NoteDiffCommand::unmarshal_note, this, _1)); } @@ -621,7 +621,7 @@ MidiModel::DiffCommand::set_state(const XMLNode& diff_command, int /*version*/) if (changed_notes) { XMLNodeList notes = changed_notes->children(); transform (notes.begin(), notes.end(), back_inserter(_changes), - boost::bind (&DiffCommand::unmarshal_change, this, _1)); + boost::bind (&NoteDiffCommand::unmarshal_change, this, _1)); } @@ -642,28 +642,28 @@ MidiModel::DiffCommand::set_state(const XMLNode& diff_command, int /*version*/) } XMLNode& -MidiModel::DiffCommand::get_state () +MidiModel::NoteDiffCommand::get_state () { - XMLNode* diff_command = new XMLNode(DIFF_COMMAND_ELEMENT); + XMLNode* diff_command = new XMLNode (NOTE_DIFF_COMMAND_ELEMENT); diff_command->add_property("midi-source", _model->midi_source()->id().to_s()); XMLNode* changes = diff_command->add_child(DIFF_NOTES_ELEMENT); for_each(_changes.begin(), _changes.end(), boost::bind ( boost::bind (&XMLNode::add_child_nocopy, changes, _1), - boost::bind (&DiffCommand::marshal_change, this, _1))); + boost::bind (&NoteDiffCommand::marshal_change, this, _1))); XMLNode* added_notes = diff_command->add_child(ADDED_NOTES_ELEMENT); for_each(_added_notes.begin(), _added_notes.end(), boost::bind( boost::bind (&XMLNode::add_child_nocopy, added_notes, _1), - boost::bind (&DiffCommand::marshal_note, this, _1))); + boost::bind (&NoteDiffCommand::marshal_note, this, _1))); XMLNode* removed_notes = diff_command->add_child(REMOVED_NOTES_ELEMENT); for_each(_removed_notes.begin(), _removed_notes.end(), boost::bind ( boost::bind (&XMLNode::add_child_nocopy, removed_notes, _1), - boost::bind (&DiffCommand::marshal_note, this, _1))); + boost::bind (&NoteDiffCommand::marshal_note, this, _1))); /* if this command had side-effects, store that state too */ @@ -673,7 +673,7 @@ MidiModel::DiffCommand::get_state () for_each(side_effect_removals.begin(), side_effect_removals.end(), boost::bind ( boost::bind (&XMLNode::add_child_nocopy, side_effect_notes, _1), - boost::bind (&DiffCommand::marshal_note, this, _1))); + boost::bind (&NoteDiffCommand::marshal_note, this, _1))); } return *diff_command; @@ -910,7 +910,7 @@ MidiModel::resolve_overlaps_unlocked (const NotePtr note, void* arg) return 0; } - DiffCommand* cmd = static_cast(arg); + NoteDiffCommand* cmd = static_cast(arg); TimeType sa = note->time(); TimeType ea = note->end_time(); @@ -964,7 +964,7 @@ MidiModel::resolve_overlaps_unlocked (const NotePtr note, void* arg) break; case InsertMergeTruncateExisting: if (cmd) { - cmd->change (*i, DiffCommand::Length, (note->time() - (*i)->time())); + cmd->change (*i, NoteDiffCommand::Length, (note->time() - (*i)->time())); } (*i)->set_length (note->time() - (*i)->time()); break; @@ -976,7 +976,7 @@ MidiModel::resolve_overlaps_unlocked (const NotePtr note, void* arg) break; case InsertMergeExtend: if (cmd) { - cmd->change ((*i), DiffCommand::Length, note->end_time() - (*i)->time()); + cmd->change ((*i), NoteDiffCommand::Length, note->end_time() - (*i)->time()); } (*i)->set_length (note->end_time() - (*i)->time()); return -1; /* do not add the new note */ @@ -1078,14 +1078,14 @@ MidiModel::resolve_overlaps_unlocked (const NotePtr note, void* arg) if (set_note_time) { if (cmd) { - cmd->change (note, DiffCommand::StartTime, note_time); + cmd->change (note, NoteDiffCommand::StartTime, note_time); } note->set_time (note_time); } if (set_note_length) { if (cmd) { - cmd->change (note, DiffCommand::Length, note_length); + cmd->change (note, NoteDiffCommand::Length, note_length); } note->set_length (note_length); } @@ -1097,7 +1097,6 @@ InsertMergePolicy MidiModel::insert_merge_policy () const { /* XXX ultimately this should be a per-track or even per-model policy */ - boost::shared_ptr ms = _midi_source.lock (); assert (ms); @@ -1165,7 +1164,6 @@ MidiModel::automation_list_automation_state_changed (Evoral::Parameter p, AutoSt { boost::shared_ptr ms = _midi_source.lock (); assert (ms); - ms->set_automation_state_of (p, s); } @@ -1196,3 +1194,37 @@ MidiModel::midi_source () { return _midi_source.lock (); } + +/** Moves notes, controllers and sys-ex to insert silence at the start of the model. + * Adds commands to the session's current undo stack to reflect the movements. + */ +void +MidiModel::insert_silence_at_start (TimeType t) +{ + /* Notes */ + + NoteDiffCommand* c = new_note_diff_command ("insert silence"); + + for (Notes::const_iterator i = notes().begin(); i != notes().end(); ++i) { + c->change (*i, NoteDiffCommand::StartTime, (*i)->time() + t); + } + + boost::shared_ptr s = _midi_source.lock (); + assert (s); + + apply_command_as_subcommand (s->session(), c); + + /* Controllers */ + + for (Controls::iterator i = controls().begin(); i != controls().end(); ++i) { + boost::shared_ptr ac = boost::dynamic_pointer_cast (i->second); + XMLNode& before = ac->alist()->get_state (); + i->second->list()->shift (0, t); + XMLNode& after = ac->alist()->get_state (); + s->session().add_command (new MementoCommand (new MidiAutomationListBinder (s, i->first), &before, &after)); + } + + /* Sys-ex */ + + /* XXX */ +} diff --git a/libs/ardour/midi_region.cc b/libs/ardour/midi_region.cc index f9fb791bad..26d43ba2a9 100644 --- a/libs/ardour/midi_region.cc +++ b/libs/ardour/midi_region.cc @@ -121,7 +121,7 @@ MidiRegion::set_position_internal (framepos_t pos, bool allow_bbt_recompute) BeatsFramesConverter old_converter(_session.tempo_map(), _position - _start); double length_beats = old_converter.from(_length); - Region::set_position_internal(pos, allow_bbt_recompute); + Region::set_position_internal (pos, allow_bbt_recompute); BeatsFramesConverter new_converter(_session.tempo_map(), pos - _start); @@ -306,9 +306,21 @@ MidiRegion::model_automation_state_changed (Evoral::Parameter const & p) } /* the source will have an iterator into the model, and that iterator will have been set up - for a given set of filtered_paramters, so now that we've changed that list we must invalidate + for a given set of filtered_parameters, so now that we've changed that list we must invalidate the iterator. */ Glib::Mutex::Lock lm (midi_source(0)->mutex()); midi_source(0)->invalidate (); } + +/** This is called when a trim drag has resulted in a -ve _start time for this region. + * Fix it up by adding some empty space to the source. + */ +void +MidiRegion::fix_negative_start () +{ + BeatsFramesConverter c (_session.tempo_map(), _position); + + model()->insert_silence_at_start (c.from (-_start)); + _start = 0; +} diff --git a/libs/ardour/quantize.cc b/libs/ardour/quantize.cc index 97be158bad..db2cbb1d21 100644 --- a/libs/ardour/quantize.cc +++ b/libs/ardour/quantize.cc @@ -63,7 +63,7 @@ Command* Quantize::operator () (boost::shared_ptr model, std::vector::Notes>& seqs) { bool even; - MidiModel::DiffCommand* cmd = new MidiModel::DiffCommand (model, "quantize"); + MidiModel::NoteDiffCommand* cmd = new MidiModel::NoteDiffCommand (model, "quantize"); for (std::vector::Notes>::iterator s = seqs.begin(); s != seqs.end(); ++s) { @@ -102,7 +102,7 @@ Quantize::operator () (boost::shared_ptr model, std::vector= _threshold) { if (_snap_start) { delta *= _strength; - cmd->change ((*i), MidiModel::DiffCommand::StartTime, + cmd->change ((*i), MidiModel::NoteDiffCommand::StartTime, (*i)->time() + delta); } } @@ -117,7 +117,7 @@ Quantize::operator () (boost::shared_ptr model, std::vectorchange ((*i), MidiModel::DiffCommand::Length, new_dur); + cmd->change ((*i), MidiModel::NoteDiffCommand::Length, new_dur); } } diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc index 5c25d34c60..585689a656 100644 --- a/libs/ardour/region.cc +++ b/libs/ardour/region.cc @@ -732,13 +732,7 @@ Region::trim_start (framepos_t new_position, void */*src*/) return; } framepos_t new_start; - frameoffset_t start_shift; - - if (new_position > _position) { - start_shift = new_position - _position; - } else { - start_shift = -(_position - new_position); - } + frameoffset_t const start_shift = new_position - _position; if (start_shift > 0) { @@ -759,6 +753,7 @@ Region::trim_start (framepos_t new_position, void */*src*/) } else { new_start = _start + start_shift; } + } else { return; } @@ -813,9 +808,10 @@ Region::modify_front (framepos_t new_position, bool reset_fade, void *src) framecnt_t newlen = 0; framepos_t delta = 0; - /* can't trim it back passed where source position zero is located */ - - new_position = max (new_position, source_zero); + if (!can_trim_start_before_source_start ()) { + /* can't trim it back past where source position zero is located */ + new_position = max (new_position, source_zero); + } if (new_position > _position) { newlen = _length - (new_position - _position); @@ -887,18 +883,13 @@ Region::trim_to (framepos_t position, framecnt_t length, void *src) void Region::trim_to_internal (framepos_t position, framecnt_t length, void */*src*/) { - frameoffset_t start_shift; framepos_t new_start; if (locked()) { return; } - if (position > _position) { - start_shift = position - _position; - } else { - start_shift = -(_position - position); - } + frameoffset_t const start_shift = position - _position; if (start_shift > 0) { @@ -910,7 +901,7 @@ Region::trim_to_internal (framepos_t position, framecnt_t length, void */*src*/) } else if (start_shift < 0) { - if (_start < -start_shift) { + if (_start < -start_shift && !can_trim_start_before_source_start ()) { new_start = 0; } else { new_start = _start + start_shift; @@ -1609,7 +1600,7 @@ Region::can_trim () const ct = CanTrim (ct | FrontTrimLater | EndTrimEarlier); - if (start() != 0) { + if (start() != 0 || can_trim_start_before_source_start ()) { ct = CanTrim (ct | FrontTrimEarlier); } diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index b67de14d07..93245d6d01 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -3186,14 +3186,14 @@ Session::restore_history (string snapshot_name) ut->add_command(c); } - } else if (n->name() == "DiffCommand") { - PBD::ID id(n->property("midi-source")->value()); + } else if (n->name() == "NoteDiffCommand") { + PBD::ID id (n->property("midi-source")->value()); boost::shared_ptr midi_source = boost::dynamic_pointer_cast(source_by_id(id)); if (midi_source) { - ut->add_command(new MidiModel::DiffCommand(midi_source->model(), *n)); + ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n)); } else { - error << _("Failed to downcast MidiSource for DiffCommand") << endmsg; + error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg; } } else if (n->name() == "StatefulDiffCommand") { diff --git a/libs/evoral/evoral/Event.hpp b/libs/evoral/evoral/Event.hpp index 2410b3684a..873572e77c 100644 --- a/libs/evoral/evoral/Event.hpp +++ b/libs/evoral/evoral/Event.hpp @@ -170,6 +170,9 @@ struct Event { inline const uint8_t* buffer() const { return _buf; } inline uint8_t*& buffer() { return _buf; } + void set_time (Time); + void set_original_time (Time); + inline event_id_t id() const { return _id; } inline void set_id (event_id_t n) { _id = n; } diff --git a/libs/evoral/src/Event.cpp b/libs/evoral/src/Event.cpp index 930a18e77b..783634ff24 100644 --- a/libs/evoral/src/Event.cpp +++ b/libs/evoral/src/Event.cpp @@ -90,6 +90,20 @@ Event::~Event() { } } +template +void +Event::set_time (Timestamp t) +{ + _nominal_time = t; +} + +template +void +Event::set_original_time (Timestamp t) +{ + _original_time = t; +} + #endif // EVORAL_EVENT_ALLOC template class Event; -- cgit v1.2.3