summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornick_m <mainsbridge@gmail.com>2017-01-27 00:41:17 +1100
committernick_m <mainsbridge@gmail.com>2017-02-04 22:57:36 +1100
commit59daffea1d78cb55b35fe19c135cc4ab472bd01d (patch)
tree45e514f2e4f5a1935e360fd4fa3e2475ec217006
parenta21a414615505269bf770ad2358482e698e841af (diff)
rework snap
snap now fills in a struct (MusicFrame) which contins a snapped frame along with a music divisor. this gives useful information wrt magnetic snap which may or may not have rounded to an exact musical position. region position may now be set musically (using quarter notes for now). this patch fixes several problems in the current code: - dragging a list of music-locked regions now maintains correct musical offsets within the list. - splitting regions using magnetic snap works correctly (#7192) - cut drag should now work correctly with magnetic snap. - musical length of split midi regions is no longer frame based.
-rw-r--r--gtk2_ardour/audio_region_view.cc7
-rw-r--r--gtk2_ardour/automation_time_axis.cc10
-rw-r--r--gtk2_ardour/editor.cc143
-rw-r--r--gtk2_ardour/editor.h40
-rw-r--r--gtk2_ardour/editor_canvas.cc10
-rw-r--r--gtk2_ardour/editor_drag.cc385
-rw-r--r--gtk2_ardour/editor_drag.h22
-rw-r--r--gtk2_ardour/editor_keys.cc24
-rw-r--r--gtk2_ardour/editor_mouse.cc18
-rw-r--r--gtk2_ardour/editor_ops.cc122
-rw-r--r--gtk2_ardour/midi_region_view.cc13
-rw-r--r--gtk2_ardour/midi_time_axis.cc8
-rw-r--r--gtk2_ardour/midi_time_axis.h2
-rw-r--r--gtk2_ardour/public_editor.h18
-rw-r--r--gtk2_ardour/region_view.cc9
-rw-r--r--gtk2_ardour/step_editor.cc5
-rw-r--r--gtk2_ardour/tempo_dialog.cc2
-rw-r--r--libs/ardour/ardour/audioregion.h2
-rw-r--r--libs/ardour/ardour/midi_playlist.h1
-rw-r--r--libs/ardour/ardour/midi_region.h3
-rw-r--r--libs/ardour/ardour/playlist.h10
-rw-r--r--libs/ardour/ardour/region.h4
-rw-r--r--libs/ardour/ardour/region_factory.h6
-rw-r--r--libs/ardour/ardour/tempo.h8
-rw-r--r--libs/ardour/ardour/types.h21
-rw-r--r--libs/ardour/audioregion.cc6
-rw-r--r--libs/ardour/midi_playlist.cc76
-rw-r--r--libs/ardour/midi_region.cc34
-rw-r--r--libs/ardour/playlist.cc53
-rw-r--r--libs/ardour/region.cc140
-rw-r--r--libs/ardour/region_factory.cc14
-rw-r--r--libs/ardour/strip_silence.cc2
-rw-r--r--libs/ardour/tempo.cc58
33 files changed, 744 insertions, 532 deletions
diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc
index 177d0d92e0..ed5665ddb1 100644
--- a/gtk2_ardour/audio_region_view.cc
+++ b/gtk2_ardour/audio_region_view.cc
@@ -1347,11 +1347,10 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev, b
/* don't create points that can't be seen */
update_envelope_visibility ();
-
framepos_t rpos = region ()->position ();
- framepos_t fx = trackview.editor().pixel_to_sample (mx) + rpos;
- trackview.editor ().snap_to_with_modifier (fx, ev);
- fx -= rpos;
+ MusicFrame snap_pos (trackview.editor().pixel_to_sample (mx) + rpos, 0);
+ trackview.editor ().snap_to_with_modifier (snap_pos, ev);
+ framepos_t fx = snap_pos.frame - rpos;
if (fx > _region->length()) {
return;
diff --git a/gtk2_ardour/automation_time_axis.cc b/gtk2_ardour/automation_time_axis.cc
index 24d4c13903..2634b87891 100644
--- a/gtk2_ardour/automation_time_axis.cc
+++ b/gtk2_ardour/automation_time_axis.cc
@@ -605,7 +605,7 @@ AutomationTimeAxisView::build_display_menu ()
}
void
-AutomationTimeAxisView::add_automation_event (GdkEvent* event, framepos_t when, double y, bool with_guard_points)
+AutomationTimeAxisView::add_automation_event (GdkEvent* event, framepos_t frame, double y, bool with_guard_points)
{
if (!_line) {
return;
@@ -632,16 +632,18 @@ AutomationTimeAxisView::add_automation_event (GdkEvent* event, framepos_t when,
_line->view_to_model_coord (x, y);
+ MusicFrame when (frame, 0);
_editor.snap_to_with_modifier (when, event);
XMLNode& before = list->get_state();
std::list<Selectable*> results;
- if (list->editor_add (when, y, with_guard_points)) {
+
+ if (list->editor_add (when.frame, y, with_guard_points)) {
XMLNode& after = list->get_state();
_editor.begin_reversible_command (_("add automation event"));
_session->add_command (new MementoCommand<ARDOUR::AutomationList> (*list.get (), &before, &after));
- _line->get_selectables (when, when, 0.0, 1.0, results);
+ _line->get_selectables (when.frame, when.frame, 0.0, 1.0, results);
_editor.get_selection ().set (results);
_editor.commit_reversible_command ();
@@ -650,7 +652,7 @@ AutomationTimeAxisView::add_automation_event (GdkEvent* event, framepos_t when,
}
bool
-AutomationTimeAxisView::paste (framepos_t pos, const Selection& selection, PasteContext& ctx, const int32_t sub_num)
+AutomationTimeAxisView::paste (framepos_t pos, const Selection& selection, PasteContext& ctx, const int32_t divisions)
{
if (_line) {
return paste_one (pos, ctx.count, ctx.times, selection, ctx.counts, ctx.greedy);
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc
index 62ad00a1d9..3ff2d710d0 100644
--- a/gtk2_ardour/editor.cc
+++ b/gtk2_ardour/editor.cc
@@ -2734,7 +2734,7 @@ Editor::trackview_by_y_position (double y, bool trackview_relative_offset) const
* @param event Event to get current key modifier information from, or 0.
*/
void
-Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, RoundMode direction, bool for_mark)
+Editor::snap_to_with_modifier (MusicFrame& start, GdkEvent const * event, RoundMode direction, bool for_mark)
{
if (!_session || !event) {
return;
@@ -2743,6 +2743,8 @@ Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, RoundM
if (ArdourKeyboard::indicates_snap (event->button.state)) {
if (_snap_mode == SnapOff) {
snap_to_internal (start, direction, for_mark);
+ } else {
+ start.set (start.frame, 0);
}
} else {
if (_snap_mode != SnapOff) {
@@ -2750,14 +2752,17 @@ Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, RoundM
} else if (ArdourKeyboard::indicates_snap_delta (event->button.state)) {
/* SnapOff, but we pressed the snap_delta modifier */
snap_to_internal (start, direction, for_mark);
+ } else {
+ start.set (start.frame, 0);
}
}
}
void
-Editor::snap_to (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
+Editor::snap_to (MusicFrame& start, RoundMode direction, bool for_mark, bool ensure_snap)
{
if (!_session || (_snap_mode == SnapOff && !ensure_snap)) {
+ start.set (start.frame, 0);
return;
}
@@ -2765,8 +2770,9 @@ Editor::snap_to (framepos_t& start, RoundMode direction, bool for_mark, bool ens
}
void
-Editor::timecode_snap_to_internal (framepos_t& start, RoundMode direction, bool /*for_mark*/)
+Editor::timecode_snap_to_internal (MusicFrame& pos, RoundMode direction, bool /*for_mark*/)
{
+ framepos_t start = pos.frame;
const framepos_t one_timecode_second = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->samples_per_timecode_frame());
framepos_t one_timecode_minute = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->samples_per_timecode_frame() * 60);
@@ -2828,14 +2834,16 @@ Editor::timecode_snap_to_internal (framepos_t& start, RoundMode direction, bool
fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg;
abort(); /*NOTREACHED*/
}
+
+ pos.set (start, 0);
}
void
-Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
+Editor::snap_to_internal (MusicFrame& start, RoundMode direction, bool for_mark, bool ensure_snap)
{
const framepos_t one_second = _session->frame_rate();
const framepos_t one_minute = _session->frame_rate() * 60;
- framepos_t presnap = start;
+ framepos_t presnap = start.frame;
framepos_t before;
framepos_t after;
@@ -2847,95 +2855,104 @@ Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark,
case SnapToCDFrame:
if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
- start % (one_second/75) == 0) {
+ start.frame % (one_second/75) == 0) {
/* start is already on a whole CD frame, do nothing */
- } else if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
- start = (framepos_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
+ } else if (((direction == 0) && (start.frame % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
+ start.frame = (framepos_t) ceil ((double) start.frame / (one_second / 75)) * (one_second / 75);
} else {
- start = (framepos_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
+ start.frame = (framepos_t) floor ((double) start.frame / (one_second / 75)) * (one_second / 75);
}
+
+ start.set (start.frame, 0);
+
break;
case SnapToSeconds:
if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
- start % one_second == 0) {
+ start.frame % one_second == 0) {
/* start is already on a whole second, do nothing */
- } else if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
- start = (framepos_t) ceil ((double) start / one_second) * one_second;
+ } else if (((direction == 0) && (start.frame % one_second > one_second / 2)) || (direction > 0)) {
+ start.frame = (framepos_t) ceil ((double) start.frame / one_second) * one_second;
} else {
- start = (framepos_t) floor ((double) start / one_second) * one_second;
+ start.frame = (framepos_t) floor ((double) start.frame / one_second) * one_second;
}
+
+ start.set (start.frame, 0);
+
break;
case SnapToMinutes:
if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
- start % one_minute == 0) {
+ start.frame % one_minute == 0) {
/* start is already on a whole minute, do nothing */
- } else if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
- start = (framepos_t) ceil ((double) start / one_minute) * one_minute;
+ } else if (((direction == 0) && (start.frame % one_minute > one_minute / 2)) || (direction > 0)) {
+ start.frame = (framepos_t) ceil ((double) start.frame / one_minute) * one_minute;
} else {
- start = (framepos_t) floor ((double) start / one_minute) * one_minute;
+ start.frame = (framepos_t) floor ((double) start.frame / one_minute) * one_minute;
}
+
+ start.set (start.frame, 0);
+
break;
case SnapToBar:
- start = _session->tempo_map().round_to_bar (start, direction);
+ start = _session->tempo_map().round_to_bar (start.frame, direction);
break;
case SnapToBeat:
- start = _session->tempo_map().round_to_beat (start, direction);
+ start = _session->tempo_map().round_to_beat (start.frame, direction);
break;
case SnapToBeatDiv128:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 128, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 128, direction);
break;
case SnapToBeatDiv64:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 64, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 64, direction);
break;
case SnapToBeatDiv32:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 32, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 32, direction);
break;
case SnapToBeatDiv28:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 28, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 28, direction);
break;
case SnapToBeatDiv24:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 24, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 24, direction);
break;
case SnapToBeatDiv20:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 20, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 20, direction);
break;
case SnapToBeatDiv16:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 16, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 16, direction);
break;
case SnapToBeatDiv14:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 14, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 14, direction);
break;
case SnapToBeatDiv12:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 12, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 12, direction);
break;
case SnapToBeatDiv10:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 10, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 10, direction);
break;
case SnapToBeatDiv8:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 8, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 8, direction);
break;
case SnapToBeatDiv7:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 7, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 7, direction);
break;
case SnapToBeatDiv6:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 6, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 6, direction);
break;
case SnapToBeatDiv5:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 5, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 5, direction);
break;
case SnapToBeatDiv4:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 4, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 4, direction);
break;
case SnapToBeatDiv3:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 3, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 3, direction);
break;
case SnapToBeatDiv2:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 2, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 2, direction);
break;
case SnapToMark:
@@ -2943,29 +2960,31 @@ Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark,
return;
}
- _session->locations()->marks_either_side (start, before, after);
+ _session->locations()->marks_either_side (start.frame, before, after);
if (before == max_framepos && after == max_framepos) {
/* No marks to snap to, so just don't snap */
return;
} else if (before == max_framepos) {
- start = after;
+ start.frame = after;
} else if (after == max_framepos) {
- start = before;
+ start.frame = before;
} else if (before != max_framepos && after != max_framepos) {
if ((direction == RoundUpMaybe || direction == RoundUpAlways))
- start = after;
+ start.frame = after;
else if ((direction == RoundDownMaybe || direction == RoundDownAlways))
- start = before;
+ start.frame = before;
else if (direction == 0 ) {
- if ((start - before) < (after - start)) {
- start = before;
+ if ((start.frame - before) < (after - start.frame)) {
+ start.frame = before;
} else {
- start = after;
+ start.frame = after;
}
}
}
+ start.set (start.frame, 0);
+
break;
case SnapToRegionStart:
@@ -2978,9 +2997,9 @@ Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark,
vector<framepos_t>::iterator next = region_boundary_cache.end ();
if (direction > 0) {
- next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
+ next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start.frame);
} else {
- next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
+ next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start.frame);
}
if (next != region_boundary_cache.begin ()) {
@@ -2991,12 +3010,15 @@ Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark,
framepos_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev;
framepos_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next;
- if (start > (p + n) / 2) {
- start = n;
+ if (start.frame > (p + n) / 2) {
+ start.frame = n;
} else {
- start = p;
+ start.frame = p;
}
}
+
+ start.set (start.frame, 0);
+
break;
}
@@ -3010,21 +3032,20 @@ Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark,
return;
}
- if (presnap > start) {
- if (presnap > (start + pixel_to_sample(snap_threshold))) {
- start = presnap;
+ if (presnap > start.frame) {
+ if (presnap > (start.frame + pixel_to_sample(snap_threshold))) {
+ start.set (presnap, 0);
}
- } else if (presnap < start) {
- if (presnap < (start - pixel_to_sample(snap_threshold))) {
- start = presnap;
+ } else if (presnap < start.frame) {
+ if (presnap < (start.frame - pixel_to_sample(snap_threshold))) {
+ start.set (presnap, 0);
}
}
default:
/* handled at entry */
return;
-
}
}
@@ -4067,9 +4088,9 @@ Editor::get_paste_offset (framepos_t pos, unsigned paste_count, framecnt_t durat
framecnt_t offset = paste_count * duration;
/* snap offset so pos + offset is aligned to the grid */
- framepos_t offset_pos = pos + offset;
+ MusicFrame offset_pos (pos + offset, 0);
snap_to(offset_pos, RoundUpMaybe);
- offset = offset_pos - pos;
+ offset = offset_pos.frame - pos;
return offset;
}
@@ -4740,6 +4761,8 @@ Editor::get_preferred_edit_position (EditIgnoreOption ignore, bool from_context_
ep = EditAtPlayhead;
}
+ MusicFrame snap_mf (0, 0);
+
switch (ep) {
case EditAtPlayhead:
if (_dragging_playhead) {
@@ -4772,7 +4795,9 @@ Editor::get_preferred_edit_position (EditIgnoreOption ignore, bool from_context_
/* XXX not right but what can we do ? */
return 0;
}
- snap_to (where);
+ snap_mf.frame = where;
+ snap_to (snap_mf);
+ where = snap_mf.frame;
DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
break;
}
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index 8ff19580c6..fa5ed9057a 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -452,20 +452,20 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
TrackViewList axis_views_from_routes (boost::shared_ptr<ARDOUR::RouteList>) const;
- void snap_to (framepos_t& first,
- ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
- bool for_mark = false,
- bool ensure_snap = false);
+ void snap_to (ARDOUR::MusicFrame& first,
+ ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
+ bool for_mark = false,
+ bool ensure_snap = false);
- void snap_to_with_modifier (framepos_t& first,
- GdkEvent const * ev,
- ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
- bool for_mark = false);
+ void snap_to_with_modifier (ARDOUR::MusicFrame& first,
+ GdkEvent const * ev,
+ ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
+ bool for_mark = false);
- void snap_to (framepos_t& first,
- framepos_t& last,
- ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
- bool for_mark = false);
+ void snap_to (ARDOUR::MusicFrame& first,
+ ARDOUR::MusicFrame& last,
+ ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
+ bool for_mark = false);
void begin_selection_op_history ();
void begin_reversible_selection_op (std::string cmd_name);
@@ -542,7 +542,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
/* editing operations that need to be public */
void mouse_add_new_marker (framepos_t where, bool is_cd=false);
- void split_regions_at (framepos_t, RegionSelection&, const int32_t sub_num, bool snap = true);
+ void split_regions_at (ARDOUR::MusicFrame, RegionSelection&, bool snap = true);
void split_region_at_points (boost::shared_ptr<ARDOUR::Region>, ARDOUR::AnalysisFeatureList&, bool can_ferret, bool select_new = false);
RegionSelection get_regions_from_selection_and_mouse (framepos_t);
@@ -2152,14 +2152,14 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void select_next_route ();
void select_prev_route ();
- void snap_to_internal (framepos_t& first,
- ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
- bool for_mark = false,
- bool ensure_snap = false);
+ void snap_to_internal (ARDOUR::MusicFrame& first,
+ ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
+ bool for_mark = false,
+ bool ensure_snap = false);
- void timecode_snap_to_internal (framepos_t& first,
- ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
- bool for_mark = false);
+ void timecode_snap_to_internal (ARDOUR::MusicFrame& first,
+ ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
+ bool for_mark = false);
RhythmFerret* rhythm_ferret;
diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc
index bc457453bc..f847a3f707 100644
--- a/gtk2_ardour/editor_canvas.cc
+++ b/gtk2_ardour/editor_canvas.cc
@@ -449,7 +449,6 @@ Editor::drop_paths (const RefPtr<Gdk::DragContext>& context,
{
vector<string> paths;
GdkEvent ev;
- framepos_t frame;
double cy;
if (convert_drop_to_paths (paths, context, x, y, data, info, time) == 0) {
@@ -461,9 +460,8 @@ Editor::drop_paths (const RefPtr<Gdk::DragContext>& context,
ev.button.x = x;
ev.button.y = y;
- frame = window_event_sample (&ev, 0, &cy);
-
- snap_to (frame);
+ MusicFrame when (window_event_sample (&ev, 0, &cy), 0);
+ snap_to (when);
bool copy = ((context->get_actions() & (Gdk::ACTION_COPY | Gdk::ACTION_LINK | Gdk::ACTION_MOVE)) == Gdk::ACTION_COPY);
#ifdef __APPLE__
@@ -471,9 +469,9 @@ Editor::drop_paths (const RefPtr<Gdk::DragContext>& context,
the main event loop with GTK/Quartz. Since import/embed wants
to push up a progress dialog, defer all this till we go idle.
*/
- Glib::signal_idle().connect (sigc::bind (sigc::mem_fun (*this, &Editor::idle_drop_paths), paths, frame, cy, copy));
+ Glib::signal_idle().connect (sigc::bind (sigc::mem_fun (*this, &Editor::idle_drop_paths), paths, when.frame, cy, copy));
#else
- drop_paths_part_two (paths, frame, cy, copy);
+ drop_paths_part_two (paths, when.frame, cy, copy);
#endif
}
diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc
index 9e763ff264..de3be07c8d 100644
--- a/gtk2_ardour/editor_drag.cc
+++ b/gtk2_ardour/editor_drag.cc
@@ -237,7 +237,7 @@ Drag::Drag (Editor* e, ArdourCanvas::Item* i, bool trackview_only)
, _raw_grab_frame (0)
, _grab_frame (0)
, _last_pointer_frame (0)
- , _snap_delta (0)
+ , _snap_delta (0, 0)
, _constraint_pressed (false)
{
@@ -268,7 +268,7 @@ Drag::start_grab (GdkEvent* event, Gdk::Cursor *cursor)
_raw_grab_frame = _editor->canvas_event_sample (event, &_grab_x, &_grab_y);
setup_pointer_frame_offset ();
- _grab_frame = adjusted_frame (_raw_grab_frame, event);
+ _grab_frame = adjusted_frame (_raw_grab_frame, event).frame;
_last_pointer_frame = _grab_frame;
_last_pointer_x = _grab_x;
@@ -324,13 +324,13 @@ Drag::end_grab (GdkEvent* event)
return _move_threshold_passed;
}
-framepos_t
+MusicFrame
Drag::adjusted_frame (framepos_t f, GdkEvent const * event, bool snap) const
{
- framepos_t pos = 0;
+ MusicFrame pos (f, 0);
if (f > _pointer_frame_offset) {
- pos = f - _pointer_frame_offset;
+ pos.frame = f - _pointer_frame_offset;
}
if (snap) {
@@ -343,14 +343,14 @@ Drag::adjusted_frame (framepos_t f, GdkEvent const * event, bool snap) const
framepos_t
Drag::adjusted_current_frame (GdkEvent const * event, bool snap) const
{
- return adjusted_frame (_drags->current_pointer_frame (), event, snap);
+ return adjusted_frame (_drags->current_pointer_frame (), event, snap).frame;
}
frameoffset_t
Drag::snap_delta (guint state) const
{
if (ArdourKeyboard::indicates_snap_delta (state)) {
- return _snap_delta;
+ return _snap_delta.frame;
}
return 0;
@@ -373,11 +373,11 @@ Drag::current_pointer_y () const
}
void
-Drag::setup_snap_delta (framepos_t pos)
+Drag::setup_snap_delta (MusicFrame pos)
{
- framepos_t temp = pos;
- _editor->snap_to (temp, ARDOUR::RoundNearest, false, true);
- _snap_delta = temp - pos;
+ MusicFrame snap (pos);
+ _editor->snap_to (snap, ARDOUR::RoundNearest, false, true);
+ _snap_delta = snap - pos;
}
bool
@@ -513,7 +513,7 @@ Drag::show_verbose_cursor_text (string const & text)
}
boost::shared_ptr<Region>
-Drag::add_midi_region (MidiTimeAxisView* view, bool commit, const int32_t sub_num)
+Drag::add_midi_region (MidiTimeAxisView* view, bool commit)
{
if (_editor->session()) {
const TempoMap& map (_editor->session()->tempo_map());
@@ -522,7 +522,7 @@ Drag::add_midi_region (MidiTimeAxisView* view, bool commit, const int32_t sub_nu
might be wrong.
*/
framecnt_t len = map.frame_at_beat (max (0.0, map.beat_at_frame (pos)) + 1.0) - pos;
- return view->add_region (grab_frame(), len, commit, sub_num);
+ return view->add_region (grab_frame(), len, commit);
}
return boost::shared_ptr<Region>();
@@ -599,33 +599,11 @@ RegionDrag::find_time_axis_view (TimeAxisView* t) const
return i;
}
-/** determines if @pos is the closest frame to an exact musical division when using SnapMagnetic.
- * (SnapMagnetic may snap to an exact division or no division at all).
- * this is a hotfix for musical region position/trim. we should really
- * deliver musical divisors when snapping magnetically to avoid this.
-*/
-int32_t
-RegionDrag::current_music_divisor (framepos_t pos, int32_t button_state)
-{
- int32_t divisions = _editor->get_grid_music_divisions (button_state);
-
- if (_editor->snap_mode() == Editing::SnapMagnetic && !ArdourKeyboard::indicates_snap (button_state)) {
- TempoMap& tmap (_editor->session()->tempo_map());
- const framepos_t exact_qn_pos = tmap.frame_at_quarter_note (tmap.exact_qn_at_frame (pos, divisions));
-
- if (pos != exact_qn_pos) {
- /* magnetic has not snapped */
- divisions = 0;
- }
- }
-
- return divisions;
-}
-
RegionMotionDrag::RegionMotionDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v, bool b)
: RegionDrag (e, i, p, v)
, _brushing (b)
, _ignore_video_lock (false)
+ , _last_position (0, 0)
, _total_x_delta (0)
, _last_pointer_time_axis_view (0)
, _last_pointer_layer (0)
@@ -640,9 +618,9 @@ void
RegionMotionDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
{
Drag::start_grab (event, cursor);
- setup_snap_delta (_last_frame_position);
+ setup_snap_delta (_last_position);
- show_verbose_cursor_time (_last_frame_position);
+ show_verbose_cursor_time (_last_position.frame);
pair<TimeAxisView*, double> const tv = _editor->trackview_by_y_position (current_pointer_y ());
if (tv.first) {
@@ -662,14 +640,13 @@ RegionMotionDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
}
double
-RegionMotionDrag::compute_x_delta (GdkEvent const * event, framepos_t* pending_region_position)
+RegionMotionDrag::compute_x_delta (GdkEvent const * event, MusicFrame* pending_region_position)
{
/* compute the amount of pointer motion in frames, and where
the region would be if we moved it by that much.
*/
*pending_region_position = adjusted_frame (_drags->current_pointer_frame (), event, false);
- framepos_t sync_frame;
framecnt_t sync_offset;
int32_t sync_dir;
@@ -677,34 +654,35 @@ RegionMotionDrag::compute_x_delta (GdkEvent const * event, framepos_t* pending_r
/* we don't handle a sync point that lies before zero.
*/
- if (sync_dir >= 0 || (sync_dir < 0 && *pending_region_position >= sync_offset)) {
+ if (sync_dir >= 0 || (sync_dir < 0 && pending_region_position->frame >= sync_offset)) {
framecnt_t const sd = snap_delta (event->button.state);
- sync_frame = *pending_region_position + (sync_dir * sync_offset) + sd;
-
- _editor->snap_to_with_modifier (sync_frame, event);
-
- *pending_region_position = _primary->region()->adjust_to_sync (sync_frame) - sd;
-
+ MusicFrame sync_snap (pending_region_position->frame + (sync_dir * sync_offset) + sd, 0);
+ _editor->snap_to_with_modifier (sync_snap, event);
+ if (sync_offset == 0 && sd == 0) {
+ *pending_region_position = sync_snap;
+ } else {
+ pending_region_position->set (_primary->region()->adjust_to_sync (sync_snap.frame) - sd, 0);
+ }
} else {
- *pending_region_position = _last_frame_position;
+ *pending_region_position = _last_position;
}
- if (*pending_region_position > max_framepos - _primary->region()->length()) {
- *pending_region_position = _last_frame_position;
+ if (pending_region_position->frame > max_framepos - _primary->region()->length()) {
+ *pending_region_position = _last_position;
}
double dx = 0;
bool const x_move_allowed = !_x_constrained;
- if ((*pending_region_position != _last_frame_position) && x_move_allowed) {
+ if ((pending_region_position->frame != _last_position.frame) && x_move_allowed) {
/* x movement since last time (in pixels) */
- dx = (static_cast<double> (*pending_region_position) - _last_frame_position) / _editor->samples_per_pixel;
+ dx = (static_cast<double> (pending_region_position->frame) - _last_position.frame) / _editor->samples_per_pixel;
/* total x movement */
- framecnt_t total_dx = *pending_region_position;
+ framecnt_t total_dx = pending_region_position->frame;
if (regions_came_from_canvas()) {
total_dx = total_dx - grab_frame ();
}
@@ -713,7 +691,7 @@ RegionMotionDrag::compute_x_delta (GdkEvent const * event, framepos_t* pending_r
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
if ((i->view->region()->position() + total_dx) < 0) {
dx = 0;
- *pending_region_position = _last_frame_position;
+ *pending_region_position = _last_position;
break;
}
}
@@ -954,9 +932,9 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
}
/* Work out the change in x */
- framepos_t pending_region_position;
+ MusicFrame pending_region_position (0, 0);
double const x_delta = compute_x_delta (event, &pending_region_position);
- _last_frame_position = pending_region_position;
+ _last_position = pending_region_position;
/* calculate hidden tracks in current y-axis delta */
int delta_skip = 0;
@@ -1159,7 +1137,7 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
i->layer += this_delta_layer;
if (_brushing) {
- _editor->mouse_brush_insert_region (rv, pending_region_position);
+ _editor->mouse_brush_insert_region (rv, pending_region_position.frame);
} else {
Duple track_origin;
@@ -1206,7 +1184,7 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
_total_x_delta += x_delta;
if (x_delta != 0 && !_brushing) {
- show_verbose_cursor_time (_last_frame_position);
+ show_verbose_cursor_time (_last_position.frame);
}
/* keep track of pointer movement */
@@ -1296,12 +1274,7 @@ RegionMoveDrag::motion (GdkEvent* event, bool first_move)
const boost::shared_ptr<const Region> original = rv->region();
boost::shared_ptr<Region> region_copy;
- if (rv == _primary) {
- region_copy = RegionFactory::create (original, true
- , current_music_divisor (original->position(), event->button.state));
- } else {
- region_copy = RegionFactory::create (original, true, 0);
- }
+ region_copy = RegionFactory::create (original, true);
/* need to set this so that the drop zone code can work. This doesn't
actually put the region into the playlist, but just sets a weak pointer
@@ -1399,16 +1372,15 @@ RegionMoveDrag::finished (GdkEvent* ev, bool movement_occurred)
i->view->get_canvas_group()->show ();
}
- bool const changed_position = (_last_frame_position != _primary->region()->position());
+ bool const changed_position = (_last_position.frame != _primary->region()->position());
bool const changed_tracks = (_time_axis_views[_views.front().time_axis_view] != &_views.front().view->get_time_axis_view());
- framecnt_t const drag_delta = _primary->region()->position() - _last_frame_position;
if (_copy) {
finished_copy (
changed_position,
changed_tracks,
- drag_delta,
+ _last_position,
ev->button.state
);
@@ -1417,7 +1389,7 @@ RegionMoveDrag::finished (GdkEvent* ev, bool movement_occurred)
finished_no_copy (
changed_position,
changed_tracks,
- drag_delta,
+ _last_position,
ev->button.state
);
@@ -1462,15 +1434,16 @@ RegionMoveDrag::create_destination_time_axis (boost::shared_ptr<Region> region,
}
void
-RegionMoveDrag::finished_copy (bool const changed_position, bool const /*changed_tracks*/, framecnt_t const drag_delta, int32_t const ev_state)
+RegionMoveDrag::finished_copy (bool const changed_position, bool const /*changed_tracks*/, MusicFrame last_position, int32_t const ev_state)
{
RegionSelection new_views;
PlaylistSet modified_playlists;
RouteTimeAxisView* new_time_axis_view = 0;
+ framecnt_t const drag_delta = _primary->region()->position() - _last_position.frame;
- int32_t divisor = current_music_divisor (_primary->region()->position() - drag_delta, ev_state);
TempoMap& tmap (_editor->session()->tempo_map());
- double qn_delta = _primary->region()->quarter_note() - tmap.exact_qn_at_frame (_primary->region()->position() - drag_delta, divisor);
+ const double last_pos_qn = tmap.exact_qn_at_frame (last_position.frame, last_position.division);
+ const double qn_delta = _primary->region()->quarter_note() - last_pos_qn;
if (_brushing) {
/* all changes were made during motion event handlers */
@@ -1495,12 +1468,16 @@ RegionMoveDrag::finished_copy (bool const changed_position, bool const /*changed
continue;
}
- framepos_t where;
+ MusicFrame where (0, 0);
+ double quarter_note;
if (changed_position && !_x_constrained) {
- where = i->view->region()->position() - drag_delta;
+ where.set (i->view->region()->position() - drag_delta, 0);
+ quarter_note = i->view->region()->quarter_note() - qn_delta;
} else {
- where = i->view->region()->position();
+ /* region has not moved - divisor will not affect musical pos */
+ where.set (i->view->region()->position(), 0);
+ quarter_note = i->view->region()->quarter_note();
}
if (i->time_axis_view < 0 || i->time_axis_view >= (int)_time_axis_views.size()) {
@@ -1528,17 +1505,16 @@ RegionMoveDrag::finished_copy (bool const changed_position, bool const /*changed
if (dest_rtv != 0) {
RegionView* new_view;
- if (i->view == _primary) {
- new_view = insert_region_into_playlist (i->view->region(), dest_rtv, i->layer, where,
- modified_playlists, current_music_divisor (where, ev_state));
+ if (i->view == _primary && !_x_constrained) {
+ new_view = insert_region_into_playlist (i->view->region(), dest_rtv, i->layer, last_position, last_pos_qn,
+ modified_playlists, true);
} else {
if (i->view->region()->position_lock_style() == AudioTime) {
- new_view = insert_region_into_playlist (i->view->region(), dest_rtv, i->layer, where,
- modified_playlists, 0);
+ new_view = insert_region_into_playlist (i->view->region(), dest_rtv, i->layer, where, quarter_note,
+ modified_playlists);
} else {
- where = tmap.frame_at_quarter_note (i->view->region()->quarter_note() - qn_delta);
- new_view = insert_region_into_playlist (i->view->region(), dest_rtv, i->layer, where,
- modified_playlists, 0);
+ new_view = insert_region_into_playlist (i->view->region(), dest_rtv, i->layer, where, quarter_note,
+ modified_playlists, true);
}
}
@@ -1575,7 +1551,7 @@ void
RegionMoveDrag::finished_no_copy (
bool const changed_position,
bool const changed_tracks,
- framecnt_t const drag_delta,
+ MusicFrame last_position,
int32_t const ev_state
)
{
@@ -1584,13 +1560,14 @@ RegionMoveDrag::finished_no_copy (
PlaylistSet frozen_playlists;
set<RouteTimeAxisView*> views_to_update;
RouteTimeAxisView* new_time_axis_view = 0;
+ framecnt_t const drag_delta = _primary->region()->position() - _last_position.frame;
typedef map<boost::shared_ptr<Playlist>, RouteTimeAxisView*> PlaylistMapping;
PlaylistMapping playlist_mapping;
- int32_t divisor = current_music_divisor (_primary->region()->position() - drag_delta, ev_state);
TempoMap& tmap (_editor->session()->tempo_map());
- double qn_delta = _primary->region()->quarter_note() - tmap.exact_qn_at_frame (_primary->region()->position() - drag_delta, divisor);
+ const double last_pos_qn = tmap.exact_qn_at_frame (last_position.frame, last_position.division);
+ const double qn_delta = _primary->region()->quarter_note() - last_pos_qn;
std::set<boost::shared_ptr<const Region> > uniq;
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ) {
@@ -1640,12 +1617,15 @@ RegionMoveDrag::finished_no_copy (
views_to_update.insert (dest_rtv);
- framepos_t where;
+ MusicFrame where (0, 0);
+ double quarter_note;
if (changed_position && !_x_constrained) {
- where = rv->region()->position() - drag_delta;
+ where.set (rv->region()->position() - drag_delta, 0);
+ quarter_note = i->view->region()->quarter_note() - qn_delta;
} else {
- where = rv->region()->position();
+ where.set (rv->region()->position(), 0);
+ quarter_note = i->view->region()->quarter_note();
}
if (changed_tracks) {
@@ -1654,21 +1634,20 @@ RegionMoveDrag::finished_no_copy (
RegionView* new_view;
if (rv == _primary) {
new_view = insert_region_into_playlist (
- RegionFactory::create (rv->region (), true), dest_rtv, dest_layer, where,
- modified_playlists, current_music_divisor (where, ev_state)
+ RegionFactory::create (rv->region (), true), dest_rtv, dest_layer, last_position, last_pos_qn,
+ modified_playlists, true
);
} else {
if (rv->region()->position_lock_style() == AudioTime) {
new_view = insert_region_into_playlist (
- RegionFactory::create (rv->region (), true), dest_rtv, dest_layer, where,
- modified_playlists, 0
+ RegionFactory::create (rv->region (), true), dest_rtv, dest_layer, where, quarter_note,
+ modified_playlists
);
} else {
- where = tmap.frame_at_quarter_note (rv->region()->quarter_note() - qn_delta);
new_view = insert_region_into_playlist (
- RegionFactory::create (rv->region (), true), dest_rtv, dest_layer, where,
- modified_playlists, 0
+ RegionFactory::create (rv->region (), true), dest_rtv, dest_layer, where, quarter_note,
+ modified_playlists, true
);
}
}
@@ -1730,13 +1709,14 @@ RegionMoveDrag::finished_no_copy (
playlist->freeze ();
}
if (rv == _primary) {
- rv->region()->set_position (where, current_music_divisor (where, ev_state));
+ rv->region()->set_position (where.frame, last_position.division);
} else {
if (rv->region()->position_lock_style() == AudioTime) {
- rv->region()->set_position (where, 0);
+ /* move by frame offset */
+ rv->region()->set_position (where.frame, 0);
} else {
- rv->region()->set_position (tmap.frame_at_quarter_note (rv->region()->quarter_note() - qn_delta), 0);
-
+ /* move by music offset */
+ rv->region()->set_position_music (rv->region()->quarter_note() - qn_delta);
}
}
_editor->session()->add_command (new StatefulDiffCommand (rv->region()));
@@ -1838,11 +1818,12 @@ RegionMoveDrag::remove_region_from_playlist (
RegionView *
RegionMoveDrag::insert_region_into_playlist (
boost::shared_ptr<Region> region,
- RouteTimeAxisView* dest_rtv,
- layer_t dest_layer,
- framecnt_t where,
- PlaylistSet& modified_playlists,
- const int32_t sub_num
+ RouteTimeAxisView* dest_rtv,
+ layer_t dest_layer,
+ MusicFrame where,
+ double quarter_note,
+ PlaylistSet& modified_playlists,
+ bool for_music
)
{
boost::shared_ptr<Playlist> dest_playlist = dest_rtv->playlist ();
@@ -1859,7 +1840,11 @@ RegionMoveDrag::insert_region_into_playlist (
if (r.second) {
dest_playlist->clear_changes ();
}
- dest_playlist->add_region (region, where, 1.0, false, sub_num);
+ if (for_music) {
+ dest_playlist->add_region (region, where.frame, 1.0, false, where.division, quarter_note, true);
+ } else {
+ dest_playlist->add_region (region, where.frame, 1.0, false, where.division);
+ }
if (dest_rtv->view()->layer_display() == Stacked || dest_rtv->view()->layer_display() == Expanded) {
dest_playlist->set_layer (region, dest_layer);
@@ -1954,13 +1939,13 @@ RegionMoveDrag::RegionMoveDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p,
speed = rtv->track()->speed ();
}
- _last_frame_position = static_cast<framepos_t> (_primary->region()->position() / speed);
+ _last_position = MusicFrame (static_cast<framepos_t> (_primary->region()->position() / speed), 0);
}
void
RegionMoveDrag::setup_pointer_frame_offset ()
{
- _pointer_frame_offset = raw_grab_frame() - _last_frame_position;
+ _pointer_frame_offset = raw_grab_frame() - _last_position.frame;
}
RegionInsertDrag::RegionInsertDrag (Editor* e, boost::shared_ptr<Region> r, RouteTimeAxisView* v, framepos_t pos)
@@ -1977,7 +1962,7 @@ RegionInsertDrag::RegionInsertDrag (Editor* e, boost::shared_ptr<Region> r, Rout
_primary->set_position (pos, 0);
_views.push_back (DraggingView (_primary, this, v));
- _last_frame_position = pos;
+ _last_position = MusicFrame (pos, 0);
_item = _primary->get_canvas_group ();
}
@@ -1997,11 +1982,11 @@ RegionInsertDrag::finished (GdkEvent * event, bool)
_editor->begin_reversible_command (Operations::insert_region);
playlist->clear_changes ();
- playlist->add_region (_primary->region (), _last_frame_position);
+ playlist->add_region (_primary->region (), _last_position.frame, _editor->get_grid_music_divisions (event->button.state));
// Mixbus doesn't seem to ripple when inserting regions from the list: should we? yes, probably
if (Config->get_edit_mode() == Ripple) {
- playlist->ripple (_last_frame_position, _primary->region()->length(), _primary->region());
+ playlist->ripple (_last_position.frame, _primary->region()->length(), _primary->region());
}
_editor->session()->add_command (new StatefulDiffCommand (playlist));
@@ -2278,7 +2263,7 @@ RegionRippleDrag::motion (GdkEvent* event, bool first_move)
framepos_t where = adjusted_current_frame (event);
assert (where >= 0);
- framepos_t after;
+ MusicFrame after (0, 0);
double delta = compute_x_delta (event, &after);
framecnt_t amount = _editor->pixel_to_sample (delta);
@@ -2328,7 +2313,7 @@ RegionRippleDrag::motion (GdkEvent* event, bool first_move)
prev_amount += amount;
}
- _last_frame_position = after;
+ _last_position = after;
}
void
@@ -2409,7 +2394,7 @@ RegionCreateDrag::motion (GdkEvent* event, bool first_move)
{
if (first_move) {
_editor->begin_reversible_command (_("create region"));
- _region = add_midi_region (_view, false, _editor->get_grid_music_divisions (event->button.state));
+ _region = add_midi_region (_view, false);
_view->playlist()->freeze ();
} else {
if (_region) {
@@ -2435,7 +2420,7 @@ void
RegionCreateDrag::finished (GdkEvent* event, bool movement_occurred)
{
if (!movement_occurred) {
- add_midi_region (_view, true, _editor->get_grid_music_divisions (event->button.state));
+ add_midi_region (_view, true);
} else {
_view->playlist()->thaw ();
_editor->commit_reversible_command();
@@ -2867,7 +2852,7 @@ TrimDrag::start_grab (GdkEvent* event, Gdk::Cursor*)
framecnt_t const region_length = (framecnt_t) (_primary->region()->length() / speed);
framepos_t const pf = adjusted_current_frame (event);
- setup_snap_delta (region_start);
+ setup_snap_delta (MusicFrame (region_start, 0));
if (Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::trim_contents_modifier ())) {
/* Move the contents of the region around without changing the region bounds */
@@ -2930,8 +2915,8 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
if (tv && tv->is_track()) {
speed = tv->track()->speed();
}
- framecnt_t adj_frame = adjusted_frame (_drags->current_pointer_frame () + snap_delta (event->button.state), event, true);
- framecnt_t dt = adj_frame - raw_grab_frame () + _pointer_frame_offset - snap_delta (event->button.state);
+ MusicFrame adj_frame = adjusted_frame (_drags->current_pointer_frame () + snap_delta (event->button.state), event, true);
+ framecnt_t dt = adj_frame.frame - raw_grab_frame () + _pointer_frame_offset - snap_delta (event->button.state);
if (first_move) {
@@ -3012,13 +2997,11 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
}
}
- int32_t divisions = current_music_divisor (adj_frame, event->button.state);
-
switch (_operation) {
case StartTrim:
for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
bool changed = i->view->trim_front (i->initial_position + dt, non_overlap_trim
- , divisions);
+ , adj_frame.division);
if (changed && _preserve_fade_anchor) {
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (i->view);
@@ -3037,7 +3020,7 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
case EndTrim:
for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
- bool changed = i->view->trim_end (i->initial_end + dt, non_overlap_trim, divisions);
+ bool changed = i->view->trim_end (i->initial_end + dt, non_overlap_trim, adj_frame.division);
if (changed && _preserve_fade_anchor) {
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (i->view);
if (arv) {
@@ -3156,7 +3139,7 @@ TrimDrag::finished (GdkEvent* event, bool movement_occurred)
} else {
/* no mouse movement */
- if (adjusted_current_frame (event) != adjusted_frame (_drags->current_pointer_frame(), event, false)) {
+ if (adjusted_current_frame (event) != adjusted_frame (_drags->current_pointer_frame(), event, false).frame) {
_editor->point_trim (event, adjusted_current_frame (event));
}
}
@@ -3648,14 +3631,14 @@ void
CursorDrag::start_grab (GdkEvent* event, Gdk::Cursor* c)
{
Drag::start_grab (event, c);
- setup_snap_delta (_editor->playhead_cursor->current_frame ());
+ const framepos_t current_frame = _editor->playhead_cursor->current_frame();
+ setup_snap_delta (MusicFrame (current_frame, 0));
_grab_zoom = _editor->samples_per_pixel;
- framepos_t where = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
+ MusicFrame where (_editor->canvas_event_sample (event) + snap_delta (event->button.state), 0);
_editor->snap_to_with_modifier (where, event);
-
_editor->_dragging_playhead = true;
Session* s = _editor->session ();
@@ -3690,16 +3673,18 @@ CursorDrag::start_grab (GdkEvent* event, Gdk::Cursor* c)
}
}
- fake_locate (where - snap_delta (event->button.state));
+ fake_locate (where.frame - snap_delta (event->button.state));
}
void
CursorDrag::motion (GdkEvent* event, bool)
{
- framepos_t where = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
+ MusicFrame where (_editor->canvas_event_sample (event) + snap_delta (event->button.state), 0);
+
_editor->snap_to_with_modifier (where, event);
- if (where != last_pointer_frame()) {
- fake_locate (where - snap_delta (event->button.state));
+
+ if (where.frame != last_pointer_frame()) {
+ fake_locate (where.frame - snap_delta (event->button.state));
}
}
@@ -3734,7 +3719,7 @@ CursorDrag::aborted (bool)
_editor->_dragging_playhead = false;
}
- _editor->playhead_cursor->set_position (adjusted_frame (grab_frame (), 0, false));
+ _editor->playhead_cursor->set_position (adjusted_frame (grab_frame (), 0, false).frame);
}
FadeInDrag::FadeInDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v)
@@ -3750,7 +3735,8 @@ FadeInDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (_primary);
boost::shared_ptr<AudioRegion> const r = arv->audio_region ();
- setup_snap_delta (r->position ());
+ const int32_t division = _editor->get_grid_music_divisions (event->button.state);
+ setup_snap_delta (MusicFrame (r->position(), division));
show_verbose_cursor_duration (r->position(), r->position() + r->fade_in()->back()->when, 32);
}
@@ -3768,18 +3754,19 @@ FadeInDrag::motion (GdkEvent* event, bool)
{
framecnt_t fade_length;
- framepos_t pos = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
+ MusicFrame pos (_editor->canvas_event_sample (event) + snap_delta (event->button.state), 0);
_editor->snap_to_with_modifier (pos, event);
- pos -= snap_delta (event->button.state);
+
+ pos.frame -= snap_delta (event->button.state);
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (_primary->region ());
- if (pos < (region->position() + 64)) {
+ if (pos.frame < (region->position() + 64)) {
fade_length = 64; // this should be a minimum defined somewhere
- } else if (pos > region->position() + region->length() - region->fade_out()->back()->when) {
+ } else if (pos.frame > region->position() + region->length() - region->fade_out()->back()->when) {
fade_length = region->length() - region->fade_out()->back()->when - 1;
} else {
- fade_length = pos - region->position();
+ fade_length = pos.frame - region->position();
}
for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
@@ -3804,18 +3791,19 @@ FadeInDrag::finished (GdkEvent* event, bool movement_occurred)
}
framecnt_t fade_length;
- framepos_t pos = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
+ MusicFrame pos (_editor->canvas_event_sample (event) + snap_delta (event->button.state), 0);
+
_editor->snap_to_with_modifier (pos, event);
- pos -= snap_delta (event->button.state);
+ pos.frame -= snap_delta (event->button.state);
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (_primary->region ());
- if (pos < (region->position() + 64)) {
+ if (pos.frame < (region->position() + 64)) {
fade_length = 64; // this should be a minimum defined somewhere
- } else if (pos >= region->position() + region->length() - region->fade_out()->back()->when) {
+ } else if (pos.frame >= region->position() + region->length() - region->fade_out()->back()->when) {
fade_length = region->length() - region->fade_out()->back()->when - 1;
} else {
- fade_length = pos - region->position();
+ fade_length = pos.frame - region->position();
}
bool in_command = false;
@@ -3874,7 +3862,8 @@ FadeOutDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (_primary);
boost::shared_ptr<AudioRegion> r = arv->audio_region ();
- setup_snap_delta (r->last_frame ());
+ const int32_t division = _editor->get_grid_music_divisions (event->button.state);
+ setup_snap_delta (MusicFrame (r->last_frame(), division));
show_verbose_cursor_duration (r->last_frame() - r->fade_out()->back()->when, r->last_frame());
}
@@ -3891,19 +3880,19 @@ void
FadeOutDrag::motion (GdkEvent* event, bool)
{
framecnt_t fade_length;
+ MusicFrame pos (_editor->canvas_event_sample (event) + snap_delta (event->button.state), 0);
- framepos_t pos = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
_editor->snap_to_with_modifier (pos, event);
- pos -= snap_delta (event->button.state);
+ pos.frame -= snap_delta (event->button.state);
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (_primary->region ());
- if (pos > (region->last_frame() - 64)) {
+ if (pos.frame > (region->last_frame() - 64)) {
fade_length = 64; // this should really be a minimum fade defined somewhere
- } else if (pos <= region->position() + region->fade_in()->back()->when) {
+ } else if (pos.frame <= region->position() + region->fade_in()->back()->when) {
fade_length = region->length() - region->fade_in()->back()->when - 1;
} else {
- fade_length = region->last_frame() - pos;
+ fade_length = region->last_frame() - pos.frame;
}
for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
@@ -3928,19 +3917,19 @@ FadeOutDrag::finished (GdkEvent* event, bool movement_occurred)
}
framecnt_t fade_length;
+ MusicFrame pos (_editor->canvas_event_sample (event) + snap_delta (event->button.state), 0);
- framepos_t pos = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
_editor->snap_to_with_modifier (pos, event);
- pos -= snap_delta (event->button.state);
+ pos.frame -= snap_delta (event->button.state);
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (_primary->region ());
- if (pos > (region->last_frame() - 64)) {
+ if (pos.frame > (region->last_frame() - 64)) {
fade_length = 64; // this should really be a minimum fade defined somewhere
- } else if (pos <= region->position() + region->fade_in()->back()->when) {
+ } else if (pos.frame <= region->position() + region->fade_in()->back()->when) {
fade_length = region->length() - region->fade_in()->back()->when - 1;
} else {
- fade_length = region->last_frame() - pos;
+ fade_length = region->last_frame() - pos.frame;
}
bool in_command = false;
@@ -4035,7 +4024,9 @@ MarkerDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
} else {
show_verbose_cursor_time (location->end());
}
- setup_snap_delta (is_start ? location->start() : location->end());
+ const int32_t division = _editor->get_grid_music_divisions (event->button.state);
+ const framepos_t pos = is_start ? location->start() : location->end();
+ setup_snap_delta (MusicFrame (pos, division));
Selection::Operation op = ArdourKeyboard::selection_type (event->button.state);
@@ -4139,7 +4130,7 @@ MarkerDrag::motion (GdkEvent* event, bool)
Location *copy_location = 0;
framecnt_t const sd = snap_delta (event->button.state);
- framecnt_t const newframe = adjusted_frame (_drags->current_pointer_frame () + sd, event, true) - sd;
+ framecnt_t const newframe = adjusted_frame (_drags->current_pointer_frame () + sd, event, true).frame - sd;
framepos_t next = newframe;
if (Keyboard::modifier_state_contains (event->button.state, ArdourKeyboard::push_points_modifier ())) {
@@ -4422,8 +4413,9 @@ ControlPointDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
_fixed_grab_x = _point->get_x() + _editor->sample_to_pixel_unrounded (_point->line().offset());
_fixed_grab_y = _point->get_y();
- framepos_t pos = _editor->pixel_to_sample (_fixed_grab_x);
- setup_snap_delta (pos);
+ const framepos_t pos = _editor->pixel_to_sample (_fixed_grab_x);
+ const int32_t division = _editor->get_grid_music_divisions (event->button.state);
+ setup_snap_delta (MusicFrame (pos, division));
float const fraction = 1 - (_point->get_y() / _point->line().height());
show_verbose_cursor_text (_point->line().get_verbose_cursor_string (fraction));
@@ -4476,13 +4468,14 @@ ControlPointDrag::motion (GdkEvent* event, bool first_motion)
cy = zero_gain_y;
}
- framepos_t cx_frames = _editor->pixel_to_sample (cx) + snap_delta (event->button.state);
+ MusicFrame cx_mf (_editor->pixel_to_sample (cx) + snap_delta (event->button.state), 0);
+
if (!_x_constrained && need_snap) {
- _editor->snap_to_with_modifier (cx_frames, event);
+ _editor->snap_to_with_modifier (cx_mf, event);
}
- cx_frames -= snap_delta (event->button.state);
- cx_frames = min (cx_frames, _point->line().maximum_time() + _point->line().offset());
+ cx_mf.frame -= snap_delta (event->button.state);
+ cx_mf.frame = min (cx_mf.frame, _point->line().maximum_time() + _point->line().offset());
float const fraction = 1.0 - (cy / _point->line().height());
@@ -4492,7 +4485,7 @@ ControlPointDrag::motion (GdkEvent* event, bool first_motion)
_point->line().start_drag_single (_point, _fixed_grab_x, initial_fraction);
}
pair<double, float> result;
- result = _point->line().drag_motion (_editor->sample_to_pixel_unrounded (cx_frames), fraction, false, _pushing, _final_index);
+ result = _point->line().drag_motion (_editor->sample_to_pixel_unrounded (cx_mf.frame), fraction, false, _pushing, _final_index);
show_verbose_cursor_text (_point->line().get_verbose_cursor_string (result.second));
}
@@ -4755,24 +4748,23 @@ RubberbandSelectDrag::motion (GdkEvent* event, bool)
framepos_t end;
double y1;
double y2;
-
framepos_t const pf = adjusted_current_frame (event, UIConfiguration::instance().get_rubberbanding_snaps_to_grid());
+ MusicFrame grab (grab_frame (), 0);
- framepos_t grab = grab_frame ();
if (UIConfiguration::instance().get_rubberbanding_snaps_to_grid ()) {
_editor->snap_to_with_modifier (grab, event);
} else {
- grab = raw_grab_frame ();
+ grab.frame = raw_grab_frame ();
}
/* base start and end on initial click position */
- if (pf < grab) {
+ if (pf < grab.frame) {
start = pf;
- end = grab;
+ end = grab.frame;
} else {
end = pf;
- start = grab;
+ start = grab.frame;
}
if (current_pointer_y() < grab_y()) {
@@ -4882,7 +4874,7 @@ RubberbandSelectDrag::finished (GdkEvent* event, bool movement_occurred)
/* MIDI track */
if (_editor->selection->empty() && _editor->mouse_mode == MouseDraw) {
/* nothing selected */
- add_midi_region (mtv, true, _editor->get_grid_music_divisions(event->button.state));
+ add_midi_region (mtv, true);
do_deselect = false;
}
}
@@ -4922,7 +4914,8 @@ TimeFXDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
_editor->get_selection().add (_primary);
framepos_t where = _primary->region()->position();
- setup_snap_delta (where);
+ const int32_t division = _editor->get_grid_music_divisions (event->button.state);
+ setup_snap_delta (MusicFrame (where, division));
show_verbose_cursor_duration (where, adjusted_current_frame (event), 0);
}
@@ -4932,19 +4925,19 @@ TimeFXDrag::motion (GdkEvent* event, bool)
{
RegionView* rv = _primary;
StreamView* cv = rv->get_time_axis_view().view ();
-
pair<TimeAxisView*, double> const tv = _editor->trackview_by_y_position (grab_y());
int layer = tv.first->layer_display() == Overlaid ? 0 : tv.second;
int layers = tv.first->layer_display() == Overlaid ? 1 : cv->layers();
- framepos_t pf = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
+ MusicFrame pf (_editor->canvas_event_sample (event) + snap_delta (event->button.state), 0);
+
_editor->snap_to_with_modifier (pf, event);
- pf -= snap_delta (event->button.state);
+ pf.frame -= snap_delta (event->button.state);
- if (pf > rv->region()->position()) {
- rv->get_time_axis_view().show_timestretch (rv->region()->position(), pf, layers, layer);
+ if (pf.frame > rv->region()->position()) {
+ rv->get_time_axis_view().show_timestretch (rv->region()->position(), pf.frame, layers, layer);
}
- show_verbose_cursor_duration (_primary->region()->position(), pf, 0);
+ show_verbose_cursor_duration (_primary->region()->position(), pf.frame, 0);
}
void
@@ -5128,7 +5121,7 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
framepos_t end = 0;
framecnt_t length = 0;
framecnt_t distance = 0;
-
+ MusicFrame start_mf (0, 0);
framepos_t const pending_position = adjusted_current_frame (event);
if (_operation != CreateSelection && pending_position == last_pointer_frame()) {
@@ -5142,23 +5135,22 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
switch (_operation) {
case CreateSelection:
{
- framepos_t grab = grab_frame ();
-
+ MusicFrame grab (grab_frame (), 0);
if (first_move) {
- grab = adjusted_current_frame (event, false);
- if (grab < pending_position) {
+ grab.frame = adjusted_current_frame (event, false);
+ if (grab.frame < pending_position) {
_editor->snap_to (grab, RoundDownMaybe);
} else {
_editor->snap_to (grab, RoundUpMaybe);
}
}
- if (pending_position < grab) {
+ if (pending_position < grab.frame) {
start = pending_position;
- end = grab;
+ end = grab.frame;
} else {
end = pending_position;
- start = grab;
+ start = grab.frame;
}
/* first drag: Either add to the selection
@@ -5269,9 +5261,11 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
length = end - start;
distance = pending_position - start;
start = pending_position;
- _editor->snap_to (start);
- end = start + length;
+ start_mf.frame = start;
+ _editor->snap_to (start_mf);
+
+ end = start_mf.frame + length;
break;
@@ -5466,15 +5460,15 @@ RangeMarkerBarDrag::motion (GdkEvent* event, bool first_move)
framepos_t const pf = adjusted_current_frame (event);
if (_operation == CreateSkipMarker || _operation == CreateRangeMarker || _operation == CreateTransportMarker || _operation == CreateCDMarker) {
- framepos_t grab = grab_frame ();
+ MusicFrame grab (grab_frame (), 0);
_editor->snap_to (grab);
if (pf < grab_frame()) {
start = pf;
- end = grab;
+ end = grab.frame;
} else {
end = pf;
- start = grab;
+ start = grab.frame;
}
/* first drag: Either add to the selection
@@ -5653,7 +5647,7 @@ NoteDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
_copy = false;
}
- setup_snap_delta (_region->source_beats_to_absolute_frames (_primary->note()->time ()));
+ setup_snap_delta (MusicFrame (_region->source_beats_to_absolute_frames (_primary->note()->time ()), 0));
if (!(_was_selected = _primary->selected())) {
@@ -6616,10 +6610,10 @@ RegionCutDrag::start_grab (GdkEvent* event, Gdk::Cursor* c)
void
RegionCutDrag::motion (GdkEvent* event, bool)
{
- framepos_t pos = _drags->current_pointer_frame();
+ MusicFrame pos (_drags->current_pointer_frame(), 0);
_editor->snap_to_with_modifier (pos, event);
- line->set_position (pos);
+ line->set_position (pos.frame);
}
void
@@ -6627,19 +6621,18 @@ RegionCutDrag::finished (GdkEvent* event, bool)
{
_editor->get_track_canvas()->canvas()->re_enter();
- framepos_t pos = _drags->current_pointer_frame();
- _editor->snap_to_with_modifier (pos, event);
+ MusicFrame pos (_drags->current_pointer_frame(), 0);
+ _editor->snap_to_with_modifier (pos, event);
line->hide ();
- RegionSelection rs = _editor->get_regions_from_selection_and_mouse (pos);
+ RegionSelection rs = _editor->get_regions_from_selection_and_mouse (pos.frame);
if (rs.empty()) {
return;
}
- _editor->split_regions_at (pos, rs, _editor->get_grid_music_divisions (event->button.state),
- false);
+ _editor->split_regions_at (pos, rs, false);
}
void
diff --git a/gtk2_ardour/editor_drag.h b/gtk2_ardour/editor_drag.h
index b5ebc3b39d..e5a02743fc 100644
--- a/gtk2_ardour/editor_drag.h
+++ b/gtk2_ardour/editor_drag.h
@@ -144,7 +144,7 @@ public:
bool motion_handler (GdkEvent*, bool);
void abort ();
- ARDOUR::framepos_t adjusted_frame (ARDOUR::framepos_t, GdkEvent const *, bool snap = true) const;
+ ARDOUR::MusicFrame adjusted_frame (ARDOUR::framepos_t, GdkEvent const *, bool snap = true) const;
ARDOUR::framepos_t adjusted_current_frame (GdkEvent const *, bool snap = true) const;
bool was_double_click() const { return _was_double_click; }
@@ -247,9 +247,9 @@ protected:
double current_pointer_y () const;
/* sets snap delta from unsnapped pos */
- void setup_snap_delta (framepos_t pos);
+ void setup_snap_delta (ARDOUR::MusicFrame pos);
- boost::shared_ptr<ARDOUR::Region> add_midi_region (MidiTimeAxisView*, bool commit, const int32_t sub_num);
+ boost::shared_ptr<ARDOUR::Region> add_midi_region (MidiTimeAxisView*, bool commit);
void show_verbose_cursor_time (framepos_t);
void show_verbose_cursor_duration (framepos_t, framepos_t, double xoffset = 0);
@@ -281,7 +281,7 @@ private:
/* difference between some key position's snapped and unsnapped
* framepos. used for relative snap.
*/
- ARDOUR::frameoffset_t _snap_delta;
+ ARDOUR::MusicFrame _snap_delta;
CursorContext::Handle _cursor_ctx; ///< cursor change context
bool _constraint_pressed; ///< if the keyboard indicated constraint modifier was pressed on start_grab()
};
@@ -328,7 +328,6 @@ protected:
std::vector<TimeAxisView*> _time_axis_views;
int find_time_axis_view (TimeAxisView *) const;
int apply_track_delta (const int start, const int delta, const int skip, const bool distance_only = false) const;
- int32_t current_music_divisor (framepos_t pos, int32_t button_state);
int _visible_y_low;
int _visible_y_high;
@@ -363,12 +362,12 @@ public:
protected:
- double compute_x_delta (GdkEvent const *, ARDOUR::framepos_t *);
+ double compute_x_delta (GdkEvent const *, ARDOUR::MusicFrame *);
virtual bool y_movement_allowed (int, double, int skip_invisible = 0) const;
bool _brushing;
bool _ignore_video_lock;
- ARDOUR::framepos_t _last_frame_position; ///< last position of the thing being dragged
+ ARDOUR::MusicFrame _last_position; ///< last position of the thing being dragged
double _total_x_delta;
int _last_pointer_time_axis_view;
double _last_pointer_layer;
@@ -410,14 +409,14 @@ private:
void finished_no_copy (
bool const,
bool const,
- ARDOUR::framecnt_t const,
+ ARDOUR::MusicFrame,
int32_t const ev_state
);
void finished_copy (
bool const,
bool const,
- ARDOUR::framecnt_t const,
+ ARDOUR::MusicFrame,
int32_t const ev_state
);
@@ -425,9 +424,10 @@ private:
boost::shared_ptr<ARDOUR::Region>,
RouteTimeAxisView*,
ARDOUR::layer_t,
- ARDOUR::framecnt_t,
+ ARDOUR::MusicFrame,
+ double quarter_note,
PlaylistSet&,
- const int32_t sub_num
+ bool for_music = false
);
void remove_region_from_playlist (
diff --git a/gtk2_ardour/editor_keys.cc b/gtk2_ardour/editor_keys.cc
index fba52014bc..2c64d6f4f3 100644
--- a/gtk2_ardour/editor_keys.cc
+++ b/gtk2_ardour/editor_keys.cc
@@ -43,9 +43,8 @@ Editor::keyboard_selection_finish (bool /*add*/, Editing::EditIgnoreOption ign)
{
if (_session) {
- framepos_t start = selection->time.start();
+ MusicFrame start (selection->time.start(), 0);
framepos_t end;
-
if ((_edit_point == EditAtPlayhead) && _session->transport_rolling()) {
end = _session->audible_frame();
} else {
@@ -53,13 +52,13 @@ Editor::keyboard_selection_finish (bool /*add*/, Editing::EditIgnoreOption ign)
}
//snap the selection start/end
- snap_to(start);
+ snap_to (start);
//if no tracks are selected and we're working from the keyboard, enable all tracks (_something_ has to be selected for any range selection)
if ( (_edit_point == EditAtPlayhead) && selection->tracks.empty() )
select_all_tracks();
- selection->set (start, end);
+ selection->set (start.frame, end);
//if session is playing a range, cancel that
if (_session->get_play_range())
@@ -73,26 +72,25 @@ Editor::keyboard_selection_begin (Editing::EditIgnoreOption ign)
{
if (_session) {
- framepos_t start;
- framepos_t end = selection->time.end_frame();
-
+ MusicFrame start (0, 0);
+ MusicFrame end (selection->time.end_frame(), 0);
if ((_edit_point == EditAtPlayhead) && _session->transport_rolling()) {
- start = _session->audible_frame();
+ start.frame = _session->audible_frame();
} else {
- start = get_preferred_edit_position(ign);
+ start.frame = get_preferred_edit_position(ign);
}
//snap the selection start/end
snap_to(start);
//if there's not already a sensible selection endpoint, go "forever"
- if (start > end) {
+ if (start.frame > end.frame) {
#ifdef MIXBUS
// 4hours at most.
// This works around a visual glitch in red-bordered selection rect.
- end = start + _session->nominal_frame_rate() * 60 * 60 * 4;
+ end.frame = start.frame + _session->nominal_frame_rate() * 60 * 60 * 4;
#else
- end = max_framepos;
+ end.frame = max_framepos;
#endif
}
@@ -100,7 +98,7 @@ Editor::keyboard_selection_begin (Editing::EditIgnoreOption ign)
if ( selection->tracks.empty() )
select_all_tracks();
- selection->set (start, end);
+ selection->set (start.frame, end.frame);
//if session is playing a range, cancel that
if (_session->get_play_range())
diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc
index 8e1ef327ab..d5bf07bd78 100644
--- a/gtk2_ardour/editor_mouse.cc
+++ b/gtk2_ardour/editor_mouse.cc
@@ -1269,9 +1269,9 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
UIConfiguration::instance().get_follow_edits() &&
!_session->config.get_external_sync()) {
- framepos_t where = canvas_event_sample (event);
- snap_to(where);
- _session->request_locate (where, false);
+ MusicFrame where (canvas_event_sample (event), 0);
+ snap_to (where);
+ _session->request_locate (where.frame, false);
}
switch (event->button.button) {
@@ -1318,7 +1318,7 @@ Editor::button_release_dispatch (GdkEventButton* ev)
bool
Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
{
- framepos_t where = canvas_event_sample (event);
+ MusicFrame where (canvas_event_sample (event), 0);
AutomationTimeAxisView* atv = 0;
_press_cursor_ctx.reset();
@@ -1466,7 +1466,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case SamplesRulerItem:
case MinsecRulerItem:
case BBTRulerItem:
- popup_ruler_menu (where, item_type);
+ popup_ruler_menu (where.frame, item_type);
break;
case MarkerItem:
@@ -1558,7 +1558,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case MarkerBarItem:
if (!_dragging_playhead) {
snap_to_with_modifier (where, event, RoundNearest, true);
- mouse_add_new_marker (where);
+ mouse_add_new_marker (where.frame);
}
return true;
@@ -1566,14 +1566,14 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
if (!_dragging_playhead) {
// if we get here then a dragged range wasn't done
snap_to_with_modifier (where, event, RoundNearest, true);
- mouse_add_new_marker (where, true);
+ mouse_add_new_marker (where.frame, true);
}
return true;
case TempoBarItem:
case TempoCurveItem:
if (!_dragging_playhead) {
snap_to_with_modifier (where, event);
- mouse_add_new_tempo_event (where);
+ mouse_add_new_tempo_event (where.frame);
}
return true;
@@ -1617,7 +1617,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
bool with_guard_points = Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier);
atv = dynamic_cast<AutomationTimeAxisView*>(clicked_axisview);
if (atv) {
- atv->add_automation_event (event, where, event->button.y, with_guard_points);
+ atv->add_automation_event (event, where.frame, event->button.y, with_guard_points);
}
return true;
break;
diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc
index 4df88b9025..288d12219f 100644
--- a/gtk2_ardour/editor_ops.cc
+++ b/gtk2_ardour/editor_ops.cc
@@ -166,8 +166,7 @@ Editor::redo (uint32_t n)
}
void
-Editor::split_regions_at (framepos_t where, RegionSelection& regions, const int32_t sub_num,
- bool snap_frame)
+Editor::split_regions_at (MusicFrame where, RegionSelection& regions, bool snap_frame)
{
bool frozen = false;
@@ -214,7 +213,7 @@ Editor::split_regions_at (framepos_t where, RegionSelection& regions, const int3
have something to split.
*/
- if (!(*a)->region()->covers (where)) {
+ if (!(*a)->region()->covers (where.frame)) {
++a;
continue;
}
@@ -246,7 +245,7 @@ Editor::split_regions_at (framepos_t where, RegionSelection& regions, const int3
if (pl) {
pl->clear_changes ();
- pl->split_region ((*a)->region(), where, sub_num);
+ pl->split_region ((*a)->region(), where);
_session->add_command (new StatefulDiffCommand (pl));
}
@@ -292,7 +291,7 @@ Editor::split_regions_at (framepos_t where, RegionSelection& regions, const int3
}
for (RegionSelection::iterator ri = latest_regionviews.begin(); ri != latest_regionviews.end(); ri++) {
- if ((*ri)->region()->position() < where) {
+ if ((*ri)->region()->position() < where.frame) {
// new regions created before the split
if (rsas & NewlyCreatedLeft) {
selection->add (*ri);
@@ -4260,7 +4259,7 @@ Editor::cut_copy_points (Editing::CutCopyOp op, Evoral::Beats earliest, bool mid
}
/* Add all selected points to the relevant copy ControlLists */
- framepos_t start = std::numeric_limits<framepos_t>::max();
+ MusicFrame start (std::numeric_limits<framepos_t>::max(), 0);
for (PointSelection::iterator sel_point = selection->points.begin(); sel_point != selection->points.end(); ++sel_point) {
boost::shared_ptr<AutomationList> al = (*sel_point)->line().the_list();
AutomationList::const_iterator ctrl_evt = (*sel_point)->model ();
@@ -4271,7 +4270,7 @@ Editor::cut_copy_points (Editing::CutCopyOp op, Evoral::Beats earliest, bool mid
earliest = std::min(earliest, Evoral::Beats((*ctrl_evt)->when));
} else {
/* Update earliest session start time in frames */
- start = std::min(start, (*sel_point)->line().session_position(ctrl_evt));
+ start.frame = std::min(start.frame, (*sel_point)->line().session_position(ctrl_evt));
}
}
@@ -4282,13 +4281,13 @@ Editor::cut_copy_points (Editing::CutCopyOp op, Evoral::Beats earliest, bool mid
}
earliest.round_down_to_beat();
} else {
- if (start == std::numeric_limits<double>::max()) {
- start = 0; // Weird... don't offset
+ if (start.frame == std::numeric_limits<double>::max()) {
+ start.frame = 0; // Weird... don't offset
}
snap_to(start, RoundDownMaybe);
}
- const double line_offset = midi ? earliest.to_double() : start;
+ const double line_offset = midi ? earliest.to_double() : start.frame;
for (Lists::iterator i = lists.begin(); i != lists.end(); ++i) {
/* Correct this copy list so that it is relative to the earliest
start time, so relative ordering between points is preserved
@@ -4691,22 +4690,21 @@ void
Editor::paste (float times, bool from_context)
{
DEBUG_TRACE (DEBUG::CutNPaste, "paste to preferred edit pos\n");
-
- paste_internal (get_preferred_edit_position (EDIT_IGNORE_NONE, from_context), times, get_grid_music_divisions (0));
+ MusicFrame where (get_preferred_edit_position (EDIT_IGNORE_NONE, from_context), 0);
+ paste_internal (where.frame, times, 0);
}
void
Editor::mouse_paste ()
{
- framepos_t where;
+ MusicFrame where (0, 0);
bool ignored;
-
- if (!mouse_frame (where, ignored)) {
+ if (!mouse_frame (where.frame, ignored)) {
return;
}
snap_to (where);
- paste_internal (where, 1, get_grid_music_divisions (0));
+ paste_internal (where.frame, 1, where.division);
}
void
@@ -6171,10 +6169,10 @@ Editor::update_region_fade_visibility ()
void
Editor::set_edit_point ()
{
- framepos_t where;
bool ignored;
+ MusicFrame where (0, 0);
- if (!mouse_frame (where, ignored)) {
+ if (!mouse_frame (where.frame, ignored)) {
return;
}
@@ -6182,7 +6180,7 @@ Editor::set_edit_point ()
if (selection->markers.empty()) {
- mouse_add_new_marker (where);
+ mouse_add_new_marker (where.frame);
} else {
bool ignored;
@@ -6190,7 +6188,7 @@ Editor::set_edit_point ()
Location* loc = find_location_from_marker (selection->markers.front(), ignored);
if (loc) {
- loc->move_to (where, get_grid_music_divisions(0));
+ loc->move_to (where.frame, where.division);
}
}
}
@@ -6201,17 +6199,17 @@ Editor::set_playhead_cursor ()
if (entered_marker) {
_session->request_locate (entered_marker->position(), _session->transport_rolling());
} else {
- framepos_t where;
+ MusicFrame where (0, 0);
bool ignored;
- if (!mouse_frame (where, ignored)) {
+ if (!mouse_frame (where.frame, ignored)) {
return;
}
snap_to (where);
if (_session) {
- _session->request_locate (where, _session->transport_rolling());
+ _session->request_locate (where.frame, _session->transport_rolling());
}
}
@@ -6239,18 +6237,16 @@ Editor::split_region ()
if (current_mouse_mode() == MouseObject) { //don't try this for Internal Edit, Stretch, Draw, etc.
RegionSelection rs = get_regions_from_selection_and_edit_point ();
-
- framepos_t where = get_preferred_edit_position ();
+ const framepos_t pos = get_preferred_edit_position();
+ const int32_t division = get_grid_music_divisions (0);
+ MusicFrame where (pos, division);
if (rs.empty()) {
return;
}
- if (snap_musical()) {
- split_regions_at (where, rs, get_grid_music_divisions (0));
- } else {
- split_regions_at (where, rs, 0);
- }
+ split_regions_at (where, rs);
+
}
}
@@ -6458,7 +6454,7 @@ Editor::set_punch_start_from_edit_point ()
{
if (_session) {
- framepos_t start = 0;
+ MusicFrame start (0, 0);
framepos_t end = max_framepos;
//use the existing punch end, if any
@@ -6468,20 +6464,20 @@ Editor::set_punch_start_from_edit_point ()
}
if ((_edit_point == EditAtPlayhead) && _session->transport_rolling()) {
- start = _session->audible_frame();
+ start.frame = _session->audible_frame();
} else {
- start = get_preferred_edit_position();
+ start.frame = get_preferred_edit_position();
}
//snap the selection start/end
snap_to(start);
//if there's not already a sensible selection endpoint, go "forever"
- if ( start > end ) {
+ if (start.frame > end ) {
end = max_framepos;
}
- set_punch_range (start, end, _("set punch start from EP"));
+ set_punch_range (start.frame, end, _("set punch start from EP"));
}
}
@@ -6492,7 +6488,7 @@ Editor::set_punch_end_from_edit_point ()
if (_session) {
framepos_t start = 0;
- framepos_t end = max_framepos;
+ MusicFrame end (max_framepos, 0);
//use the existing punch start, if any
Location* tpl = transport_punch_location();
@@ -6501,15 +6497,15 @@ Editor::set_punch_end_from_edit_point ()
}
if ((_edit_point == EditAtPlayhead) && _session->transport_rolling()) {
- end = _session->audible_frame();
+ end.frame = _session->audible_frame();
} else {
- end = get_preferred_edit_position();
+ end.frame = get_preferred_edit_position();
}
//snap the selection start/end
- snap_to(end);
+ snap_to (end);
- set_punch_range (start, end, _("set punch end from EP"));
+ set_punch_range (start, end.frame, _("set punch end from EP"));
}
}
@@ -6519,7 +6515,7 @@ Editor::set_loop_start_from_edit_point ()
{
if (_session) {
- framepos_t start = 0;
+ MusicFrame start (0, 0);
framepos_t end = max_framepos;
//use the existing loop end, if any
@@ -6529,20 +6525,20 @@ Editor::set_loop_start_from_edit_point ()
}
if ((_edit_point == EditAtPlayhead) && _session->transport_rolling()) {
- start = _session->audible_frame();
+ start.frame = _session->audible_frame();
} else {
- start = get_preferred_edit_position();
+ start.frame = get_preferred_edit_position();
}
//snap the selection start/end
- snap_to(start);
+ snap_to (start);
//if there's not already a sensible selection endpoint, go "forever"
- if ( start > end ) {
+ if (start.frame > end ) {
end = max_framepos;
}
- set_loop_range (start, end, _("set loop start from EP"));
+ set_loop_range (start.frame, end, _("set loop start from EP"));
}
}
@@ -6553,7 +6549,7 @@ Editor::set_loop_end_from_edit_point ()
if (_session) {
framepos_t start = 0;
- framepos_t end = max_framepos;
+ MusicFrame end (max_framepos, 0);
//use the existing loop start, if any
Location* tpl = transport_loop_location();
@@ -6562,15 +6558,15 @@ Editor::set_loop_end_from_edit_point ()
}
if ((_edit_point == EditAtPlayhead) && _session->transport_rolling()) {
- end = _session->audible_frame();
+ end.frame = _session->audible_frame();
} else {
- end = get_preferred_edit_position();
+ end.frame = get_preferred_edit_position();
}
//snap the selection start/end
snap_to(end);
- set_loop_range (start, end, _("set loop end from EP"));
+ set_loop_range (start, end.frame, _("set loop end from EP"));
}
}
@@ -6985,9 +6981,9 @@ Editor::snap_regions_to_grid ()
pl->freeze();
}
- framepos_t start_frame = (*r)->region()->first_frame ();
- snap_to (start_frame);
- (*r)->region()->set_position (start_frame);
+ MusicFrame start ((*r)->region()->first_frame (), 0);
+ snap_to (start);
+ (*r)->region()->set_position (start.frame, start.division);
}
while (used_playlists.size() > 0) {
@@ -7187,11 +7183,12 @@ Editor::playhead_forward_to_grid ()
return;
}
- framepos_t pos = playhead_cursor->current_frame ();
- if (pos < max_framepos - 1) {
- pos += 2;
+ MusicFrame pos (playhead_cursor->current_frame (), 0);
+
+ if (pos.frame < max_framepos - 1) {
+ pos.frame += 2;
snap_to_internal (pos, RoundUpAlways, false);
- _session->request_locate (pos);
+ _session->request_locate (pos.frame);
}
}
@@ -7203,11 +7200,12 @@ Editor::playhead_backward_to_grid ()
return;
}
- framepos_t pos = playhead_cursor->current_frame ();
- if (pos > 2) {
- pos -= 2;
+ MusicFrame pos (playhead_cursor->current_frame (), 0);
+
+ if (pos.frame > 2) {
+ pos.frame -= 2;
snap_to_internal (pos, RoundDownAlways, false);
- _session->request_locate (pos);
+ _session->request_locate (pos.frame);
}
}
@@ -7472,7 +7470,7 @@ Editor::insert_time (
if (opt == SplitIntersected) {
/* non musical split */
- (*i)->split (pos, 0);
+ (*i)->split (MusicFrame (pos, 0));
}
(*i)->shift (pos, frames, (opt == MoveIntersected), ignore_music_glue);
diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc
index 397ee66cf5..195cc6f828 100644
--- a/gtk2_ardour/midi_region_view.cc
+++ b/gtk2_ardour/midi_region_view.cc
@@ -3426,21 +3426,20 @@ MidiRegionView::nudge_notes (bool forward, bool fine)
/* use grid */
- framepos_t next_pos = ref_point;
-
+ MusicFrame next_pos (ref_point, 0);
if (forward) {
- if (max_framepos - 1 < next_pos) {
- next_pos += 1;
+ if (max_framepos - 1 < next_pos.frame) {
+ next_pos.frame += 1;
}
} else {
- if (next_pos == 0) {
+ if (next_pos.frame == 0) {
return;
}
- next_pos -= 1;
+ next_pos.frame -= 1;
}
trackview.editor().snap_to (next_pos, (forward ? RoundUpAlways : RoundDownAlways), false);
- const framecnt_t distance = ref_point - next_pos;
+ const framecnt_t distance = ref_point - next_pos.frame;
delta = region_frames_to_region_beats (fabs ((double)distance));
}
diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc
index 6bbc813eb2..00764d0b78 100644
--- a/gtk2_ardour/midi_time_axis.cc
+++ b/gtk2_ardour/midi_time_axis.cc
@@ -1646,9 +1646,11 @@ MidiTimeAxisView::automation_child_menu_item (Evoral::Parameter param)
}
boost::shared_ptr<MidiRegion>
-MidiTimeAxisView::add_region (framepos_t pos, framecnt_t length, bool commit, const int32_t sub_num)
+MidiTimeAxisView::add_region (framepos_t f, framecnt_t length, bool commit)
{
Editor* real_editor = dynamic_cast<Editor*> (&_editor);
+ MusicFrame pos (f, 0);
+
if (commit) {
real_editor->begin_reversible_command (Operations::create_region);
}
@@ -1665,8 +1667,8 @@ MidiTimeAxisView::add_region (framepos_t pos, framecnt_t length, bool commit, co
boost::shared_ptr<Region> region = (RegionFactory::create (src, plist));
/* sets beat position */
- region->set_position (pos, sub_num);
- playlist()->add_region (region, pos, 1.0, false, sub_num);
+ region->set_position (pos.frame, pos.division);
+ playlist()->add_region (region, pos.frame, 1.0, false, pos.division);
_session->add_command (new StatefulDiffCommand (playlist()));
if (commit) {
diff --git a/gtk2_ardour/midi_time_axis.h b/gtk2_ardour/midi_time_axis.h
index a75c965413..ac953c8f96 100644
--- a/gtk2_ardour/midi_time_axis.h
+++ b/gtk2_ardour/midi_time_axis.h
@@ -83,7 +83,7 @@ public:
void set_height (uint32_t, TrackHeightMode m = OnlySelf);
- boost::shared_ptr<ARDOUR::MidiRegion> add_region (ARDOUR::framepos_t, ARDOUR::framecnt_t, bool, const int32_t sub_num);
+ boost::shared_ptr<ARDOUR::MidiRegion> add_region (ARDOUR::framepos_t, ARDOUR::framecnt_t, bool);
void show_all_automation (bool apply_to_selection = false);
void show_existing_automation (bool apply_to_selection = false);
diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h
index a63cd049b3..7516d48099 100644
--- a/gtk2_ardour/public_editor.h
+++ b/gtk2_ardour/public_editor.h
@@ -148,10 +148,10 @@ class PublicEditor : public Gtkmm2ext::Tabbable {
* Snap a value according to the current snap setting.
* ensure_snap overrides SnapOff and magnetic snap
*/
- virtual void snap_to (framepos_t& first,
- ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
- bool for_mark = false,
- bool ensure_snap = false) = 0;
+ virtual void snap_to (ARDOUR::MusicFrame& first,
+ ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
+ bool for_mark = false,
+ bool ensure_snap = false) = 0;
/** Undo some transactions.
* @param n Number of transactions to undo.
@@ -320,7 +320,7 @@ class PublicEditor : public Gtkmm2ext::Tabbable {
virtual void restore_editing_space () = 0;
virtual framepos_t get_preferred_edit_position (Editing::EditIgnoreOption = Editing::EDIT_IGNORE_NONE, bool from_context_menu = false, bool from_outside_canvas = false) = 0;
virtual void toggle_meter_updating() = 0;
- virtual void split_regions_at (framepos_t, RegionSelection&, const int32_t sub_num, bool snap) = 0;
+ virtual void split_regions_at (ARDOUR::MusicFrame, RegionSelection&, bool snap) = 0;
virtual void split_region_at_points (boost::shared_ptr<ARDOUR::Region>, ARDOUR::AnalysisFeatureList&, bool can_ferret, bool select_new = false) = 0;
virtual void mouse_add_new_marker (framepos_t where, bool is_cd=false) = 0;
virtual void foreach_time_axis_view (sigc::slot<void,TimeAxisView&>) = 0;
@@ -435,10 +435,10 @@ class PublicEditor : public Gtkmm2ext::Tabbable {
virtual ARDOUR::Location* find_location_from_marker (ArdourMarker *, bool &) const = 0;
virtual ArdourMarker* find_marker_from_location_id (PBD::ID const &, bool) const = 0;
- virtual void snap_to_with_modifier (framepos_t & first,
- GdkEvent const * ev,
- ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
- bool for_mark = false) = 0;
+ virtual void snap_to_with_modifier (ARDOUR::MusicFrame& first,
+ GdkEvent const * ev,
+ ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
+ bool for_mark = false) = 0;
virtual void get_regions_at (RegionSelection &, framepos_t where, TrackViewList const &) const = 0;
virtual void get_regions_after (RegionSelection&, framepos_t where, const TrackViewList& ts) const = 0;
diff --git a/gtk2_ardour/region_view.cc b/gtk2_ardour/region_view.cc
index cc9a5b61ce..9f6ff645ce 100644
--- a/gtk2_ardour/region_view.cc
+++ b/gtk2_ardour/region_view.cc
@@ -947,20 +947,19 @@ frameoffset_t
RegionView::snap_frame_to_frame (frameoffset_t x, bool ensure_snap) const
{
PublicEditor& editor = trackview.editor();
-
/* x is region relative, convert it to global absolute frames */
framepos_t const session_frame = x + _region->position();
/* try a snap in either direction */
- framepos_t frame = session_frame;
+ MusicFrame frame (session_frame, 0);
editor.snap_to (frame, RoundNearest, false, ensure_snap);
/* if we went off the beginning of the region, snap forwards */
- if (frame < _region->position ()) {
- frame = session_frame;
+ if (frame.frame < _region->position ()) {
+ frame.frame = session_frame;
editor.snap_to (frame, RoundUpAlways, false, ensure_snap);
}
/* back to region relative */
- return frame - _region->position();
+ return frame.frame - _region->position();
}
diff --git a/gtk2_ardour/step_editor.cc b/gtk2_ardour/step_editor.cc
index c45c0f4461..ac51076a46 100644
--- a/gtk2_ardour/step_editor.cc
+++ b/gtk2_ardour/step_editor.cc
@@ -116,13 +116,12 @@ StepEditor::prepare_step_edit_region ()
} else {
const Meter& m = _mtv.session()->tempo_map().meter_at_frame (step_edit_insert_position);
-
double baf = max (0.0, _mtv.session()->tempo_map().beat_at_frame (step_edit_insert_position));
double next_bar_in_beats = baf + m.divisions_per_bar();
framecnt_t next_bar_pos = _mtv.session()->tempo_map().frame_at_beat (next_bar_in_beats);
framecnt_t len = next_bar_pos - step_edit_insert_position;
- step_edit_region = _mtv.add_region (step_edit_insert_position, len, true, _editor.get_grid_music_divisions (0));
+ step_edit_region = _mtv.add_region (step_edit_insert_position, len, true);
RegionView* rv = _mtv.midi_view()->find_view (step_edit_region);
step_edit_region_view = dynamic_cast<MidiRegionView*>(rv);
@@ -411,7 +410,7 @@ StepEditor::step_edit_bar_sync ()
}
framepos_t fpos = step_edit_region_view->region_beats_to_absolute_frames (step_edit_beat_pos);
- fpos = _session->tempo_map().round_to_bar (fpos, RoundUpAlways);
+ fpos = _session->tempo_map().round_to_bar (fpos, RoundUpAlways).frame;
step_edit_beat_pos = step_edit_region_view->region_frames_to_region_beats (fpos - step_edit_region->position()).round_up_to_beat();
step_edit_region_view->move_step_edit_cursor (step_edit_beat_pos);
}
diff --git a/gtk2_ardour/tempo_dialog.cc b/gtk2_ardour/tempo_dialog.cc
index f08fb10dda..0b9a071d7d 100644
--- a/gtk2_ardour/tempo_dialog.cc
+++ b/gtk2_ardour/tempo_dialog.cc
@@ -423,7 +423,7 @@ TempoDialog::tap_tempo_focus_out (GdkEventFocus* )
MeterDialog::MeterDialog (TempoMap& map, framepos_t frame, const string&)
: ArdourDialog (_("New Meter"))
{
- frame = map.round_to_bar(frame, RoundNearest);
+ frame = map.round_to_bar(frame, RoundNearest).frame;
Timecode::BBT_Time when (map.bbt_at_frame (frame));
Meter meter (map.meter_at_frame (frame));
diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h
index d25cf0e421..a2c43460ed 100644
--- a/libs/ardour/ardour/audioregion.h
+++ b/libs/ardour/ardour/audioregion.h
@@ -189,7 +189,7 @@ class LIBARDOUR_API AudioRegion : public Region
AudioRegion (boost::shared_ptr<AudioSource>);
AudioRegion (const SourceList &);
AudioRegion (boost::shared_ptr<const AudioRegion>);
- AudioRegion (boost::shared_ptr<const AudioRegion>, frameoffset_t offset, const int32_t sub_num);
+ AudioRegion (boost::shared_ptr<const AudioRegion>, ARDOUR::MusicFrame offset);
AudioRegion (boost::shared_ptr<const AudioRegion>, const SourceList&);
AudioRegion (SourceList &);
diff --git a/libs/ardour/ardour/midi_playlist.h b/libs/ardour/ardour/midi_playlist.h
index 3c031a994f..49eb892e42 100644
--- a/libs/ardour/ardour/midi_playlist.h
+++ b/libs/ardour/ardour/midi_playlist.h
@@ -87,6 +87,7 @@ public:
int set_state (const XMLNode&, int version);
bool destroy_region (boost::shared_ptr<Region>);
+ void _split_region (boost::shared_ptr<Region>, MusicFrame position);
void set_note_mode (NoteMode m) { _note_mode = m; }
diff --git a/libs/ardour/ardour/midi_region.h b/libs/ardour/ardour/midi_region.h
index 8f1edded21..b41f620e87 100644
--- a/libs/ardour/ardour/midi_region.h
+++ b/libs/ardour/ardour/midi_region.h
@@ -127,7 +127,7 @@ class LIBARDOUR_API MidiRegion : public Region
MidiRegion (const SourceList&);
MidiRegion (boost::shared_ptr<const MidiRegion>);
- MidiRegion (boost::shared_ptr<const MidiRegion>, frameoffset_t offset, const int32_t sub_num = 0);
+ MidiRegion (boost::shared_ptr<const MidiRegion>, ARDOUR::MusicFrame offset);
framecnt_t _read_at (const SourceList&, Evoral::EventSink<framepos_t>& dst,
framepos_t position,
@@ -146,6 +146,7 @@ class LIBARDOUR_API MidiRegion : public Region
void recompute_at_end ();
void set_position_internal (framepos_t pos, bool allow_bbt_recompute, const int32_t sub_num);
+ void set_position_music_internal (double qn);
void set_length_internal (framecnt_t len, const int32_t sub_num);
void set_start_internal (framecnt_t, const int32_t sub_num);
void trim_to_internal (framepos_t position, framecnt_t length, const int32_t sub_num);
diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h
index bdf17eabf0..580b245c47 100644
--- a/libs/ardour/ardour/playlist.h
+++ b/libs/ardour/ardour/playlist.h
@@ -135,14 +135,14 @@ public:
/* Editing operations */
- void add_region (boost::shared_ptr<Region>, framepos_t position, float times = 1, bool auto_partition = false, const int32_t sub_num = 0);
+ void add_region (boost::shared_ptr<Region>, framepos_t position, float times = 1, bool auto_partition = false, int32_t sub_num = 0, double quarter_note = 0.0, bool for_music = false);
void remove_region (boost::shared_ptr<Region>);
void get_equivalent_regions (boost::shared_ptr<Region>, std::vector<boost::shared_ptr<Region> >&);
void get_region_list_equivalent_regions (boost::shared_ptr<Region>, std::vector<boost::shared_ptr<Region> >&);
void get_source_equivalent_regions (boost::shared_ptr<Region>, std::vector<boost::shared_ptr<Region> >&);
void replace_region (boost::shared_ptr<Region> old, boost::shared_ptr<Region> newr, framepos_t pos);
- void split_region (boost::shared_ptr<Region>, framepos_t position, const int32_t sub_num);
- void split (framepos_t at, const int32_t sub_num);
+ void split_region (boost::shared_ptr<Region>, MusicFrame position);
+ void split (MusicFrame at);
void shift (framepos_t at, frameoffset_t distance, bool move_intersected, bool ignore_music_glue);
void partition (framepos_t start, framepos_t end, bool cut = false);
void duplicate (boost::shared_ptr<Region>, framepos_t position, float times);
@@ -372,7 +372,7 @@ public:
virtual XMLNode& state (bool);
- bool add_region_internal (boost::shared_ptr<Region>, framepos_t position, const int32_t sub_num = 0);
+ bool add_region_internal (boost::shared_ptr<Region>, framepos_t position, int32_t sub_num = 0, double quarter_note = 0.0, bool for_music = false);
int remove_region_internal (boost::shared_ptr<Region>);
void copy_regions (RegionList&) const;
@@ -390,7 +390,7 @@ public:
void begin_undo ();
void end_undo ();
- void _split_region (boost::shared_ptr<Region>, framepos_t position, const int32_t sub_num);
+ virtual void _split_region (boost::shared_ptr<Region>, MusicFrame position);
typedef std::pair<boost::shared_ptr<Region>, boost::shared_ptr<Region> > TwoRegions;
diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h
index a01ef703f3..85e0442a41 100644
--- a/libs/ardour/ardour/region.h
+++ b/libs/ardour/ardour/region.h
@@ -215,6 +215,7 @@ class LIBARDOUR_API Region
void set_length (framecnt_t, const int32_t sub_num);
void set_start (framepos_t);
void set_position (framepos_t, int32_t sub_num = 0);
+ void set_position_music (double qn);
void set_initial_position (framepos_t);
void special_set_position (framepos_t);
virtual void update_after_tempo_map_change (bool send_change = true);
@@ -346,7 +347,7 @@ class LIBARDOUR_API Region
Region (boost::shared_ptr<const Region>);
/** Construct a region from another region, at an offset within that region */
- Region (boost::shared_ptr<const Region>, frameoffset_t start_offset, const int32_t sub_num);
+ Region (boost::shared_ptr<const Region>, ARDOUR::MusicFrame start_offset);
/** Construct a region as a copy of another region, but with different sources */
Region (boost::shared_ptr<const Region>, const SourceList&);
@@ -364,6 +365,7 @@ class LIBARDOUR_API Region
virtual int _set_state (const XMLNode&, int version, PBD::PropertyChange& what_changed, bool send_signal);
void post_set (const PBD::PropertyChange&);
virtual void set_position_internal (framepos_t pos, bool allow_bbt_recompute, const int32_t sub_num);
+ virtual void set_position_music_internal (double qn);
virtual void set_length_internal (framecnt_t, const int32_t sub_num);
virtual void set_start_internal (framecnt_t, const int32_t sub_num = 0);
bool verify_start_and_length (framepos_t, framecnt_t&);
diff --git a/libs/ardour/ardour/region_factory.h b/libs/ardour/ardour/region_factory.h
index 6971e77242..4b32da0512 100644
--- a/libs/ardour/ardour/region_factory.h
+++ b/libs/ardour/ardour/region_factory.h
@@ -59,7 +59,7 @@ public:
static PBD::Signal1<void,boost::shared_ptr<Region> > CheckNewRegion;
/** create a "pure copy" of Region @param other */
- static boost::shared_ptr<Region> create (boost::shared_ptr<const Region> other, bool announce = false, const int32_t sub_num = 0);
+ static boost::shared_ptr<Region> create (boost::shared_ptr<const Region> other, bool announce = false);
/** create a region from a single Source */
static boost::shared_ptr<Region> create (boost::shared_ptr<Source>,
@@ -72,8 +72,8 @@ public:
static boost::shared_ptr<Region> create (boost::shared_ptr<Region> other,
const PBD::PropertyList&, bool announce = true);
/** create a copy of @param other starting at @param offset within @param other */
- static boost::shared_ptr<Region> create (boost::shared_ptr<Region> other, frameoffset_t offset,
- const PBD::PropertyList&, bool announce = true, const int32_t sub_num = 0);
+ static boost::shared_ptr<Region> create (boost::shared_ptr<Region> other, ARDOUR::MusicFrame offset,
+ const PBD::PropertyList&, bool announce = true);
/** create a "copy" of @param other but using a different set of sources @param srcs */
static boost::shared_ptr<Region> create (boost::shared_ptr<Region> other, const SourceList& srcs,
const PBD::PropertyList&, bool announce = true);
diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h
index a3ab8d68f6..1dce6347a0 100644
--- a/libs/ardour/ardour/tempo.h
+++ b/libs/ardour/ardour/tempo.h
@@ -386,10 +386,10 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
void replace_meter (const MeterSection&, const Meter&, const Timecode::BBT_Time& where, framepos_t frame, PositionLockStyle pls);
- framepos_t round_to_bar (framepos_t frame, RoundMode dir);
- framepos_t round_to_beat (framepos_t frame, RoundMode dir);
+ MusicFrame round_to_bar (framepos_t frame, RoundMode dir);
+ MusicFrame round_to_beat (framepos_t frame, RoundMode dir);
framepos_t round_to_beat_subdivision (framepos_t fr, int sub_num, RoundMode dir);
- framepos_t round_to_quarter_note_subdivision (framepos_t fr, int sub_num, RoundMode dir);
+ MusicFrame round_to_quarter_note_subdivision (framepos_t fr, int sub_num, RoundMode dir);
void set_length (framepos_t frames);
@@ -564,7 +564,7 @@ private:
void recompute_meters (Metrics& metrics);
void recompute_map (Metrics& metrics, framepos_t end = -1);
- framepos_t round_to_type (framepos_t fr, RoundMode dir, BBTPointType);
+ MusicFrame round_to_type (framepos_t fr, RoundMode dir, BBTPointType);
const MeterSection& first_meter() const;
MeterSection& first_meter();
diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h
index 46ef2bade9..0a2fd62f7b 100644
--- a/libs/ardour/ardour/types.h
+++ b/libs/ardour/ardour/types.h
@@ -319,6 +319,27 @@ namespace ARDOUR {
}
};
+ /* used for translating audio frames to an exact musical position using a note divisor.
+ an exact musical position almost never falls exactly on an audio frame, but for sub-sample
+ musical accuracy we need to derive exact musical locations from a frame position
+ the division follows TempoMap::exact_beat_at_frame().
+ division
+ -1 musical location is the bar closest to frame
+ 0 musical location is the musical position of the frame
+ 1 musical location is the BBT beat closest to frame
+ n musical location is the quarter-note division n closest to frame
+ */
+ struct MusicFrame {
+ framepos_t frame;
+ int32_t division;
+
+ MusicFrame (framepos_t f, int32_t d) : frame (f), division (d) {}
+
+ void set (framepos_t f, int32_t d) {frame = f; division = d; }
+
+ MusicFrame operator- (MusicFrame other) { return MusicFrame (frame - other.frame, 0); }
+ };
+
/* XXX: slightly unfortunate that there is this and Evoral::Range<>,
but this has a uint32_t id which Evoral::Range<> does not.
*/
diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc
index bf4c5c6910..7d8c003791 100644
--- a/libs/ardour/audioregion.cc
+++ b/libs/ardour/audioregion.cc
@@ -279,13 +279,13 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other)
assert (_sources.size() == _master_sources.size());
}
-AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, framecnt_t offset, const int32_t sub_num)
- : Region (other, offset, sub_num)
+AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, MusicFrame offset)
+ : Region (other, offset)
, AUDIOREGION_COPY_STATE (other)
/* As far as I can see, the _envelope's times are relative to region position, and have nothing
to do with sources (and hence _start). So when we copy the envelope, we just use the supplied offset.
*/
- , _envelope (Properties::envelope, boost::shared_ptr<AutomationList> (new AutomationList (*other->_envelope.val(), offset, other->_length)))
+ , _envelope (Properties::envelope, boost::shared_ptr<AutomationList> (new AutomationList (*other->_envelope.val(), offset.frame, other->_length)))
, _automatable (other->session())
, _fade_in_suspended (0)
, _fade_out_suspended (0)
diff --git a/libs/ardour/midi_playlist.cc b/libs/ardour/midi_playlist.cc
index 67764d66ae..20c1c77111 100644
--- a/libs/ardour/midi_playlist.cc
+++ b/libs/ardour/midi_playlist.cc
@@ -33,7 +33,9 @@
#include "ardour/midi_region.h"
#include "ardour/midi_source.h"
#include "ardour/midi_state_tracker.h"
+#include "ardour/region_factory.h"
#include "ardour/session.h"
+#include "ardour/tempo.h"
#include "ardour/types.h"
#include "pbd/i18n.h"
@@ -381,6 +383,80 @@ MidiPlaylist::destroy_region (boost::shared_ptr<Region> region)
return changed;
}
+void
+MidiPlaylist::_split_region (boost::shared_ptr<Region> region, MusicFrame playlist_position)
+{
+ if (!region->covers (playlist_position.frame)) {
+ return;
+ }
+
+ if (region->position() == playlist_position.frame ||
+ region->last_frame() == playlist_position.frame) {
+ return;
+ }
+
+ boost::shared_ptr<const MidiRegion> mr = boost::dynamic_pointer_cast<MidiRegion>(region);
+
+ if (mr == 0) {
+ return;
+ }
+
+ boost::shared_ptr<Region> left;
+ boost::shared_ptr<Region> right;
+
+ string before_name;
+ string after_name;
+ const double before_qn = _session.tempo_map().exact_qn_at_frame (playlist_position.frame, playlist_position.division) - region->quarter_note();
+ const double after_qn = mr->length_beats() - before_qn;
+ MusicFrame before (playlist_position.frame - region->position(), playlist_position.division);
+ MusicFrame after (region->length() - before.frame, playlist_position.division);
+
+ /* split doesn't change anything about length, so don't try to splice */
+ bool old_sp = _splicing;
+ _splicing = true;
+
+ RegionFactory::region_name (before_name, region->name(), false);
+
+ {
+ PropertyList plist;
+
+ plist.add (Properties::length, before.frame);
+ plist.add (Properties::length_beats, before_qn);
+ plist.add (Properties::name, before_name);
+ plist.add (Properties::left_of_split, true);
+ plist.add (Properties::layering_index, region->layering_index ());
+ plist.add (Properties::layer, region->layer ());
+
+ /* note: we must use the version of ::create with an offset here,
+ since it supplies that offset to the Region constructor, which
+ is necessary to get audio region gain envelopes right.
+ */
+ left = RegionFactory::create (region, MusicFrame (0, 0), plist, true);
+ }
+
+ RegionFactory::region_name (after_name, region->name(), false);
+
+ {
+ PropertyList plist;
+
+ plist.add (Properties::length, after.frame);
+ plist.add (Properties::length_beats, after_qn);
+ plist.add (Properties::name, after_name);
+ plist.add (Properties::right_of_split, true);
+ plist.add (Properties::layering_index, region->layering_index ());
+ plist.add (Properties::layer, region->layer ());
+
+ /* same note as above */
+ right = RegionFactory::create (region, before, plist, true);
+ }
+
+ add_region_internal (left, region->position(), 0, region->quarter_note(), true);
+ add_region_internal (right, region->position() + before.frame, before.division, region->quarter_note() + before_qn, true);
+
+ remove_region_internal (region);
+
+ _splicing = old_sp;
+}
set<Evoral::Parameter>
MidiPlaylist::contained_automation()
diff --git a/libs/ardour/midi_region.cc b/libs/ardour/midi_region.cc
index 7511aadce8..3c885a8d99 100644
--- a/libs/ardour/midi_region.cc
+++ b/libs/ardour/midi_region.cc
@@ -102,20 +102,20 @@ MidiRegion::MidiRegion (boost::shared_ptr<const MidiRegion> other)
}
/** Create a new MidiRegion that is part of an existing one */
-MidiRegion::MidiRegion (boost::shared_ptr<const MidiRegion> other, frameoffset_t offset, const int32_t sub_num)
- : Region (other, offset, sub_num)
+MidiRegion::MidiRegion (boost::shared_ptr<const MidiRegion> other, MusicFrame offset)
+ : Region (other, offset)
, _start_beats (Properties::start_beats, other->_start_beats)
, _length_beats (Properties::length_beats, other->_length_beats)
{
- if (offset != 0) {
- _start_beats = (_session.tempo_map().exact_qn_at_frame (other->_position + offset, sub_num) - other->_quarter_note) + other->_start_beats;
- update_length_beats (sub_num);
- /* we've potentially shifted _start_beats, now reset _start frames to match */
- _start = _session.tempo_map().frames_between_quarter_notes (_quarter_note - _start_beats, _quarter_note);
- }
register_properties ();
+ const double offset_quarter_note = _session.tempo_map().exact_qn_at_frame (other->_position + offset.frame, offset.division) - other->_quarter_note;
+ if (offset.frame != 0) {
+ _start_beats = other->_start_beats + offset_quarter_note;
+ _length_beats = other->_length_beats - offset_quarter_note;
+ }
+
assert(_name.val().find("/") == string::npos);
midi_source(0)->ModelChanged.connect_same_thread (_source_connection, boost::bind (&MidiRegion::model_changed, this));
model_changed ();
@@ -345,6 +345,24 @@ MidiRegion::set_position_internal (framepos_t pos, bool allow_bbt_recompute, con
}
}
+void
+MidiRegion::set_position_music_internal (double qn)
+{
+ Region::set_position_music_internal (qn);
+ /* set _start to new position in tempo map */
+ _start = _session.tempo_map().frames_between_quarter_notes (quarter_note() - start_beats(), quarter_note());
+
+ if (position_lock_style() == AudioTime) {
+ _length_beats = _session.tempo_map().quarter_note_at_frame (_position + _length) - quarter_note();
+
+ } else {
+ /* leave _length_beats alone, and change _length to reflect the state of things
+ at the new position (tempo map may dictate a different number of frames).
+ */
+ _length = _session.tempo_map().frames_between_quarter_notes (quarter_note(), quarter_note() + length_beats());
+ }
+}
+
framecnt_t
MidiRegion::read_at (Evoral::EventSink<framepos_t>& out,
framepos_t position,
diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc
index 7cea903d5d..99e65ab3e2 100644
--- a/libs/ardour/playlist.cc
+++ b/libs/ardour/playlist.cc
@@ -669,7 +669,7 @@ Playlist::clear_pending ()
/** Note: this calls set_layer (..., DBL_MAX) so it will reset the layering index of region */
void
-Playlist::add_region (boost::shared_ptr<Region> region, framepos_t position, float times, bool auto_partition, const int32_t sub_num)
+Playlist::add_region (boost::shared_ptr<Region> region, framepos_t position, float times, bool auto_partition, int32_t sub_num, double quarter_note, bool for_music)
{
RegionWriteLock rlock (this);
times = fabs (times);
@@ -688,19 +688,18 @@ Playlist::add_region (boost::shared_ptr<Region> region, framepos_t position, flo
}
if (itimes >= 1) {
- add_region_internal (region, pos, sub_num);
+ add_region_internal (region, pos, sub_num, quarter_note, for_music);
set_layer (region, DBL_MAX);
pos += region->length();
--itimes;
}
-
/* note that itimes can be zero if we being asked to just
insert a single fraction of the region.
*/
for (int i = 0; i < itimes; ++i) {
- boost::shared_ptr<Region> copy = RegionFactory::create (region, true, sub_num);
+ boost::shared_ptr<Region> copy = RegionFactory::create (region, true);
add_region_internal (copy, pos, sub_num);
set_layer (copy, DBL_MAX);
pos += region->length();
@@ -743,7 +742,7 @@ Playlist::set_region_ownership ()
}
bool
-Playlist::add_region_internal (boost::shared_ptr<Region> region, framepos_t position, const int32_t sub_num)
+Playlist::add_region_internal (boost::shared_ptr<Region> region, framepos_t position, int32_t sub_num, double quarter_note, bool for_music)
{
if (region->data_type() != _type) {
return false;
@@ -755,8 +754,11 @@ Playlist::add_region_internal (boost::shared_ptr<Region> region, framepos_t posi
boost::shared_ptr<Playlist> foo (shared_from_this());
region->set_playlist (boost::weak_ptr<Playlist>(foo));
}
-
- region->set_position (position, sub_num);
+ if (for_music) {
+ region->set_position_music (quarter_note);
+ } else {
+ region->set_position (position, sub_num);
+ }
regions.insert (upper_bound (regions.begin(), regions.end(), region, cmp), region);
all_regions.insert (region);
@@ -1411,7 +1413,7 @@ Playlist::duplicate_ranges (std::list<AudioRange>& ranges, float times)
}
void
- Playlist::split (framepos_t at, const int32_t sub_num)
+ Playlist::split (MusicFrame at)
{
RegionWriteLock rlock (this);
RegionList copy (regions.rlist());
@@ -1420,33 +1422,34 @@ Playlist::duplicate_ranges (std::list<AudioRange>& ranges, float times)
*/
for (RegionList::iterator r = copy.begin(); r != copy.end(); ++r) {
- _split_region (*r, at, sub_num);
+ _split_region (*r, at);
}
}
void
- Playlist::split_region (boost::shared_ptr<Region> region, framepos_t playlist_position, const int32_t sub_num)
+ Playlist::split_region (boost::shared_ptr<Region> region, MusicFrame playlist_position)
{
RegionWriteLock rl (this);
- _split_region (region, playlist_position, sub_num);
+ _split_region (region, playlist_position);
}
void
- Playlist::_split_region (boost::shared_ptr<Region> region, framepos_t playlist_position, const int32_t sub_num)
+ Playlist::_split_region (boost::shared_ptr<Region> region, MusicFrame playlist_position)
{
- if (!region->covers (playlist_position)) {
+ if (!region->covers (playlist_position.frame)) {
return;
}
- if (region->position() == playlist_position ||
- region->last_frame() == playlist_position) {
+ if (region->position() == playlist_position.frame ||
+ region->last_frame() == playlist_position.frame) {
return;
}
boost::shared_ptr<Region> left;
boost::shared_ptr<Region> right;
- frameoffset_t before;
- frameoffset_t after;
+
+ MusicFrame before (playlist_position.frame - region->position(), playlist_position.division);
+ MusicFrame after (region->length() - before.frame, 0);
string before_name;
string after_name;
@@ -1455,15 +1458,12 @@ Playlist::duplicate_ranges (std::list<AudioRange>& ranges, float times)
bool old_sp = _splicing;
_splicing = true;
- before = playlist_position - region->position();
- after = region->length() - before;
-
RegionFactory::region_name (before_name, region->name(), false);
{
PropertyList plist;
- plist.add (Properties::length, before);
+ plist.add (Properties::length, before.frame);
plist.add (Properties::name, before_name);
plist.add (Properties::left_of_split, true);
plist.add (Properties::layering_index, region->layering_index ());
@@ -1473,7 +1473,7 @@ Playlist::duplicate_ranges (std::list<AudioRange>& ranges, float times)
since it supplies that offset to the Region constructor, which
is necessary to get audio region gain envelopes right.
*/
- left = RegionFactory::create (region, 0, plist, true, sub_num);
+ left = RegionFactory::create (region, MusicFrame (0, 0), plist, true);
}
RegionFactory::region_name (after_name, region->name(), false);
@@ -1481,18 +1481,19 @@ Playlist::duplicate_ranges (std::list<AudioRange>& ranges, float times)
{
PropertyList plist;
- plist.add (Properties::length, after);
+ plist.add (Properties::length, after.frame);
plist.add (Properties::name, after_name);
plist.add (Properties::right_of_split, true);
plist.add (Properties::layering_index, region->layering_index ());
plist.add (Properties::layer, region->layer ());
/* same note as above */
- right = RegionFactory::create (region, before, plist, true, sub_num);
+ right = RegionFactory::create (region, before, plist, true);
}
- add_region_internal (left, region->position());
- add_region_internal (right, region->position() + before);
+ add_region_internal (left, region->position(), 0);
+ add_region_internal (right, region->position() + before.frame, before.division);
+
remove_region_internal (region);
_splicing = old_sp;
diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc
index 0d0a40d17a..4eda001708 100644
--- a/libs/ardour/region.cc
+++ b/libs/ardour/region.cc
@@ -329,7 +329,7 @@ Region::Region (boost::shared_ptr<const Region> other)
the start within \a other is given by \a offset
(i.e. relative to the start of \a other's sources, the start is \a offset + \a other.start()
*/
-Region::Region (boost::shared_ptr<const Region> other, frameoffset_t offset, const int32_t sub_num)
+Region::Region (boost::shared_ptr<const Region> other, MusicFrame offset)
: SessionObject(other->session(), other->name())
, _type (other->data_type())
, REGION_COPY_STATE (other)
@@ -343,7 +343,6 @@ Region::Region (boost::shared_ptr<const Region> other, frameoffset_t offset, con
/* override state that may have been incorrectly inherited from the other region
*/
- _position = other->_position + offset;
_locked = false;
_whole_file = false;
_hidden = false;
@@ -351,9 +350,17 @@ Region::Region (boost::shared_ptr<const Region> other, frameoffset_t offset, con
use_sources (other->_sources);
set_master_sources (other->_master_sources);
- _start = other->_start + offset;
- _beat = _session.tempo_map().exact_beat_at_frame (_position, sub_num);
- _quarter_note = _session.tempo_map().exact_qn_at_frame (_position, sub_num);
+ _position = other->_position + offset.frame;
+ _start = other->_start + offset.frame;
+
+ /* prevent offset of 0 from altering musical position */
+ if (offset.frame != 0) {
+ const double offset_qn = _session.tempo_map().exact_qn_at_frame (other->_position + offset.frame, offset.division)
+ - other->_quarter_note;
+
+ _quarter_note = other->_quarter_note + offset_qn;
+ _beat = _session.tempo_map().beat_at_quarter_note (_quarter_note);
+ }
/* if the other region had a distinct sync point
set, then continue to use it as best we can.
@@ -589,6 +596,13 @@ Region::set_position (framepos_t pos, int32_t sub_num)
return;
}
+ /* do this even if the position is the same. this helps out
+ a GUI that has moved its representation already.
+ */
+ PropertyChange p_and_l;
+
+ p_and_l.add (Properties::position);
+
if (position_lock_style() == AudioTime) {
set_position_internal (pos, true, sub_num);
} else {
@@ -596,67 +610,79 @@ Region::set_position (framepos_t pos, int32_t sub_num)
_beat = _session.tempo_map().exact_beat_at_frame (pos, sub_num);
}
- /* will set pulse accordingly */
+ /* will set quarter note accordingly */
set_position_internal (pos, false, sub_num);
}
- /* do this even if the position is the same. this helps out
- a GUI that has moved its representation already.
- */
- PropertyChange p_and_l;
-
- p_and_l.add (Properties::position);
- /* Currently length change due to position change is only implemented
- for MidiRegion (Region has no length in beats).
- Notify a length change regardless (its more efficient for MidiRegions),
- and when Region has a _length_beats we will need it here anyway).
- */
- p_and_l.add (Properties::length);
+ if (position_lock_style() == MusicTime) {
+ p_and_l.add (Properties::length);
+ }
send_change (p_and_l);
}
-/** A gui may need to create a region, then place it in an initial
- * position determined by the user.
- * When this takes place within one gui operation, we have to reset
- * _last_position to prevent an implied move.
- */
void
-Region::set_initial_position (framepos_t pos)
+Region::set_position_internal (framepos_t pos, bool allow_bbt_recompute, const int32_t sub_num)
{
- if (!can_move()) {
- return;
- }
+ /* We emit a change of Properties::position even if the position hasn't changed
+ (see Region::set_position), so we must always set this up so that
+ e.g. Playlist::notify_region_moved doesn't use an out-of-date last_position.
+ */
+ _last_position = _position;
if (_position != pos) {
_position = pos;
+ if (allow_bbt_recompute) {
+ recompute_position_from_lock_style (sub_num);
+ } else {
+ /* MusicTime dictates that we glue to ardour beats. the pulse may have changed.*/
+ _quarter_note = _session.tempo_map().quarter_note_at_beat (_beat);
+ }
+
/* check that the new _position wouldn't make the current
length impossible - if so, change the length.
XXX is this the right thing to do?
*/
-
if (max_framepos - _length < _position) {
_last_length = _length;
_length = max_framepos - _position;
}
-
- recompute_position_from_lock_style (0);
- /* ensure that this move doesn't cause a range move */
- _last_position = _position;
}
+}
+void
+Region::set_position_music (double qn)
+{
+ if (!can_move()) {
+ return;
+ }
/* do this even if the position is the same. this helps out
a GUI that has moved its representation already.
*/
- send_change (Properties::position);
+ PropertyChange p_and_l;
+
+ p_and_l.add (Properties::position);
+
+ if (!_session.loading()) {
+ _beat = _session.tempo_map().beat_at_quarter_note (qn);
+ }
+
+ /* will set frame accordingly */
+ set_position_music_internal (qn);
+
+ if (position_lock_style() == MusicTime) {
+ p_and_l.add (Properties::length);
+ }
+
+ send_change (p_and_l);
}
void
-Region::set_position_internal (framepos_t pos, bool allow_bbt_recompute, const int32_t sub_num)
+Region::set_position_music_internal (double qn)
{
/* We emit a change of Properties::position even if the position hasn't changed
(see Region::set_position), so we must always set this up so that
@@ -664,26 +690,58 @@ Region::set_position_internal (framepos_t pos, bool allow_bbt_recompute, const i
*/
_last_position = _position;
- if (_position != pos) {
- _position = pos;
+ if (_quarter_note != qn) {
+ _position = _session.tempo_map().frame_at_quarter_note (qn);
+ _quarter_note = qn;
- if (allow_bbt_recompute) {
- recompute_position_from_lock_style (sub_num);
- } else {
- /* MusicTime dictates that we glue to ardour beats. the pulse may have changed.*/
- _quarter_note = _session.tempo_map().quarter_note_at_beat (_beat);
+ /* check that the new _position wouldn't make the current
+ length impossible - if so, change the length.
+
+ XXX is this the right thing to do?
+ */
+ if (max_framepos - _length < _position) {
+ _last_length = _length;
+ _length = max_framepos - _position;
}
+ }
+}
+
+/** A gui may need to create a region, then place it in an initial
+ * position determined by the user.
+ * When this takes place within one gui operation, we have to reset
+ * _last_position to prevent an implied move.
+ */
+void
+Region::set_initial_position (framepos_t pos)
+{
+ if (!can_move()) {
+ return;
+ }
+
+ if (_position != pos) {
+ _position = pos;
/* check that the new _position wouldn't make the current
length impossible - if so, change the length.
XXX is this the right thing to do?
*/
+
if (max_framepos - _length < _position) {
_last_length = _length;
_length = max_framepos - _position;
}
+
+ recompute_position_from_lock_style (0);
+ /* ensure that this move doesn't cause a range move */
+ _last_position = _position;
}
+
+
+ /* do this even if the position is the same. this helps out
+ a GUI that has moved its representation already.
+ */
+ send_change (Properties::position);
}
void
diff --git a/libs/ardour/region_factory.cc b/libs/ardour/region_factory.cc
index 16a9e02e37..78425db88c 100644
--- a/libs/ardour/region_factory.cc
+++ b/libs/ardour/region_factory.cc
@@ -46,7 +46,7 @@ std::map<std::string, PBD::ID> RegionFactory::region_name_map;
RegionFactory::CompoundAssociations RegionFactory::_compound_associations;
boost::shared_ptr<Region>
-RegionFactory::create (boost::shared_ptr<const Region> region, bool announce, const int32_t sub_num)
+RegionFactory::create (boost::shared_ptr<const Region> region, bool announce)
{
boost::shared_ptr<Region> ret;
boost::shared_ptr<const AudioRegion> ar;
@@ -54,7 +54,7 @@ RegionFactory::create (boost::shared_ptr<const Region> region, bool announce, co
if ((ar = boost::dynamic_pointer_cast<const AudioRegion>(region)) != 0) {
- ret = boost::shared_ptr<Region> (new AudioRegion (ar, 0, sub_num));
+ ret = boost::shared_ptr<Region> (new AudioRegion (ar, MusicFrame (0, 0)));
} else if ((mr = boost::dynamic_pointer_cast<const MidiRegion>(region)) != 0) {
@@ -71,7 +71,7 @@ RegionFactory::create (boost::shared_ptr<const Region> region, bool announce, co
source->set_ancestor_name(mr->sources().front()->name());
ret = mr->clone(source);
} else {
- ret = boost::shared_ptr<Region> (new MidiRegion (mr, 0, sub_num));
+ ret = boost::shared_ptr<Region> (new MidiRegion (mr, MusicFrame (0, 0)));
}
} else {
@@ -87,8 +87,6 @@ RegionFactory::create (boost::shared_ptr<const Region> region, bool announce, co
ret->set_position_lock_style (MusicTime);
}
- ret->set_position (region->position(), sub_num);
-
/* pure copy constructor - no property list */
if (announce) {
map_add (ret);
@@ -144,7 +142,7 @@ RegionFactory::create (boost::shared_ptr<Region> region, const PropertyList& pli
}
boost::shared_ptr<Region>
-RegionFactory::create (boost::shared_ptr<Region> region, frameoffset_t offset, const PropertyList& plist, bool announce, const int32_t sub_num)
+RegionFactory::create (boost::shared_ptr<Region> region, MusicFrame offset, const PropertyList& plist, bool announce)
{
boost::shared_ptr<Region> ret;
boost::shared_ptr<const AudioRegion> other_a;
@@ -152,11 +150,11 @@ RegionFactory::create (boost::shared_ptr<Region> region, frameoffset_t offset, c
if ((other_a = boost::dynamic_pointer_cast<AudioRegion>(region)) != 0) {
- ret = boost::shared_ptr<Region> (new AudioRegion (other_a, offset, sub_num));
+ ret = boost::shared_ptr<Region> (new AudioRegion (other_a, offset));
} else if ((other_m = boost::dynamic_pointer_cast<MidiRegion>(region)) != 0) {
- ret = boost::shared_ptr<Region> (new MidiRegion (other_m, offset, sub_num));
+ ret = boost::shared_ptr<Region> (new MidiRegion (other_m, offset));
} else {
fatal << _("programming error: RegionFactory::create() called with unknown Region type")
diff --git a/libs/ardour/strip_silence.cc b/libs/ardour/strip_silence.cc
index 3141f422a8..1cbb81a3ed 100644
--- a/libs/ardour/strip_silence.cc
+++ b/libs/ardour/strip_silence.cc
@@ -116,7 +116,7 @@ StripSilence::run (boost::shared_ptr<Region> r, Progress* progress)
plist.add (Properties::position, r->position() + (i->first - r->start()));
copy = boost::dynamic_pointer_cast<AudioRegion> (
- RegionFactory::create (region, (i->first - r->start()), plist)
+ RegionFactory::create (region, MusicFrame (i->first - r->start(), 0), plist)
);
copy->set_name (RegionFactory::new_region_name (region->name ()));
diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc
index 469bbac4de..d690896c15 100644
--- a/libs/ardour/tempo.cc
+++ b/libs/ardour/tempo.cc
@@ -3676,13 +3676,13 @@ TempoMap::bbt_duration_at (framepos_t pos, const BBT_Time& bbt, int dir)
return 0;
}
-framepos_t
+MusicFrame
TempoMap::round_to_bar (framepos_t fr, RoundMode dir)
{
return round_to_type (fr, dir, Bar);
}
-framepos_t
+MusicFrame
TempoMap::round_to_beat (framepos_t fr, RoundMode dir)
{
return round_to_type (fr, dir, Beat);
@@ -3784,7 +3784,7 @@ TempoMap::round_to_beat_subdivision (framepos_t fr, int sub_num, RoundMode dir)
return ret_frame;
}
-framepos_t
+MusicFrame
TempoMap::round_to_quarter_note_subdivision (framepos_t fr, int sub_num, RoundMode dir)
{
Glib::Threads::RWLock::ReaderLock lm (lock);
@@ -3865,7 +3865,7 @@ TempoMap::round_to_quarter_note_subdivision (framepos_t fr, int sub_num, RoundMo
if (rem > ticks) {
if (beats == 0) {
/* can't go backwards past zero, so ... */
- return 0;
+ return MusicFrame (0, 0);
}
/* step back to previous beat */
--beats;
@@ -3880,35 +3880,46 @@ TempoMap::round_to_quarter_note_subdivision (framepos_t fr, int sub_num, RoundMo
}
}
- const framepos_t ret_frame = frame_at_minute (minute_at_pulse_locked (_metrics, (beats + (ticks / BBT_Time::ticks_per_beat)) / 4.0));
+ MusicFrame ret (0, 0);
+ ret.frame = frame_at_minute (minute_at_pulse_locked (_metrics, (beats + (ticks / BBT_Time::ticks_per_beat)) / 4.0));
+ ret.division = sub_num;
- return ret_frame;
+ return ret;
}
-framepos_t
+MusicFrame
TempoMap::round_to_type (framepos_t frame, RoundMode dir, BBTPointType type)
{
Glib::Threads::RWLock::ReaderLock lm (lock);
-
- const double beat_at_framepos = max (0.0, beat_at_minute_locked (_metrics, minute_at_frame (frame)));
+ const double minute = minute_at_frame (frame);
+ const double beat_at_framepos = max (0.0, beat_at_minute_locked (_metrics, minute));
BBT_Time bbt (bbt_at_beat_locked (_metrics, beat_at_framepos));
+ MusicFrame ret (0, 0);
switch (type) {
case Bar:
+ ret.division = -1;
+
if (dir < 0) {
/* find bar previous to 'frame' */
if (bbt.bars > 0)
--bbt.bars;
bbt.beats = 1;
bbt.ticks = 0;
- return frame_at_minute (minute_at_bbt_locked (_metrics, bbt));
+
+ ret.frame = frame_at_minute (minute_at_bbt_locked (_metrics, bbt));
+
+ return ret;
} else if (dir > 0) {
/* find bar following 'frame' */
++bbt.bars;
bbt.beats = 1;
bbt.ticks = 0;
- return frame_at_minute (minute_at_bbt_locked (_metrics, bbt));
+
+ ret.frame = frame_at_minute (minute_at_bbt_locked (_metrics, bbt));
+
+ return ret;
} else {
/* true rounding: find nearest bar */
framepos_t raw_ft = frame_at_minute (minute_at_bbt_locked (_metrics, bbt));
@@ -3919,26 +3930,39 @@ TempoMap::round_to_type (framepos_t frame, RoundMode dir, BBTPointType type)
framepos_t next_ft = frame_at_minute (minute_at_bbt_locked (_metrics, bbt));
if ((raw_ft - prev_ft) > (next_ft - prev_ft) / 2) {
- return next_ft;
+ ret.frame = next_ft;
+
+ return ret;
} else {
- return prev_ft;
+ --bbt.bars;
+ ret.frame = prev_ft;
+
+ return ret;
}
}
break;
case Beat:
+ ret.division = 1;
+
if (dir < 0) {
- return frame_at_minute (minute_at_beat_locked (_metrics, floor (beat_at_framepos)));
+ ret.frame = frame_at_minute (minute_at_beat_locked (_metrics, floor (beat_at_framepos)));
+
+ return ret;
} else if (dir > 0) {
- return frame_at_minute (minute_at_beat_locked (_metrics, ceil (beat_at_framepos)));
+ ret.frame = frame_at_minute (minute_at_beat_locked (_metrics, ceil (beat_at_framepos)));
+
+ return ret;
} else {
- return frame_at_minute (minute_at_beat_locked (_metrics, floor (beat_at_framepos + 0.5)));
+ ret.frame = frame_at_minute (minute_at_beat_locked (_metrics, floor (beat_at_framepos + 0.5)));
+
+ return ret;
}
break;
}
- return 0;
+ return MusicFrame (0, 0);
}
void