#include "sys_ex.h"
#include "ui_config.h"
-#include "i18n.h"
+#include "pbd/i18n.h"
using namespace ARDOUR;
using namespace PBD;
, _step_edit_cursor_width (1.0)
, _step_edit_cursor_position (0.0)
, _channel_selection_scoped_note (0)
- , _temporary_note_group (0)
, _mouse_state(None)
, _pressed_button(0)
, _sort_needed (true)
, _step_edit_cursor_width (1.0)
, _step_edit_cursor_position (0.0)
, _channel_selection_scoped_note (0)
- , _temporary_note_group (0)
, _mouse_state(None)
, _pressed_button(0)
, _sort_needed (true)
, _step_edit_cursor_width (1.0)
, _step_edit_cursor_position (0.0)
, _channel_selection_scoped_note (0)
- , _temporary_note_group (0)
, _mouse_state(None)
, _pressed_button(0)
, _sort_needed (true)
, _step_edit_cursor_width (1.0)
, _step_edit_cursor_position (0.0)
, _channel_selection_scoped_note (0)
- , _temporary_note_group (0)
, _mouse_state(None)
, _pressed_button(0)
, _sort_needed (true)
}
// Start of note in frames relative to region start
+ uint32_t divisions = 0;
+
if (snap_t) {
framecnt_t grid_frames;
t = snap_frame_to_grid_underneath (t, grid_frames);
+ divisions = trackview.editor().get_grid_music_divisions (0);
}
- const MidiModel::TimeType beat_time = Evoral::Beats (trackview.session()->tempo_map().beat_at_frame (_region->position() + t)
+
+ const MidiModel::TimeType beat_time = Evoral::Beats (trackview.session()->tempo_map().exact_beat_at_frame (_region->position() + t, divisions)
- (mr->beat() - mr->start_beats().to_double()));
const double note = view->y_to_note(y);
const uint8_t chan = mtv->get_channel_for_add();
delete _note_group;
delete _note_diff_command;
delete _step_edit_cursor;
- delete _temporary_note_group;
}
void
what_changed.contains (ARDOUR::Properties::position)) {
_source_relative_time_converter.set_origin_b (_region->position() - _region->start());
}
- /* catch an end trim so we can live update */
+ /* catch end and start trim so we can update the view*/
if (!what_changed.contains (ARDOUR::Properties::start) &&
what_changed.contains (ARDOUR::Properties::length)) {
enable_display (true);
+ } else if (what_changed.contains (ARDOUR::Properties::start) &&
+ what_changed.contains (ARDOUR::Properties::length)) {
+ enable_display (true);
}
}
if (_enable_display) {
redisplay_model();
- }
+ }
for (PatchChanges::iterator x = _patch_changes.begin(); x != _patch_changes.end(); ++x) {
if ((*x)->canvas_item()->width() >= _pixel_width) {
const double x0 = trackview.editor().sample_to_pixel (note_start_frames);
double x1;
const double y0 = 1 + floor(midi_stream_view()->note_to_y(note->note()));
- double y1;/* trim note display to not overlap the end of its region */
+ double y1;
+ /* trim note display to not overlap the end of its region */
if (note->length() > 0) {
Evoral::Beats note_end_time = note->end_time();
if (note->end_time() > mr->start_beats() + mr->length_beats()) {
- note_end_time = mr->length_beats();
+ note_end_time = mr->start_beats() + mr->length_beats();
}
const framepos_t note_end_frames = map.frame_at_beat (_region->beat() - mr->start_beats().to_double()
void
MidiRegionView::update_resizing (NoteBase* primary, bool at_front, double delta_x, bool relative, double snap_delta, bool with_snap)
{
+ TempoMap& tmap (trackview.session()->tempo_map());
bool cursor_set = false;
bool const ensure_snap = trackview.editor().snap_mode () != SnapMagnetic;
sign = -1;
}
- const double snapped_x = (with_snap ? snap_pixel_to_sample (current_x, ensure_snap) : trackview.editor ().pixel_to_sample (current_x));
- Evoral::Beats beats = region_frames_to_region_beats (snapped_x);
- Evoral::Beats len = Evoral::Beats();
+ double snapped_x;
+ uint32_t divisions = 0;
+
+ if (with_snap) {
+ snapped_x = snap_pixel_to_sample (current_x, ensure_snap);
+ divisions = trackview.editor().get_grid_music_divisions (0);
+ } else {
+ snapped_x = trackview.editor ().pixel_to_sample (current_x);
+ }
+ const Evoral::Beats beats = Evoral::Beats (tmap.exact_beat_at_frame (snapped_x + midi_region()->position(), divisions)
+ - midi_region()->beat()) + midi_region()->start_beats();
+
+ Evoral::Beats len = Evoral::Beats();
if (at_front) {
if (beats < canvas_note->note()->end_time()) {
MidiRegionView::commit_resizing (NoteBase* primary, bool at_front, double delta_x, bool relative, double snap_delta, bool with_snap)
{
_note_diff_command = _model->new_note_diff_command (_("resize notes"));
+ TempoMap& tmap (trackview.session()->tempo_map());
/* XX why doesn't snap_pixel_to_sample() handle this properly? */
bool const ensure_snap = trackview.editor().snap_mode () != SnapMagnetic;
sign = -1;
}
+ uint32_t divisions = 0;
/* Convert the new x position to a frame within the source */
framepos_t current_fr;
if (with_snap) {
current_fr = snap_pixel_to_sample (current_x, ensure_snap);
+ divisions = trackview.editor().get_grid_music_divisions (0);
} else {
current_fr = trackview.editor().pixel_to_sample (current_x);
}
/* and then to beats */
- const Evoral::Beats x_beats = region_frames_to_region_beats (current_fr + _region->start());
+ const Evoral::Beats x_beats = Evoral::Beats (tmap.exact_beat_at_frame (current_fr + midi_region()->position(), divisions)
+ - midi_region()->beat()) + midi_region()->start_beats();
if (at_front && x_beats < canvas_note->note()->end_time()) {
note_diff_add_change (canvas_note, MidiModel::NoteDiffCommand::StartTime, x_beats - (sign * snap_delta_beats));
/** This method handles undo */
bool
-MidiRegionView::paste (framepos_t pos, const ::Selection& selection, PasteContext& ctx, const int32_t& sub_num)
+MidiRegionView::paste (framepos_t pos, const ::Selection& selection, PasteContext& ctx, const int32_t sub_num)
{
bool commit = false;
// Paste notes, if available
MidiNoteSelection::const_iterator m = selection.midi_notes.get_nth(ctx.counts.n_notes());
if (m != selection.midi_notes.end()) {
ctx.counts.increase_n_notes();
- if (!(*m)->empty()) { commit = true; }
+ if (!(*m)->empty()) {
+ commit = true;
+ }
paste_internal(pos, ctx.count, ctx.times, **m);
}
const ATracks& atracks = midi_view()->automation_tracks();
for (ATracks::const_iterator a = atracks.begin(); a != atracks.end(); ++a) {
if (a->second->paste(pos, selection, ctx, sub_num)) {
+ if(!commit) {
+ trackview.editor().begin_reversible_command (Operations::paste);
+ }
commit = true;
}
}
/* calculate time in beats relative to start of source */
const Evoral::Beats length = get_grid_beats(unsnapped_frame);
- const Evoral::Beats time = std::max(
+ const uint32_t divisions = editor.get_grid_music_divisions (0);
+
+ Evoral::Beats time = std::max(
Evoral::Beats(),
- absolute_frames_to_source_beats (f + _region->position ()));
+ Evoral::Beats (trackview.session()->tempo_map().exact_beat_at_frame (f + _region->position(), divisions))
+ - (_region->beat() - midi_region()->start_beats().to_double()));
_ghost_note->note()->set_time (time);
_ghost_note->note()->set_length (length);
void
MidiRegionView::trim_front_starting ()
{
- /* Reparent the note group to the region view's parent, so that it doesn't change
- when the region view is trimmed.
+ /* We used to eparent the note group to the region view's parent, so that it didn't change.
+ now we update it.
*/
- _temporary_note_group = new ArdourCanvas::Container (group->parent ());
- _temporary_note_group->move (group->position ());
- _note_group->reparent (_temporary_note_group);
}
void
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 ();
}
- /* until _start is modified on the fly during front trim,
- we have to redisplay the model when a start trim has finished.
- */
- enable_display (true);
}
void
char buf[128];
snprintf (buf, sizeof (buf), "%d %s\nCh %d Vel %d",
(int) note_value,
- name.empty() ? Evoral::midi_note_name (note_value).c_str() : name.c_str(),
+ name.empty() ? ParameterDescriptor::midi_note_name (note_value).c_str() : name.c_str(),
(int) n->channel() + 1,
(int) n->velocity());
MidiRegionView::snap_frame_to_grid_underneath (framepos_t p, framecnt_t& grid_frames) const
{
PublicEditor& editor = trackview.editor ();
- const Evoral::Beats p_beat = region_frames_to_region_beats (p);
const Evoral::Beats grid_beats = get_grid_beats(p);
-
- grid_frames = region_beats_to_region_frames (p_beat + grid_beats) - region_beats_to_region_frames (p_beat);
+ Evoral::Beats p_beat = max (Evoral::Beats(), region_frames_to_region_beats (p));
+ const double rem = fmod (p_beat.to_double(), grid_beats.to_double());
/* Hack so that we always snap to the note that we are over, instead of snapping
to the next one if we're more than halfway through the one we're over.
*/
- if (editor.snap_mode() == SnapNormal && p >= grid_frames / 2) {
- p -= grid_frames / 2;
+ if (editor.snap_mode() == SnapNormal && rem >= grid_beats.to_double() / 2.0) {
+ p_beat -= Evoral::Beats(grid_beats.to_double() / 2.0);
}
- return snap_frame_to_frame (p);
+ const framepos_t snap_me = trackview.session()->tempo_map().frame_at_beat (p_beat.to_double() + _region->beat()) - _region->position();
+
+ return snap_frame_to_frame (snap_me);
}
ChannelMode