summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorCarl Hetherington <carl@carlh.net>2010-12-09 21:34:46 +0000
committerCarl Hetherington <carl@carlh.net>2010-12-09 21:34:46 +0000
commit5c23faaa0d86b2d1b18d4f03565bad55c410fb7a (patch)
tree673cafb6a98854a4683110e4e89449103403e3cf /libs
parent7d4e03e28e58a9315f163738f35559f57b099d37 (diff)
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
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/ardour/midi_model.h56
-rw-r--r--libs/ardour/ardour/midi_region.h9
-rw-r--r--libs/ardour/ardour/region.h4
-rw-r--r--libs/ardour/enums.cc14
-rw-r--r--libs/ardour/midi_model.cc130
-rw-r--r--libs/ardour/midi_region.cc16
-rw-r--r--libs/ardour/quantize.cc6
-rw-r--r--libs/ardour/region.cc27
-rw-r--r--libs/ardour/session_state.cc8
-rw-r--r--libs/evoral/evoral/Event.hpp3
-rw-r--r--libs/evoral/src/Event.cpp14
11 files changed, 184 insertions, 103 deletions
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<MidiModel> 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<MidiModel> model() const { return _model; }
+
+ protected:
+ boost::shared_ptr<MidiModel> _model;
+ const std::string _name;
+
+ };
+
+ class NoteDiffCommand : public DiffCommand {
+ public:
+
+ NoteDiffCommand (boost::shared_ptr<MidiModel> m, const std::string& name) : DiffCommand (m, name) {}
+ NoteDiffCommand (boost::shared_ptr<MidiModel> m, const XMLNode& node);
+
enum Property {
NoteNumber,
Velocity,
@@ -66,17 +91,12 @@ public:
Channel
};
- DiffCommand (boost::shared_ptr<MidiModel> m, const std::string& name);
- DiffCommand (boost::shared_ptr<MidiModel> 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<MidiModel> model() const { return _model; }
-
+ NoteDiffCommand& operator+= (const NoteDiffCommand& other);
+
private:
- boost::shared_ptr<MidiModel> _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<MidiSource> source);
@@ -151,6 +167,8 @@ public:
boost::shared_ptr<Evoral::Control> 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<MidiModel> model() { return midi_source()->model(); }
boost::shared_ptr<const MidiModel> 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<const MidiRegion>, frameoffset_t offset = 0, bool offset_relative = true);
- private:
framecnt_t _read_at (const SourceList&, Evoral::EventSink<framepos_t>& 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<MidiSource> 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<MidiSource> 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<MidiModel> 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<MidiModel> m, const XMLNode& node)
- : _model(m)
+MidiModel::NoteDiffCommand::NoteDiffCommand (boost::shared_ptr<MidiModel> 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<NotePtr>::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<MidiModel::TimeType>::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<DiffCommand*>(arg);
+ NoteDiffCommand* cmd = static_cast<NoteDiffCommand*>(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<MidiSource> ms = _midi_source.lock ();
assert (ms);
@@ -1165,7 +1164,6 @@ MidiModel::automation_list_automation_state_changed (Evoral::Parameter p, AutoSt
{
boost::shared_ptr<MidiSource> 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<MidiSource> 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<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (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<AutomationList> (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<MidiModel> model, std::vector<Evoral::Sequence<Evoral::MusicalTime>::Notes>& seqs)
{
bool even;
- MidiModel::DiffCommand* cmd = new MidiModel::DiffCommand (model, "quantize");
+ MidiModel::NoteDiffCommand* cmd = new MidiModel::NoteDiffCommand (model, "quantize");
for (std::vector<Evoral::Sequence<Evoral::MusicalTime>::Notes>::iterator s = seqs.begin(); s != seqs.end(); ++s) {
@@ -102,7 +102,7 @@ Quantize::operator () (boost::shared_ptr<MidiModel> model, std::vector<Evoral::S
if (fabs (delta) >= _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<MidiModel> model, std::vector<Evoral::S
new_dur = _end_grid;
}
- cmd->change ((*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<MidiSource> midi_source =
boost::dynamic_pointer_cast<MidiSource, Source>(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<Timestamp>::~Event() {
}
}
+template<typename Timestamp>
+void
+Event<Timestamp>::set_time (Timestamp t)
+{
+ _nominal_time = t;
+}
+
+template<typename Timestamp>
+void
+Event<Timestamp>::set_original_time (Timestamp t)
+{
+ _original_time = t;
+}
+
#endif // EVORAL_EVENT_ALLOC
template class Event<Evoral::MusicalTime>;