mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 07:14:56 +01:00
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
This commit is contained in:
parent
7d4e03e28e
commit
5c23faaa0d
15 changed files with 275 additions and 178 deletions
|
|
@ -111,7 +111,7 @@ EditNoteDialog::run ()
|
|||
return r;
|
||||
}
|
||||
|
||||
_region_view->start_diff_command (_("edit note"));
|
||||
_region_view->start_note_diff_command (_("edit note"));
|
||||
|
||||
bool had_change = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -1533,6 +1533,7 @@ TrimDrag::start_grab (GdkEvent* event, Gdk::Cursor*)
|
|||
framepos_t const pf = adjusted_current_frame (event);
|
||||
|
||||
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
|
||||
/* Move the contents of the region around without changing the region bounds */
|
||||
_operation = ContentsTrim;
|
||||
Drag::start_grab (event, _editor->cursors()->trimmer);
|
||||
} else {
|
||||
|
|
@ -1691,6 +1692,16 @@ TrimDrag::finished (GdkEvent* event, bool movement_occurred)
|
|||
if (movement_occurred) {
|
||||
motion (event, false);
|
||||
|
||||
/* This must happen before the region's StatefulDiffCommand is created, as it may
|
||||
`correct' (ahem) the region's _start from being negative to being zero. It
|
||||
needs to be zero in the undo record.
|
||||
*/
|
||||
if (_operation == StartTrim) {
|
||||
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
|
||||
i->view->trim_front_ending ();
|
||||
}
|
||||
}
|
||||
|
||||
if (!_editor->selection->selected (_primary)) {
|
||||
_primary->thaw_after_trim ();
|
||||
} else {
|
||||
|
|
@ -1709,7 +1720,6 @@ TrimDrag::finished (GdkEvent* event, bool movement_occurred)
|
|||
}
|
||||
|
||||
_editor->motion_frozen_playlists.clear ();
|
||||
|
||||
if (_have_transaction) {
|
||||
_editor->commit_reversible_command();
|
||||
}
|
||||
|
|
@ -1723,6 +1733,7 @@ TrimDrag::finished (GdkEvent* event, bool movement_occurred)
|
|||
if (_operation == StartTrim) {
|
||||
i->view->trim_front_ending ();
|
||||
}
|
||||
|
||||
i->view->region()->resume_property_changes ();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &
|
|||
, _custom_device_mode(string())
|
||||
, _active_notes(0)
|
||||
, _note_group(new ArdourCanvas::Group(*group))
|
||||
, _diff_command(0)
|
||||
, _note_diff_command (0)
|
||||
, _ghost_note(0)
|
||||
, _drag_rect (0)
|
||||
, _step_edit_cursor (0)
|
||||
|
|
@ -121,7 +121,7 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &
|
|||
, _custom_device_mode(string())
|
||||
, _active_notes(0)
|
||||
, _note_group(new ArdourCanvas::Group(*parent))
|
||||
, _diff_command(0)
|
||||
, _note_diff_command (0)
|
||||
, _ghost_note(0)
|
||||
, _drag_rect (0)
|
||||
, _step_edit_cursor (0)
|
||||
|
|
@ -152,7 +152,7 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other)
|
|||
, _custom_device_mode(string())
|
||||
, _active_notes(0)
|
||||
, _note_group(new ArdourCanvas::Group(*get_canvas_group()))
|
||||
, _diff_command(0)
|
||||
, _note_diff_command (0)
|
||||
, _ghost_note(0)
|
||||
, _drag_rect (0)
|
||||
, _step_edit_cursor (0)
|
||||
|
|
@ -185,7 +185,7 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other, boost::shared_ptr<M
|
|||
, _custom_device_mode(string())
|
||||
, _active_notes(0)
|
||||
, _note_group(new ArdourCanvas::Group(*get_canvas_group()))
|
||||
, _diff_command(0)
|
||||
, _note_diff_command (0)
|
||||
, _ghost_note(0)
|
||||
, _drag_rect (0)
|
||||
, _step_edit_cursor (0)
|
||||
|
|
@ -774,8 +774,8 @@ MidiRegionView::create_note_at(double x, double y, double length, bool sh)
|
|||
|
||||
view->update_note_range(new_note->note());
|
||||
|
||||
MidiModel::DiffCommand* cmd = _model->new_diff_command("add note");
|
||||
cmd->add(new_note);
|
||||
MidiModel::NoteDiffCommand* cmd = _model->new_note_diff_command("add note");
|
||||
cmd->add (new_note);
|
||||
_model->apply_command(*trackview.session(), cmd);
|
||||
|
||||
play_midi_note (new_note);
|
||||
|
|
@ -819,18 +819,18 @@ MidiRegionView::display_model(boost::shared_ptr<MidiModel> model)
|
|||
}
|
||||
|
||||
void
|
||||
MidiRegionView::start_diff_command(string name)
|
||||
MidiRegionView::start_note_diff_command (string name)
|
||||
{
|
||||
if (!_diff_command) {
|
||||
_diff_command = _model->new_diff_command(name);
|
||||
if (!_note_diff_command) {
|
||||
_note_diff_command = _model->new_note_diff_command (name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MidiRegionView::diff_add_note(const boost::shared_ptr<NoteType> note, bool selected, bool show_velocity)
|
||||
MidiRegionView::note_diff_add_note (const boost::shared_ptr<NoteType> note, bool selected, bool show_velocity)
|
||||
{
|
||||
if (_diff_command) {
|
||||
_diff_command->add(note);
|
||||
if (_note_diff_command) {
|
||||
_note_diff_command->add (note);
|
||||
}
|
||||
if (selected) {
|
||||
_marked_for_selection.insert(note);
|
||||
|
|
@ -841,30 +841,30 @@ MidiRegionView::diff_add_note(const boost::shared_ptr<NoteType> note, bool selec
|
|||
}
|
||||
|
||||
void
|
||||
MidiRegionView::diff_remove_note(ArdourCanvas::CanvasNoteEvent* ev)
|
||||
MidiRegionView::note_diff_remove_note (ArdourCanvas::CanvasNoteEvent* ev)
|
||||
{
|
||||
if (_diff_command && ev->note()) {
|
||||
_diff_command->remove(ev->note());
|
||||
if (_note_diff_command && ev->note()) {
|
||||
_note_diff_command->remove(ev->note());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MidiRegionView::diff_add_change (ArdourCanvas::CanvasNoteEvent* ev,
|
||||
MidiModel::DiffCommand::Property property,
|
||||
MidiRegionView::note_diff_add_change (ArdourCanvas::CanvasNoteEvent* ev,
|
||||
MidiModel::NoteDiffCommand::Property property,
|
||||
uint8_t val)
|
||||
{
|
||||
if (_diff_command) {
|
||||
_diff_command->change (ev->note(), property, val);
|
||||
if (_note_diff_command) {
|
||||
_note_diff_command->change (ev->note(), property, val);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MidiRegionView::diff_add_change (ArdourCanvas::CanvasNoteEvent* ev,
|
||||
MidiModel::DiffCommand::Property property,
|
||||
MidiRegionView::note_diff_add_change (ArdourCanvas::CanvasNoteEvent* ev,
|
||||
MidiModel::NoteDiffCommand::Property property,
|
||||
Evoral::MusicalTime val)
|
||||
{
|
||||
if (_diff_command) {
|
||||
_diff_command->change (ev->note(), property, val);
|
||||
if (_note_diff_command) {
|
||||
_note_diff_command->change (ev->note(), property, val);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -873,19 +873,19 @@ MidiRegionView::apply_diff ()
|
|||
{
|
||||
bool add_or_remove;
|
||||
|
||||
if (!_diff_command) {
|
||||
if (!_note_diff_command) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((add_or_remove = _diff_command->adds_or_removes())) {
|
||||
if ((add_or_remove = _note_diff_command->adds_or_removes())) {
|
||||
// Mark all selected notes for selection when model reloads
|
||||
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
|
||||
_marked_for_selection.insert((*i)->note());
|
||||
}
|
||||
}
|
||||
|
||||
_model->apply_command(*trackview.session(), _diff_command);
|
||||
_diff_command = 0;
|
||||
_model->apply_command(*trackview.session(), _note_diff_command);
|
||||
_note_diff_command = 0;
|
||||
midi_view()->midi_track()->playlist_modified();
|
||||
|
||||
if (add_or_remove) {
|
||||
|
|
@ -896,23 +896,23 @@ MidiRegionView::apply_diff ()
|
|||
}
|
||||
|
||||
void
|
||||
MidiRegionView::apply_diff_as_subcommand()
|
||||
MidiRegionView::apply_diff_as_subcommand ()
|
||||
{
|
||||
bool add_or_remove;
|
||||
|
||||
if (!_diff_command) {
|
||||
if (!_note_diff_command) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((add_or_remove = _diff_command->adds_or_removes())) {
|
||||
if ((add_or_remove = _note_diff_command->adds_or_removes())) {
|
||||
// Mark all selected notes for selection when model reloads
|
||||
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
|
||||
_marked_for_selection.insert((*i)->note());
|
||||
}
|
||||
}
|
||||
|
||||
_model->apply_command_as_subcommand(*trackview.session(), _diff_command);
|
||||
_diff_command = 0;
|
||||
_model->apply_command_as_subcommand(*trackview.session(), _note_diff_command);
|
||||
_note_diff_command = 0;
|
||||
midi_view()->midi_track()->playlist_modified();
|
||||
|
||||
if (add_or_remove) {
|
||||
|
|
@ -925,8 +925,8 @@ MidiRegionView::apply_diff_as_subcommand()
|
|||
void
|
||||
MidiRegionView::abort_command()
|
||||
{
|
||||
delete _diff_command;
|
||||
_diff_command = 0;
|
||||
delete _note_diff_command;
|
||||
_note_diff_command = 0;
|
||||
clear_selection();
|
||||
}
|
||||
|
||||
|
|
@ -1177,7 +1177,7 @@ MidiRegionView::~MidiRegionView ()
|
|||
clear_events();
|
||||
|
||||
delete _note_group;
|
||||
delete _diff_command;
|
||||
delete _note_diff_command;
|
||||
delete _step_edit_cursor;
|
||||
delete _temporary_note_group;
|
||||
}
|
||||
|
|
@ -1569,8 +1569,8 @@ MidiRegionView::step_add_note (uint8_t channel, uint8_t number, uint8_t velocity
|
|||
_marked_for_selection.clear ();
|
||||
clear_selection ();
|
||||
|
||||
start_diff_command (_("step add"));
|
||||
diff_add_note (new_note, true, false);
|
||||
start_note_diff_command (_("step add"));
|
||||
note_diff_add_note (new_note, true, false);
|
||||
apply_diff();
|
||||
|
||||
// last_step_edit_note = new_note;
|
||||
|
|
@ -1720,11 +1720,11 @@ MidiRegionView::delete_selection()
|
|||
return;
|
||||
}
|
||||
|
||||
start_diff_command (_("delete selection"));
|
||||
start_note_diff_command (_("delete selection"));
|
||||
|
||||
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
|
||||
if ((*i)->selected()) {
|
||||
_diff_command->remove((*i)->note());
|
||||
_note_diff_command->remove((*i)->note());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1736,8 +1736,8 @@ MidiRegionView::delete_selection()
|
|||
void
|
||||
MidiRegionView::delete_note (boost::shared_ptr<NoteType> n)
|
||||
{
|
||||
start_diff_command (_("delete note"));
|
||||
_diff_command->remove (n);
|
||||
start_note_diff_command (_("delete note"));
|
||||
_note_diff_command->remove (n);
|
||||
apply_diff ();
|
||||
|
||||
trackview.editor().hide_verbose_canvas_cursor ();
|
||||
|
|
@ -2096,7 +2096,7 @@ MidiRegionView::note_dropped(CanvasNoteEvent *, frameoffset_t dt, int8_t dnote)
|
|||
highest_note_difference = highest_note_in_selection - 127;
|
||||
}
|
||||
|
||||
start_diff_command(_("move notes"));
|
||||
start_note_diff_command (_("move notes"));
|
||||
|
||||
for (Selection::iterator i = _selection.begin(); i != _selection.end() ; ++i) {
|
||||
|
||||
|
|
@ -2106,7 +2106,7 @@ MidiRegionView::note_dropped(CanvasNoteEvent *, frameoffset_t dt, int8_t dnote)
|
|||
continue;
|
||||
}
|
||||
|
||||
diff_add_change (*i, MidiModel::DiffCommand::StartTime, new_time);
|
||||
note_diff_add_change (*i, MidiModel::NoteDiffCommand::StartTime, new_time);
|
||||
|
||||
uint8_t original_pitch = (*i)->note()->note();
|
||||
uint8_t new_pitch = original_pitch + dnote - highest_note_difference;
|
||||
|
|
@ -2123,7 +2123,7 @@ MidiRegionView::note_dropped(CanvasNoteEvent *, frameoffset_t dt, int8_t dnote)
|
|||
lowest_note_in_selection = std::min(lowest_note_in_selection, new_pitch);
|
||||
highest_note_in_selection = std::max(highest_note_in_selection, new_pitch);
|
||||
|
||||
diff_add_change (*i, MidiModel::DiffCommand::NoteNumber, new_pitch);
|
||||
note_diff_add_change (*i, MidiModel::NoteDiffCommand::NoteNumber, new_pitch);
|
||||
}
|
||||
|
||||
apply_diff();
|
||||
|
|
@ -2308,7 +2308,7 @@ MidiRegionView::update_resizing (ArdourCanvas::CanvasNote* primary, bool at_fron
|
|||
void
|
||||
MidiRegionView::commit_resizing (ArdourCanvas::CanvasNote* primary, bool at_front, double delta_x, bool relative)
|
||||
{
|
||||
start_diff_command(_("resize notes"));
|
||||
start_note_diff_command (_("resize notes"));
|
||||
|
||||
for (std::vector<NoteResizeData *>::iterator i = _resize_data.begin(); i != _resize_data.end(); ++i) {
|
||||
CanvasNote* canvas_note = (*i)->canvas_note;
|
||||
|
|
@ -2333,14 +2333,14 @@ MidiRegionView::commit_resizing (ArdourCanvas::CanvasNote* primary, bool at_fron
|
|||
current_x = frames_to_beats (current_x);
|
||||
|
||||
if (at_front && current_x < canvas_note->note()->end_time()) {
|
||||
diff_add_change (canvas_note, MidiModel::DiffCommand::StartTime, current_x);
|
||||
note_diff_add_change (canvas_note, MidiModel::NoteDiffCommand::StartTime, current_x);
|
||||
|
||||
double len = canvas_note->note()->time() - current_x;
|
||||
len += canvas_note->note()->length();
|
||||
|
||||
if (len > 0) {
|
||||
/* XXX convert to beats */
|
||||
diff_add_change (canvas_note, MidiModel::DiffCommand::Length, len);
|
||||
note_diff_add_change (canvas_note, MidiModel::NoteDiffCommand::Length, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2349,7 +2349,7 @@ MidiRegionView::commit_resizing (ArdourCanvas::CanvasNote* primary, bool at_fron
|
|||
|
||||
if (len > 0) {
|
||||
/* XXX convert to beats */
|
||||
diff_add_change (canvas_note, MidiModel::DiffCommand::Length, len);
|
||||
note_diff_add_change (canvas_note, MidiModel::NoteDiffCommand::Length, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2364,7 +2364,7 @@ MidiRegionView::commit_resizing (ArdourCanvas::CanvasNote* primary, bool at_fron
|
|||
void
|
||||
MidiRegionView::change_note_channel (CanvasNoteEvent* event, int8_t channel)
|
||||
{
|
||||
diff_add_change (event, MidiModel::DiffCommand::Channel, (uint8_t) channel);
|
||||
note_diff_add_change (event, MidiModel::NoteDiffCommand::Channel, (uint8_t) channel);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -2381,7 +2381,7 @@ MidiRegionView::change_note_velocity(CanvasNoteEvent* event, int8_t velocity, bo
|
|||
|
||||
event->set_selected (event->selected()); // change color
|
||||
|
||||
diff_add_change (event, MidiModel::DiffCommand::Velocity, new_velocity);
|
||||
note_diff_add_change (event, MidiModel::NoteDiffCommand::Velocity, new_velocity);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -2396,7 +2396,7 @@ MidiRegionView::change_note_note (CanvasNoteEvent* event, int8_t note, bool rela
|
|||
}
|
||||
|
||||
clamp_to_0_127 (new_note);
|
||||
diff_add_change (event, MidiModel::DiffCommand::NoteNumber, new_note);
|
||||
note_diff_add_change (event, MidiModel::NoteDiffCommand::NoteNumber, new_note);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -2463,11 +2463,11 @@ MidiRegionView::trim_note (CanvasNoteEvent* event, Evoral::MusicalTime front_del
|
|||
}
|
||||
|
||||
if (change_start) {
|
||||
diff_add_change (event, MidiModel::DiffCommand::StartTime, new_start);
|
||||
note_diff_add_change (event, MidiModel::NoteDiffCommand::StartTime, new_start);
|
||||
}
|
||||
|
||||
if (change_length) {
|
||||
diff_add_change (event, MidiModel::DiffCommand::Length, new_length);
|
||||
note_diff_add_change (event, MidiModel::NoteDiffCommand::Length, new_length);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2490,13 +2490,13 @@ MidiRegionView::change_note_time (CanvasNoteEvent* event, Evoral::MusicalTime de
|
|||
new_time = delta;
|
||||
}
|
||||
|
||||
diff_add_change (event, MidiModel::DiffCommand::StartTime, new_time);
|
||||
note_diff_add_change (event, MidiModel::NoteDiffCommand::StartTime, new_time);
|
||||
}
|
||||
|
||||
void
|
||||
MidiRegionView::change_note_length (CanvasNoteEvent* event, Evoral::MusicalTime t)
|
||||
{
|
||||
diff_add_change (event, MidiModel::DiffCommand::Length, t);
|
||||
note_diff_add_change (event, MidiModel::NoteDiffCommand::Length, t);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -2526,7 +2526,7 @@ MidiRegionView::change_velocities (bool up, bool fine, bool allow_smush)
|
|||
}
|
||||
}
|
||||
|
||||
start_diff_command(_("change velocities"));
|
||||
start_note_diff_command (_("change velocities"));
|
||||
|
||||
for (Selection::iterator i = _selection.begin(); i != _selection.end();) {
|
||||
Selection::iterator next = i;
|
||||
|
|
@ -2579,7 +2579,7 @@ MidiRegionView::transpose (bool up, bool fine, bool allow_smush)
|
|||
}
|
||||
}
|
||||
|
||||
start_diff_command (_("transpose"));
|
||||
start_note_diff_command (_("transpose"));
|
||||
|
||||
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ) {
|
||||
Selection::iterator next = i;
|
||||
|
|
@ -2613,7 +2613,7 @@ MidiRegionView::change_note_lengths (bool fine, bool shorter, Evoral::MusicalTim
|
|||
delta = -delta;
|
||||
}
|
||||
|
||||
start_diff_command (_("change note lengths"));
|
||||
start_note_diff_command (_("change note lengths"));
|
||||
|
||||
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ) {
|
||||
Selection::iterator next = i;
|
||||
|
|
@ -2682,7 +2682,7 @@ MidiRegionView::nudge_notes (bool forward)
|
|||
delta = -delta;
|
||||
}
|
||||
|
||||
start_diff_command (_("nudge"));
|
||||
start_note_diff_command (_("nudge"));
|
||||
|
||||
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ) {
|
||||
Selection::iterator next = i;
|
||||
|
|
@ -2697,9 +2697,9 @@ MidiRegionView::nudge_notes (bool forward)
|
|||
void
|
||||
MidiRegionView::change_channel(uint8_t channel)
|
||||
{
|
||||
start_diff_command(_("change channel"));
|
||||
start_note_diff_command(_("change channel"));
|
||||
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
|
||||
diff_add_change (*i, MidiModel::DiffCommand::Channel, channel);
|
||||
note_diff_add_change (*i, MidiModel::NoteDiffCommand::Channel, channel);
|
||||
}
|
||||
|
||||
apply_diff();
|
||||
|
|
@ -2814,7 +2814,7 @@ MidiRegionView::cut_copy_clear (Editing::CutCopyOp op)
|
|||
|
||||
if (op != Copy) {
|
||||
|
||||
start_diff_command();
|
||||
start_note_diff_command();
|
||||
|
||||
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
|
||||
switch (op) {
|
||||
|
|
@ -2822,7 +2822,7 @@ MidiRegionView::cut_copy_clear (Editing::CutCopyOp op)
|
|||
break;
|
||||
case Cut:
|
||||
case Clear:
|
||||
diff_remove_note (*i);
|
||||
note_diff_remove_note (*i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -2854,7 +2854,7 @@ MidiRegionView::paste (framepos_t pos, float times, const MidiCutBuffer& mcb)
|
|||
return;
|
||||
}
|
||||
|
||||
start_diff_command (_("paste"));
|
||||
start_note_diff_command (_("paste"));
|
||||
|
||||
Evoral::MusicalTime beat_delta;
|
||||
Evoral::MusicalTime paste_pos_beats;
|
||||
|
|
@ -2877,7 +2877,7 @@ MidiRegionView::paste (framepos_t pos, float times, const MidiCutBuffer& mcb)
|
|||
|
||||
/* make all newly added notes selected */
|
||||
|
||||
diff_add_note (copied_note, true);
|
||||
note_diff_add_note (copied_note, true);
|
||||
end_point = copied_note->end_time();
|
||||
}
|
||||
|
||||
|
|
@ -3246,4 +3246,9 @@ MidiRegionView::trim_front_ending ()
|
|||
_note_group->reparent (*group);
|
||||
delete _temporary_note_group;
|
||||
_temporary_note_group = 0;
|
||||
|
||||
if (_region->start() < 0) {
|
||||
/* Trim drag made start time -ve; fix this */
|
||||
midi_region()->fix_negative_start ();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -180,11 +180,11 @@ class MidiRegionView : public RegionView
|
|||
|
||||
void display_model(boost::shared_ptr<ARDOUR::MidiModel> model);
|
||||
|
||||
void start_diff_command(std::string name = "midi edit");
|
||||
void diff_add_change(ArdourCanvas::CanvasNoteEvent* ev, ARDOUR::MidiModel::DiffCommand::Property, uint8_t val);
|
||||
void diff_add_change(ArdourCanvas::CanvasNoteEvent* ev, ARDOUR::MidiModel::DiffCommand::Property, Evoral::MusicalTime val);
|
||||
void diff_add_note(const boost::shared_ptr<NoteType> note, bool selected, bool show_velocity=false);
|
||||
void diff_remove_note(ArdourCanvas::CanvasNoteEvent* ev);
|
||||
void start_note_diff_command (std::string name = "midi edit");
|
||||
void note_diff_add_change (ArdourCanvas::CanvasNoteEvent* ev, ARDOUR::MidiModel::NoteDiffCommand::Property, uint8_t val);
|
||||
void note_diff_add_change (ArdourCanvas::CanvasNoteEvent* ev, ARDOUR::MidiModel::NoteDiffCommand::Property, Evoral::MusicalTime val);
|
||||
void note_diff_add_note (const boost::shared_ptr<NoteType> note, bool selected, bool show_velocity = false);
|
||||
void note_diff_remove_note (ArdourCanvas::CanvasNoteEvent* ev);
|
||||
|
||||
void apply_diff();
|
||||
void apply_diff_as_subcommand();
|
||||
|
|
@ -363,7 +363,7 @@ class MidiRegionView : public RegionView
|
|||
SysExes _sys_exes;
|
||||
ArdourCanvas::CanvasNote** _active_notes;
|
||||
ArdourCanvas::Group* _note_group;
|
||||
ARDOUR::MidiModel::DiffCommand* _diff_command;
|
||||
ARDOUR::MidiModel::NoteDiffCommand* _note_diff_command;
|
||||
ArdourCanvas::CanvasNote* _ghost_note;
|
||||
double _last_ghost_x;
|
||||
double _last_ghost_y;
|
||||
|
|
|
|||
|
|
@ -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,16 +91,11 @@ 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);
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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&);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,49 +89,49 @@ 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,
|
||||
MidiModel::NoteDiffCommand::change (const NotePtr note, Property prop,
|
||||
uint8_t new_value)
|
||||
{
|
||||
NoteChange change;
|
||||
|
|
@ -175,7 +175,7 @@ MidiModel::DiffCommand::change(const NotePtr note, Property prop,
|
|||
}
|
||||
|
||||
void
|
||||
MidiModel::DiffCommand::change(const NotePtr note, Property prop,
|
||||
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 */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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") {
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue