clicked_control_point = 0;
last_update_frame = 0;
pre_press_cursor = 0;
+ last_paste_pos = 0;
+ paste_count = 0;
_drags = new DragManager (this);
lock_dialog = 0;
ruler_dialog = 0;
sfbrowser = 0;
- location_marker_color = ARDOUR_UI::config()->get_canvasvar_LocationMarker();
- location_range_color = ARDOUR_UI::config()->get_canvasvar_LocationRange();
- location_cd_marker_color = ARDOUR_UI::config()->get_canvasvar_LocationCDMarker();
- location_loop_color = ARDOUR_UI::config()->get_canvasvar_LocationLoop();
- location_punch_color = ARDOUR_UI::config()->get_canvasvar_LocationPunch();
+ location_marker_color = ARDOUR_UI::config()->get_LocationMarker();
+ location_range_color = ARDOUR_UI::config()->get_LocationRange();
+ location_cd_marker_color = ARDOUR_UI::config()->get_LocationCDMarker();
+ location_loop_color = ARDOUR_UI::config()->get_LocationLoop();
+ location_punch_color = ARDOUR_UI::config()->get_LocationPunch();
zoom_focus = ZoomFocusLeft;
_edit_point = EditAtMouse;
_dragging_playhead = true;
}
- if ((fraction < 0.0f) && (*_control_scroll_target < (framepos_t) fabs(step))) {
+ if ((fraction < 0.0f) && (*_control_scroll_target <= (framepos_t) fabs(step))) {
*_control_scroll_target = 0;
} else if ((fraction > 0.0f) && (max_framepos - *_control_scroll_target < step)) {
*_control_scroll_target = max_framepos - (current_page_samples()*2); // allow room for slop in where the PH is on the screen
} else {
- *_control_scroll_target += (framepos_t) floor (step);
+ *_control_scroll_target += (framepos_t) trunc (step);
}
/* move visuals, we'll catch up with it later */
_session->locations()->added.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_new_location, this, _1), gui_context());
_session->locations()->removed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::location_gone, this, _1), gui_context());
_session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
- _session->locations()->StateChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
_session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
playhead_cursor->show ();
bool changed = (_edit_point != ep);
_edit_point = ep;
- string str = edit_point_strings[(int)ep];
-
if (Profile->get_mixbus())
if (ep == EditAtSelectedMarker)
ep = EditAtPlayhead;
-
+
+ string str = edit_point_strings[(int)ep];
if (str != edit_point_selector.get_text ()) {
edit_point_selector.set_text (str);
}
if (_session && (prop = node.property ("playhead"))) {
framepos_t pos;
sscanf (prop->value().c_str(), "%" PRIi64, &pos);
- playhead_cursor->set_position (pos);
+ if (pos >= 0) {
+ playhead_cursor->set_position (pos);
+ } else {
+ warning << _("Playhead position stored with a negative value - ignored (use zero instead)") << endmsg;
+ playhead_cursor->set_position (0);
+ }
} else {
playhead_cursor->set_position (0);
}
* @param event Event to get current key modifier information from, or 0.
*/
void
-Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, int32_t direction, bool for_mark)
+Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, RoundMode direction, bool for_mark)
{
if (!_session || !event) {
return;
}
void
-Editor::snap_to (framepos_t& start, int32_t direction, bool for_mark)
+Editor::snap_to (framepos_t& start, RoundMode direction, bool for_mark)
{
if (!_session || _snap_mode == SnapOff) {
return;
}
void
-Editor::timecode_snap_to_internal (framepos_t& start, int32_t direction, bool /*for_mark*/)
+Editor::timecode_snap_to_internal (framepos_t& start, RoundMode direction, bool /*for_mark*/)
{
const framepos_t one_timecode_second = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame());
framepos_t one_timecode_minute = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame() * 60);
switch (_snap_type) {
case SnapToTimecodeFrame:
- if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
+ if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
+ fmod((double)start, (double)_session->frames_per_timecode_frame()) == 0) {
+ /* start is already on a whole timecode frame, do nothing */
+ } else if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
start = (framepos_t) (ceil ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
} else {
start = (framepos_t) (floor ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
} else {
start -= _session->config.get_timecode_offset ();
}
- if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
+ if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
+ (start % one_timecode_second == 0)) {
+ /* start is already on a whole second, do nothing */
+ } else if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
start = (framepos_t) ceil ((double) start / one_timecode_second) * one_timecode_second;
} else {
start = (framepos_t) floor ((double) start / one_timecode_second) * one_timecode_second;
} else {
start -= _session->config.get_timecode_offset ();
}
- if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
+ if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
+ (start % one_timecode_minute == 0)) {
+ /* start is already on a whole minute, do nothing */
+ } else if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
start = (framepos_t) ceil ((double) start / one_timecode_minute) * one_timecode_minute;
} else {
start = (framepos_t) floor ((double) start / one_timecode_minute) * one_timecode_minute;
break;
default:
fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg;
- /*NOTREACHED*/
+ abort(); /*NOTREACHED*/
}
}
void
-Editor::snap_to_internal (framepos_t& start, int32_t direction, bool for_mark)
+Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark)
{
const framepos_t one_second = _session->frame_rate();
const framepos_t one_minute = _session->frame_rate() * 60;
return timecode_snap_to_internal (start, direction, for_mark);
case SnapToCDFrame:
- if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
+ if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
+ start % (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 {
start = (framepos_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
break;
case SnapToSeconds:
- if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
+ if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
+ start % 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 {
start = (framepos_t) floor ((double) start / one_second) * one_second;
break;
case SnapToMinutes:
- if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
+ if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
+ start % 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 {
start = (framepos_t) floor ((double) start / one_minute) * one_minute;
mouse_mode_size_group->add_widget (mouse_move_button);
mouse_mode_size_group->add_widget (mouse_cut_button);
mouse_mode_size_group->add_widget (mouse_select_button);
- mouse_mode_size_group->add_widget (mouse_zoom_button);
mouse_mode_size_group->add_widget (mouse_gain_button);
mouse_mode_size_group->add_widget (mouse_timefx_button);
mouse_mode_size_group->add_widget (mouse_audition_button);
if (!ARDOUR::Profile->get_mixbus()) {
mouse_mode_hbox->pack_start (mouse_cut_button, false, false);
- mouse_mode_hbox->pack_start (mouse_zoom_button, false, false);
}
if (!ARDOUR::Profile->get_trx()) {
ARDOUR_UI::instance()->set_tip (mouse_select_button, _("Range Mode (select/move Ranges)"));
ARDOUR_UI::instance()->set_tip (mouse_draw_button, _("Draw/Edit MIDI Notes"));
ARDOUR_UI::instance()->set_tip (mouse_gain_button, _("Draw Region Gain"));
- ARDOUR_UI::instance()->set_tip (mouse_zoom_button, _("Select Zoom Range"));
ARDOUR_UI::instance()->set_tip (mouse_timefx_button, _("Stretch/Shrink Regions and MIDI Notes"));
ARDOUR_UI::instance()->set_tip (mouse_audition_button, _("Listen to Specific Regions"));
ARDOUR_UI::instance()->set_tip (internal_edit_button, _("Note Level Editing"));
return *_playlist_selector;
}
+framecnt_t
+Editor::get_paste_offset (framepos_t pos, unsigned paste_count, framecnt_t duration)
+{
+ if (paste_count == 0) {
+ /* don't bother calculating an offset that will be zero anyway */
+ return 0;
+ }
+
+ /* calculate basic unsnapped multi-paste offset */
+ framecnt_t offset = paste_count * duration;
+
+ /* snap offset so pos + offset is aligned to the grid */
+ framepos_t offset_pos = pos + offset;
+ snap_to(offset_pos, RoundUpMaybe);
+ offset = offset_pos - pos;
+
+ return offset;
+}
+
Evoral::MusicalTime
Editor::get_grid_type_as_beats (bool& success, framepos_t position)
{
switch (_snap_type) {
case SnapToBeat:
- return 1.0;
+ return Evoral::MusicalTime(1.0);
break;
case SnapToBeatDiv128:
- return 1.0/128.0;
+ return Evoral::MusicalTime(1.0/128.0);
break;
case SnapToBeatDiv64:
- return 1.0/64.0;
+ return Evoral::MusicalTime(1.0/64.0);
break;
case SnapToBeatDiv32:
- return 1.0/32.0;
+ return Evoral::MusicalTime(1.0/32.0);
break;
case SnapToBeatDiv28:
- return 1.0/28.0;
+ return Evoral::MusicalTime(1.0/28.0);
break;
case SnapToBeatDiv24:
- return 1.0/24.0;
+ return Evoral::MusicalTime(1.0/24.0);
break;
case SnapToBeatDiv20:
- return 1.0/20.0;
+ return Evoral::MusicalTime(1.0/20.0);
break;
case SnapToBeatDiv16:
- return 1.0/16.0;
+ return Evoral::MusicalTime(1.0/16.0);
break;
case SnapToBeatDiv14:
- return 1.0/14.0;
+ return Evoral::MusicalTime(1.0/14.0);
break;
case SnapToBeatDiv12:
- return 1.0/12.0;
+ return Evoral::MusicalTime(1.0/12.0);
break;
case SnapToBeatDiv10:
- return 1.0/10.0;
+ return Evoral::MusicalTime(1.0/10.0);
break;
case SnapToBeatDiv8:
- return 1.0/8.0;
+ return Evoral::MusicalTime(1.0/8.0);
break;
case SnapToBeatDiv7:
- return 1.0/7.0;
+ return Evoral::MusicalTime(1.0/7.0);
break;
case SnapToBeatDiv6:
- return 1.0/6.0;
+ return Evoral::MusicalTime(1.0/6.0);
break;
case SnapToBeatDiv5:
- return 1.0/5.0;
+ return Evoral::MusicalTime(1.0/5.0);
break;
case SnapToBeatDiv4:
- return 1.0/4.0;
+ return Evoral::MusicalTime(1.0/4.0);
break;
case SnapToBeatDiv3:
- return 1.0/3.0;
+ return Evoral::MusicalTime(1.0/3.0);
break;
case SnapToBeatDiv2:
- return 1.0/2.0;
+ return Evoral::MusicalTime(1.0/2.0);
break;
case SnapToBar:
if (_session) {
- return _session->tempo_map().meter_at (position).divisions_per_bar();
+ return Evoral::MusicalTime(_session->tempo_map().meter_at (position).divisions_per_bar());
}
break;
break;
}
- return 0.0;
+ return Evoral::MusicalTime();
}
framecnt_t
redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
- use_visual_state (*vs);
+ if (vs) {
+ use_visual_state (*vs);
+ }
}
void
VisualState* vs = redo_visual_stack.back();
redo_visual_stack.pop_back();
- undo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
+ // can 'vs' really be 0? Is there a place that puts NULL pointers onto the stack?
+ // why do we check here?
+ undo_visual_stack.push_back (current_visual_state (vs ? (vs->gui_state != 0) : false));
- use_visual_state (*vs);
+ if (vs) {
+ use_visual_state (*vs);
+ }
}
void
{
if (pending_visual_change.idle_handler_id < 0) {
// see comment in add_to_idle_resize above.
- pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE + 20, _idle_visual_changer, this, NULL);
+ pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_visual_changer, this, NULL);
pending_visual_change.being_handled = false;
}
}