X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor_ops.cc;h=d79f1df47b7410d770d2a54b0f759933b5a0e96f;hb=7b155267505af3fedffc7972b08cb784c97b7e74;hp=96289280046f52d8770891ff9790ac5e2c988dbf;hpb=e258b2622a4386b405c2216d79b34887c3ed55bf;p=ardour.git diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index 9628928004..d79f1df47b 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -55,8 +55,10 @@ #include "ardour/quantize.h" #include "ardour/strip_silence.h" #include "ardour/route_group.h" +#include "ardour/operations.h" #include "ardour_ui.h" +#include "debug.h" #include "editor.h" #include "time_axis_view.h" #include "route_time_axis.h" @@ -80,6 +82,11 @@ #include "editor_regions.h" #include "quantize_dialog.h" #include "interthread_progress_window.h" +#include "insert_time_dialog.h" +#include "normalize_dialog.h" +#include "editor_cursors.h" +#include "mouse_cursors.h" +#include "patch_change_dialog.h" #include "i18n.h" @@ -112,8 +119,10 @@ Editor::redo (uint32_t n) } void -Editor::split_regions_at (nframes64_t where, RegionSelection& regions) +Editor::split_regions_at (framepos_t where, RegionSelection& regions) { + bool frozen = false; + list > used_playlists; if (regions.empty()) { @@ -136,6 +145,9 @@ Editor::split_regions_at (nframes64_t where, RegionSelection& regions) } } else { snap_to (where); + + frozen = true; + EditorFreeze(); /* Emit Signal */ } for (RegionSelection::iterator a = regions.begin(); a != regions.end(); ) { @@ -156,11 +168,10 @@ Editor::split_regions_at (nframes64_t where, RegionSelection& regions) boost::shared_ptr pl = (*a)->region()->playlist(); - if (!pl) { - cerr << "region " << (*a)->region()->name() << " has no playlist!\n"; - a = tmp; - continue; - } + if (!pl) { + a = tmp; + continue; + } if (!pl->frozen()) { /* we haven't seen this playlist before */ @@ -171,7 +182,7 @@ Editor::split_regions_at (nframes64_t where, RegionSelection& regions) } if (pl) { - pl->clear_history (); + pl->clear_changes (); pl->split_region ((*a)->region(), where); _session->add_command (new StatefulDiffCommand (pl)); } @@ -186,6 +197,10 @@ Editor::split_regions_at (nframes64_t where, RegionSelection& regions) } commit_reversible_command (); + + if (frozen){ + EditorThaw(); /* Emit Signal */ + } } boost::shared_ptr @@ -193,7 +208,7 @@ Editor::select_region_for_operation (int /*dir*/, TimeAxisView **tv) { RegionView* rv; boost::shared_ptr region; - nframes64_t start = 0; + framepos_t start = 0; if (selection->time.start () == selection->time.end_frame ()) { @@ -236,7 +251,7 @@ Editor::extend_selection_to_end_of_region (bool next) { TimeAxisView *tv; boost::shared_ptr region; - nframes64_t start; + framepos_t start; if ((region = select_region_for_operation (next ? 1 : 0, &tv)) == 0) { return; @@ -258,7 +273,7 @@ Editor::extend_selection_to_start_of_region (bool previous) { TimeAxisView *tv; boost::shared_ptr region; - nframes64_t end; + framepos_t end; if ((region = select_region_for_operation (previous ? -1 : 0, &tv)) == 0) { return; @@ -303,13 +318,14 @@ Editor::nudge_backward_release (GdkEventButton* ev) void Editor::nudge_forward (bool next, bool force_playhead) { - nframes64_t distance; - nframes64_t next_distance; - RegionSelection rs; + framepos_t distance; + framepos_t next_distance; - get_regions_for_action (rs); + if (!_session) { + return; + } - if (!_session) return; + RegionSelection rs = get_regions_from_selection_and_entered (); if (!force_playhead && !rs.empty()) { @@ -324,7 +340,7 @@ Editor::nudge_forward (bool next, bool force_playhead) distance = next_distance; } - r->clear_history (); + r->clear_changes (); r->set_position (r->position() + distance, this); _session->add_command (new StatefulDiffCommand (r)); } @@ -351,20 +367,20 @@ Editor::nudge_forward (bool next, bool force_playhead) if (next) { distance = next_distance; } - if (max_frames - distance > loc->start() + loc->length()) { + if (max_framepos - distance > loc->start() + loc->length()) { loc->set_start (loc->start() + distance); } else { - loc->set_start (max_frames - loc->length()); + loc->set_start (max_framepos - loc->length()); } } else { distance = get_nudge_distance (loc->end(), next_distance); if (next) { distance = next_distance; } - if (max_frames - distance > loc->end()) { + if (max_framepos - distance > loc->end()) { loc->set_end (loc->end() + distance); } else { - loc->set_end (max_frames); + loc->set_end (max_framepos); } } XMLNode& after (loc->get_state()); @@ -383,13 +399,14 @@ Editor::nudge_forward (bool next, bool force_playhead) void Editor::nudge_backward (bool next, bool force_playhead) { - nframes64_t distance; - nframes64_t next_distance; - RegionSelection rs; + framepos_t distance; + framepos_t next_distance; - get_regions_for_action (rs); + if (!_session) { + return; + } - if (!_session) return; + RegionSelection rs = get_regions_from_selection_and_entered (); if (!force_playhead && !rs.empty()) { @@ -404,7 +421,7 @@ Editor::nudge_backward (bool next, bool force_playhead) distance = next_distance; } - r->clear_history (); + r->clear_changes (); if (r->position() > distance) { r->set_position (r->position() - distance, this); @@ -476,63 +493,54 @@ Editor::nudge_backward (bool next, bool force_playhead) void Editor::nudge_forward_capture_offset () { - nframes64_t distance; - RegionSelection rs; - - get_regions_for_action (rs); - - if (!_session) return; - - if (!rs.empty()) { - - begin_reversible_command (_("nudge forward")); - - distance = _session->worst_output_latency(); - - for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { - boost::shared_ptr r ((*i)->region()); - - r->clear_history (); - r->set_position (r->position() + distance, this); - _session->add_command(new StatefulDiffCommand (r)); - } - - commit_reversible_command (); + RegionSelection rs = get_regions_from_selection_and_entered (); + + if (!_session || rs.empty()) { + return; + } + begin_reversible_command (_("nudge forward")); + + framepos_t const distance = _session->worst_output_latency(); + + for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { + boost::shared_ptr r ((*i)->region()); + + r->clear_changes (); + r->set_position (r->position() + distance, this); + _session->add_command(new StatefulDiffCommand (r)); } + + commit_reversible_command (); } void Editor::nudge_backward_capture_offset () { - nframes64_t distance; - RegionSelection rs; - - get_regions_for_action (rs); - - if (!_session) return; + RegionSelection rs = get_regions_from_selection_and_entered (); - if (!rs.empty()) { - - begin_reversible_command (_("nudge forward")); - - distance = _session->worst_output_latency(); - - for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { - boost::shared_ptr r ((*i)->region()); + if (!_session || rs.empty()) { + return; + } - r->clear_history (); + begin_reversible_command (_("nudge forward")); + + framepos_t const distance = _session->worst_output_latency(); - if (r->position() > distance) { - r->set_position (r->position() - distance, this); - } else { - r->set_position (0, this); - } - _session->add_command(new StatefulDiffCommand (r)); + for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { + boost::shared_ptr r ((*i)->region()); + + r->clear_changes (); + + if (r->position() > distance) { + r->set_position (r->position() - distance, this); + } else { + r->set_position (0, this); } - - commit_reversible_command (); + _session->add_command(new StatefulDiffCommand (r)); } + + commit_reversible_command (); } /* DISPLAY MOTION */ @@ -553,7 +561,7 @@ Editor::move_to_end () void Editor::build_region_boundary_cache () { - nframes64_t pos = 0; + framepos_t pos = 0; vector interesting_points; boost::shared_ptr r; TrackViewList tracks; @@ -596,8 +604,8 @@ Editor::build_region_boundary_cache () while (pos < _session->current_end_frame() && !at_end) { - nframes64_t rpos; - nframes64_t lpos = max_frames; + framepos_t rpos; + framepos_t lpos = max_framepos; for (vector::iterator p = interesting_points.begin(); p != interesting_points.end(); ++p) { @@ -620,7 +628,6 @@ Editor::build_region_boundary_cache () case SyncPoint: rpos = r->sync_position (); - //r->adjust_to_sync (r->first_frame()); break; default: @@ -646,7 +653,7 @@ Editor::build_region_boundary_cache () to sort later. */ - vector::iterator ri; + vector::iterator ri; for (ri = region_boundary_cache.begin(); ri != region_boundary_cache.end(); ++ri) { if (*ri == rpos) { @@ -668,20 +675,20 @@ Editor::build_region_boundary_cache () } boost::shared_ptr -Editor::find_next_region (nframes64_t frame, RegionPoint point, int32_t dir, TrackViewList& tracks, TimeAxisView **ontrack) +Editor::find_next_region (framepos_t frame, RegionPoint point, int32_t dir, TrackViewList& tracks, TimeAxisView **ontrack) { TrackViewList::iterator i; - nframes64_t closest = max_frames; + framepos_t closest = max_framepos; boost::shared_ptr ret; - nframes64_t rpos = 0; + framepos_t rpos = 0; float track_speed; - nframes64_t track_frame; + framepos_t track_frame; RouteTimeAxisView *rtav; for (i = tracks.begin(); i != tracks.end(); ++i) { - nframes64_t distance; + framecnt_t distance; boost::shared_ptr r; track_speed = 1.0f; @@ -707,7 +714,6 @@ Editor::find_next_region (nframes64_t frame, RegionPoint point, int32_t dir, Tra case SyncPoint: rpos = r->sync_position (); - // r->adjust_to_sync (r->first_frame()); break; } @@ -731,17 +737,16 @@ Editor::find_next_region (nframes64_t frame, RegionPoint point, int32_t dir, Tra return ret; } -nframes64_t -Editor::find_next_region_boundary (nframes64_t pos, int32_t dir, const TrackViewList& tracks) +framepos_t +Editor::find_next_region_boundary (framepos_t pos, int32_t dir, const TrackViewList& tracks) { - nframes64_t distance = max_frames; - nframes64_t current_nearest = -1; - + framecnt_t distance = max_framepos; + framepos_t current_nearest = -1; for (TrackViewList::const_iterator i = tracks.begin(); i != tracks.end(); ++i) { - nframes64_t contender; - nframes64_t d; - + framepos_t contender; + framecnt_t d; + RouteTimeAxisView* rtv = dynamic_cast (*i); if (!rtv) { @@ -763,10 +768,10 @@ Editor::find_next_region_boundary (nframes64_t pos, int32_t dir, const TrackView return current_nearest; } -nframes64_t -Editor::get_region_boundary (nframes64_t pos, int32_t dir, bool with_selection, bool only_onscreen) +framepos_t +Editor::get_region_boundary (framepos_t pos, int32_t dir, bool with_selection, bool only_onscreen) { - nframes64_t target; + framepos_t target; TrackViewList tvl; if (with_selection && Config->get_region_boundaries_from_selected_tracks()) { @@ -801,8 +806,8 @@ Editor::get_region_boundary (nframes64_t pos, int32_t dir, bool with_selection, void Editor::cursor_to_region_boundary (bool with_selection, int32_t dir) { - nframes64_t pos = playhead_cursor->current_frame; - nframes64_t target; + framepos_t pos = playhead_cursor->current_frame; + framepos_t target; if (!_session) { return; @@ -836,7 +841,7 @@ void Editor::cursor_to_region_point (EditorCursor* cursor, RegionPoint point, int32_t dir) { boost::shared_ptr r; - nframes64_t pos = cursor->current_frame; + framepos_t pos = cursor->current_frame; if (!_session) { return; @@ -868,7 +873,7 @@ Editor::cursor_to_region_point (EditorCursor* cursor, RegionPoint point, int32_t return; } - switch (point){ + switch (point) { case Start: pos = r->first_frame (); break; @@ -879,7 +884,6 @@ Editor::cursor_to_region_point (EditorCursor* cursor, RegionPoint point, int32_t case SyncPoint: pos = r->sync_position (); - // r->adjust_to_sync (r->first_frame()); break; } @@ -916,15 +920,12 @@ Editor::cursor_to_previous_region_point (EditorCursor* cursor, RegionPoint point void Editor::cursor_to_selection_start (EditorCursor *cursor) { - nframes64_t pos = 0; - RegionSelection rs; - - get_regions_for_action (rs); + framepos_t pos = 0; switch (mouse_mode) { case MouseObject: - if (!rs.empty()) { - pos = rs.start(); + if (!selection->regions.empty()) { + pos = selection->regions.start(); } break; @@ -948,15 +949,12 @@ Editor::cursor_to_selection_start (EditorCursor *cursor) void Editor::cursor_to_selection_end (EditorCursor *cursor) { - nframes64_t pos = 0; - RegionSelection rs; - - get_regions_for_action (rs); + framepos_t pos = 0; switch (mouse_mode) { case MouseObject: - if (!rs.empty()) { - pos = rs.end_frame(); + if (!selection->regions.empty()) { + pos = selection->regions.end_frame(); } break; @@ -980,7 +978,7 @@ Editor::cursor_to_selection_end (EditorCursor *cursor) void Editor::selected_marker_to_region_boundary (bool with_selection, int32_t dir) { - nframes64_t target; + framepos_t target; Location* loc; bool ignored; @@ -989,7 +987,7 @@ Editor::selected_marker_to_region_boundary (bool with_selection, int32_t dir) } if (selection->markers.empty()) { - nframes64_t mouse; + framepos_t mouse; bool ignored; if (!mouse_frame (mouse, ignored)) { @@ -1003,7 +1001,7 @@ Editor::selected_marker_to_region_boundary (bool with_selection, int32_t dir) return; } - nframes64_t pos = loc->start(); + framepos_t pos = loc->start(); // so we don't find the current region again.. if (dir > 0 || pos > 0) { @@ -1033,7 +1031,7 @@ void Editor::selected_marker_to_region_point (RegionPoint point, int32_t dir) { boost::shared_ptr r; - nframes64_t pos; + framepos_t pos; Location* loc; bool ignored; @@ -1066,7 +1064,7 @@ Editor::selected_marker_to_region_point (RegionPoint point, int32_t dir) return; } - switch (point){ + switch (point) { case Start: pos = r->first_frame (); break; @@ -1109,7 +1107,7 @@ Editor::selected_marker_to_previous_region_point (RegionPoint point) void Editor::selected_marker_to_selection_start () { - nframes64_t pos = 0; + framepos_t pos = 0; Location* loc; bool ignored; @@ -1121,14 +1119,10 @@ Editor::selected_marker_to_selection_start () return; } - RegionSelection rs; - - get_regions_for_action (rs); - switch (mouse_mode) { case MouseObject: - if (!rs.empty()) { - pos = rs.start(); + if (!selection->regions.empty()) { + pos = selection->regions.start(); } break; @@ -1148,7 +1142,7 @@ Editor::selected_marker_to_selection_start () void Editor::selected_marker_to_selection_end () { - nframes64_t pos = 0; + framepos_t pos = 0; Location* loc; bool ignored; @@ -1160,14 +1154,10 @@ Editor::selected_marker_to_selection_end () return; } - RegionSelection rs; - - get_regions_for_action (rs); - switch (mouse_mode) { case MouseObject: - if (!rs.empty()) { - pos = rs.end_frame(); + if (!selection->regions.empty()) { + pos = selection->regions.end_frame(); } break; @@ -1187,18 +1177,18 @@ Editor::selected_marker_to_selection_end () void Editor::scroll_playhead (bool forward) { - nframes64_t pos = playhead_cursor->current_frame; - nframes64_t delta = (nframes64_t) floor (current_page_frames() / 0.8); + framepos_t pos = playhead_cursor->current_frame; + framecnt_t delta = (framecnt_t) floor (current_page_frames() / 0.8); if (forward) { - if (pos == max_frames) { + if (pos == max_framepos) { return; } - if (pos < max_frames - delta) { + if (pos < max_framepos - delta) { pos += delta ; } else { - pos = max_frames; + pos = max_framepos; } } else { @@ -1217,68 +1207,6 @@ Editor::scroll_playhead (bool forward) _session->request_locate (pos); } -void -Editor::playhead_backward () -{ - nframes64_t pos; - nframes64_t cnt; - float prefix; - bool was_floating; - - if (get_prefix (prefix, was_floating)) { - cnt = 1; - } else { - if (was_floating) { - cnt = (nframes64_t) floor (prefix * _session->frame_rate ()); - } else { - cnt = (nframes64_t) prefix; - } - } - - pos = playhead_cursor->current_frame; - - if ((nframes64_t) pos < cnt) { - pos = 0; - } else { - pos -= cnt; - } - - /* XXX this is completely insane. with the current buffering - design, we'll force a complete track buffer flush and - reload, just to move 1 sample !!! - */ - - _session->request_locate (pos); -} - -void -Editor::playhead_forward () -{ - nframes64_t pos; - nframes64_t cnt; - bool was_floating; - float prefix; - - if (get_prefix (prefix, was_floating)) { - cnt = 1; - } else { - if (was_floating) { - cnt = (nframes64_t) floor (prefix * _session->frame_rate ()); - } else { - cnt = (nframes64_t) floor (prefix); - } - } - - pos = playhead_cursor->current_frame; - - /* XXX this is completely insane. with the current buffering - design, we'll force a complete track buffer flush and - reload, just to move 1 sample !!! - */ - - _session->request_locate (pos+cnt); -} - void Editor::cursor_align (bool playhead_to_edit) { @@ -1312,98 +1240,13 @@ Editor::cursor_align (bool playhead_to_edit) } } -void -Editor::edit_cursor_backward () -{ - nframes64_t pos; - nframes64_t cnt; - float prefix; - bool was_floating; - - if (get_prefix (prefix, was_floating)) { - cnt = 1; - } else { - if (was_floating) { - cnt = (nframes64_t) floor (prefix * _session->frame_rate ()); - } else { - cnt = (nframes64_t) prefix; - } - } - - if ((pos = get_preferred_edit_position()) < 0) { - return; - } - - if (pos < cnt) { - pos = 0; - } else { - pos -= cnt; - } - - // EDIT CURSOR edit_cursor->set_position (pos); -} - -void -Editor::edit_cursor_forward () -{ - //nframes64_t pos; - nframes64_t cnt; - bool was_floating; - float prefix; - - if (get_prefix (prefix, was_floating)) { - cnt = 1; - } else { - if (was_floating) { - cnt = (nframes64_t) floor (prefix * _session->frame_rate ()); - } else { - cnt = (nframes64_t) floor (prefix); - } - } - - // pos = edit_cursor->current_frame; - // EDIT CURSOR edit_cursor->set_position (pos+cnt); -} - -void -Editor::goto_frame () -{ - float prefix; - bool was_floating; - nframes64_t frame; - - if (get_prefix (prefix, was_floating)) { - return; - } - - if (was_floating) { - frame = (nframes64_t) floor (prefix * _session->frame_rate()); - } else { - frame = (nframes64_t) floor (prefix); - } - - _session->request_locate (frame); -} - void Editor::scroll_backward (float pages) { - nframes64_t frame; - nframes64_t one_page = (nframes64_t) rint (_canvas_width * frames_per_unit); - bool was_floating; - float prefix; - nframes64_t cnt; - - if (get_prefix (prefix, was_floating)) { - cnt = (nframes64_t) floor (pages * one_page); - } else { - if (was_floating) { - cnt = (nframes64_t) floor (prefix * _session->frame_rate()); - } else { - cnt = (nframes64_t) floor (prefix * one_page); - } - } + framepos_t const one_page = (framepos_t) rint (_canvas_width * frames_per_unit); + framepos_t const cnt = (framepos_t) floor (pages * one_page); + framepos_t frame; if (leftmost_frame < cnt) { frame = 0; } else { @@ -1416,24 +1259,12 @@ Editor::scroll_backward (float pages) void Editor::scroll_forward (float pages) { - nframes64_t frame; - nframes64_t one_page = (nframes64_t) rint (_canvas_width * frames_per_unit); - bool was_floating; - float prefix; - nframes64_t cnt; - - if (get_prefix (prefix, was_floating)) { - cnt = (nframes64_t) floor (pages * one_page); - } else { - if (was_floating) { - cnt = (nframes64_t) floor (prefix * _session->frame_rate()); - } else { - cnt = (nframes64_t) floor (prefix * one_page); - } - } + framepos_t const one_page = (framepos_t) rint (_canvas_width * frames_per_unit); + framepos_t const cnt = (framepos_t) floor (pages * one_page); - if (max_frames - cnt < leftmost_frame) { - frame = max_frames - cnt; + framepos_t frame; + if (max_framepos - cnt < leftmost_frame) { + frame = max_framepos - cnt; } else { frame = leftmost_frame + cnt; } @@ -1444,38 +1275,18 @@ Editor::scroll_forward (float pages) void Editor::scroll_tracks_down () { - float prefix; - bool was_floating; - int cnt; - - if (get_prefix (prefix, was_floating)) { - cnt = 1; - } else { - cnt = (int) floor (prefix); - } - - double vert_value = vertical_adjustment.get_value() + (cnt * - vertical_adjustment.get_page_size()); + double vert_value = vertical_adjustment.get_value() + vertical_adjustment.get_page_size(); if (vert_value > vertical_adjustment.get_upper() - _canvas_height) { vert_value = vertical_adjustment.get_upper() - _canvas_height; } + vertical_adjustment.set_value (vert_value); } void Editor::scroll_tracks_up () { - float prefix; - bool was_floating; - int cnt; - - if (get_prefix (prefix, was_floating)) { - cnt = 1; - } else { - cnt = (int) floor (prefix); - } - - vertical_adjustment.set_value (vertical_adjustment.get_value() - (cnt * vertical_adjustment.get_page_size())); + vertical_adjustment.set_value (vertical_adjustment.get_value() - vertical_adjustment.get_page_size()); } void @@ -1536,14 +1347,14 @@ Editor::temporal_zoom (gdouble fpu) { if (!_session) return; - nframes64_t current_page = current_page_frames(); - nframes64_t current_leftmost = leftmost_frame; - nframes64_t current_rightmost; - nframes64_t current_center; - nframes64_t new_page_size; - nframes64_t half_page_size; - nframes64_t leftmost_after_zoom = 0; - nframes64_t where; + framepos_t current_page = current_page_frames(); + framepos_t current_leftmost = leftmost_frame; + framepos_t current_rightmost; + framepos_t current_center; + framepos_t new_page_size; + framepos_t half_page_size; + framepos_t leftmost_after_zoom = 0; + framepos_t where; bool in_track_canvas; double nfpu; double l; @@ -1556,7 +1367,7 @@ Editor::temporal_zoom (gdouble fpu) nfpu = fpu; - new_page_size = (nframes64_t) floor (_canvas_width * nfpu); + new_page_size = (framepos_t) floor (_canvas_width * nfpu); half_page_size = new_page_size / 2; switch (zoom_focus) { @@ -1588,10 +1399,10 @@ Editor::temporal_zoom (gdouble fpu) if (l < 0) { leftmost_after_zoom = 0; - } else if (l > max_frames) { - leftmost_after_zoom = max_frames - new_page_size; + } else if (l > max_framepos) { + leftmost_after_zoom = max_framepos - new_page_size; } else { - leftmost_after_zoom = (nframes64_t) l; + leftmost_after_zoom = (framepos_t) l; } break; @@ -1614,10 +1425,10 @@ Editor::temporal_zoom (gdouble fpu) if (l < 0) { leftmost_after_zoom = 0; - } else if (l > max_frames) { - leftmost_after_zoom = max_frames - new_page_size; + } else if (l > max_framepos) { + leftmost_after_zoom = max_framepos - new_page_size; } else { - leftmost_after_zoom = (nframes64_t) l; + leftmost_after_zoom = (framepos_t) l; } } @@ -1633,10 +1444,10 @@ Editor::temporal_zoom (gdouble fpu) if (l < 0) { leftmost_after_zoom = 0; - } else if (l > max_frames) { - leftmost_after_zoom = max_frames - new_page_size; + } else if (l > max_framepos) { + leftmost_after_zoom = max_framepos - new_page_size; } else { - leftmost_after_zoom = (nframes64_t) l; + leftmost_after_zoom = (framepos_t) l; } } else { @@ -1655,13 +1466,11 @@ Editor::temporal_zoom (gdouble fpu) void Editor::temporal_zoom_region (bool both_axes) { - - nframes64_t start = max_frames; - nframes64_t end = 0; - RegionSelection rs; + framepos_t start = max_framepos; + framepos_t end = 0; set tracks; - get_regions_for_action (rs); + RegionSelection rs = get_regions_from_selection_and_entered (); if (rs.empty()) { return; @@ -1695,9 +1504,9 @@ Editor::temporal_zoom_region (bool both_axes) return; } - nframes64_t range = end - start; + framepos_t range = end - start; double new_fpu = (double)range / (double)_canvas_width; - nframes64_t extra_samples = (nframes64_t) floor (one_centimeter_in_pixels * new_fpu); + framepos_t extra_samples = (framepos_t) floor (one_centimeter_in_pixels * new_fpu); if (start > extra_samples) { start -= extra_samples; @@ -1705,10 +1514,10 @@ Editor::temporal_zoom_region (bool both_axes) start = 0; } - if (max_frames - extra_samples > end) { + if (max_framepos - extra_samples > end) { end += extra_samples; } else { - end = max_frames; + end = max_framepos; } if (both_axes) { @@ -1764,8 +1573,8 @@ Editor::temporal_zoom_selection () return; } - nframes64_t start = selection->time[clicked_selection].start; - nframes64_t end = selection->time[clicked_selection].end; + framepos_t start = selection->time[clicked_selection].start; + framepos_t end = selection->time[clicked_selection].end; temporal_zoom_by_frame (start, end, "zoom to selection"); } @@ -1776,18 +1585,18 @@ Editor::temporal_zoom_session () ENSURE_GUI_THREAD (*this, &Editor::temporal_zoom_session) if (_session) { - nframes_t const l = _session->current_end_frame() - _session->current_start_frame(); + framecnt_t const l = _session->current_end_frame() - _session->current_start_frame(); double s = _session->current_start_frame() - l * 0.01; if (s < 0) { s = 0; } - nframes_t const e = _session->current_end_frame() + l * 0.01; - temporal_zoom_by_frame (nframes_t (s), e, "zoom to _session"); + framecnt_t const e = _session->current_end_frame() + l * 0.01; + temporal_zoom_by_frame (framecnt_t (s), e, "zoom to _session"); } } void -Editor::temporal_zoom_by_frame (nframes64_t start, nframes64_t end, const string & /*op*/) +Editor::temporal_zoom_by_frame (framepos_t start, framepos_t end, const string & /*op*/) { if (!_session) return; @@ -1795,13 +1604,13 @@ Editor::temporal_zoom_by_frame (nframes64_t start, nframes64_t end, const string return; } - nframes64_t range = end - start; + framepos_t range = end - start; double new_fpu = (double)range / (double)_canvas_width; - nframes64_t new_page = (nframes64_t) floor (_canvas_width * new_fpu); - nframes64_t middle = (nframes64_t) floor( (double)start + ((double)range / 2.0f )); - nframes64_t new_leftmost = (nframes64_t) floor( (double)middle - ((double)new_page/2.0f)); + framepos_t new_page = (framepos_t) floor (_canvas_width * new_fpu); + framepos_t middle = (framepos_t) floor( (double)start + ((double)range / 2.0f )); + framepos_t new_leftmost = (framepos_t) floor( (double)middle - ((double)new_page/2.0f)); if (new_leftmost > middle) { new_leftmost = 0; @@ -1811,7 +1620,7 @@ Editor::temporal_zoom_by_frame (nframes64_t start, nframes64_t end, const string } void -Editor::temporal_zoom_to_frame (bool coarser, nframes64_t frame) +Editor::temporal_zoom_to_frame (bool coarser, framepos_t frame) { if (!_session) { return; @@ -1833,15 +1642,15 @@ Editor::temporal_zoom_to_frame (bool coarser, nframes64_t frame) return; } - nframes64_t new_leftmost = frame - (nframes64_t)range_before; + framepos_t new_leftmost = frame - (framepos_t)range_before; if (new_leftmost > frame) { new_leftmost = 0; } -// begin_reversible_command (_("zoom to frame")); -// _session->add_undo (sigc::bind (sigc::mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit)); -// _session->add_redo (sigc::bind (sigc::mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu)); -// commit_reversible_command (); + + if (new_leftmost < 0) { + new_leftmost = 0; + } reposition_and_zoom (new_leftmost, new_fpu); } @@ -1896,22 +1705,22 @@ Editor::add_location_from_selection () return; } - nframes64_t start = selection->time[clicked_selection].start; - nframes64_t end = selection->time[clicked_selection].end; + framepos_t start = selection->time[clicked_selection].start; + framepos_t end = selection->time[clicked_selection].end; _session->locations()->next_available_name(rangename,"selection"); - Location *location = new Location (start, end, rangename, Location::IsRangeMarker); + Location *location = new Location (*_session, start, end, rangename, Location::IsRangeMarker); _session->begin_reversible_command (_("add marker")); - XMLNode &before = _session->locations()->get_state(); + XMLNode &before = _session->locations()->get_state(); _session->locations()->add (location, true); - XMLNode &after = _session->locations()->get_state(); + XMLNode &after = _session->locations()->get_state(); _session->add_command(new MementoCommand(*(_session->locations()), &before, &after)); _session->commit_reversible_command (); } void -Editor::add_location_mark (nframes64_t where) +Editor::add_location_mark (framepos_t where) { string markername; @@ -1921,11 +1730,11 @@ Editor::add_location_mark (nframes64_t where) if (!choose_new_marker_name(markername)) { return; } - Location *location = new Location (where, where, markername, Location::IsMark); + Location *location = new Location (*_session, where, where, markername, Location::IsMark); _session->begin_reversible_command (_("add marker")); - XMLNode &before = _session->locations()->get_state(); + XMLNode &before = _session->locations()->get_state(); _session->locations()->add (location, true); - XMLNode &after = _session->locations()->get_state(); + XMLNode &after = _session->locations()->get_state(); _session->add_command(new MementoCommand(*(_session->locations()), &before, &after)); _session->commit_reversible_command (); } @@ -1936,27 +1745,24 @@ Editor::add_location_from_playhead_cursor () add_location_mark (_session->audible_frame()); } +/** Add a range marker around each selected region */ void -Editor::add_locations_from_audio_region () +Editor::add_locations_from_region () { - RegionSelection rs; - - get_regions_for_action (rs); - + RegionSelection rs = get_regions_from_selection_and_entered (); + if (rs.empty()) { return; } - _session->begin_reversible_command (rs.size () > 1 ? _("add markers") : _("add marker")); + _session->begin_reversible_command (selection->regions.size () > 1 ? _("add markers") : _("add marker")); XMLNode &before = _session->locations()->get_state(); - cerr << "Add locations\n"; - for (RegionSelection::iterator i = rs.begin (); i != rs.end (); ++i) { boost::shared_ptr region = (*i)->region (); - Location *location = new Location (region->position(), region->last_frame(), region->name(), Location::IsRangeMarker); + Location *location = new Location (*_session, region->position(), region->last_frame(), region->name(), Location::IsRangeMarker); _session->locations()->add (location, true); } @@ -1966,13 +1772,12 @@ Editor::add_locations_from_audio_region () _session->commit_reversible_command (); } +/** Add a single range marker around all selected regions */ void -Editor::add_location_from_audio_region () +Editor::add_location_from_region () { - RegionSelection rs; - - get_regions_for_action (rs); - + RegionSelection rs = get_regions_from_selection_and_entered (); + if (rs.empty()) { return; } @@ -1982,7 +1787,7 @@ Editor::add_location_from_audio_region () string markername; - if (rs.size() > 1) { // more than one region selected + if (rs.size() > 1) { _session->locations()->next_available_name(markername, "regions"); } else { RegionView* rv = *(rs.begin()); @@ -1994,10 +1799,8 @@ Editor::add_location_from_audio_region () return; } - cerr << "Add location\n"; - // single range spanning all selected - Location *location = new Location (rs.start(), rs.end_frame(), markername, Location::IsRangeMarker); + Location *location = new Location (*_session, selection->regions.start(), selection->regions.end_frame(), markername, Location::IsRangeMarker); _session->locations()->add (location, true); XMLNode &after = _session->locations()->get_state(); @@ -2005,59 +1808,6 @@ Editor::add_location_from_audio_region () _session->commit_reversible_command (); } -void -Editor::amplitude_zoom_step (bool in) -{ - gdouble zoom = 1.0; - - if (in) { - zoom *= 2.0; - } else { - if (zoom > 2.0) { - zoom /= 2.0; - } else { - zoom = 1.0; - } - } - -#ifdef FIX_FOR_CANVAS - /* XXX DO SOMETHING */ -#endif -} - - -/* DELETION */ - - -void -Editor::delete_sample_forward () -{ -} - -void -Editor::delete_sample_backward () -{ -} - -void -Editor::delete_screen () -{ -} - -/* SEARCH */ - -void -Editor::search_backwards () -{ - /* what ? */ -} - -void -Editor::search_forwards () -{ - /* what ? */ -} - /* MARKS */ void @@ -2095,26 +1845,16 @@ Editor::jump_backward_to_mark () void Editor::set_mark () { - nframes64_t pos; - float prefix; - bool was_floating; - string markername; - - if (get_prefix (prefix, was_floating)) { - pos = _session->audible_frame (); - } else { - if (was_floating) { - pos = (nframes64_t) floor (prefix * _session->frame_rate ()); - } else { - pos = (nframes64_t) floor (prefix); - } - } + framepos_t const pos = _session->audible_frame (); - _session->locations()->next_available_name(markername,"mark"); - if (!choose_new_marker_name(markername)) { + string markername; + _session->locations()->next_available_name (markername, "mark"); + + if (!choose_new_marker_name (markername)) { return; } - _session->locations()->add (new Location (pos, 0, markername, Location::IsMark), true); + + _session->locations()->add (new Location (*_session, pos, 0, markername, Location::IsMark), true); } void @@ -2122,9 +1862,9 @@ Editor::clear_markers () { if (_session) { _session->begin_reversible_command (_("clear markers")); - XMLNode &before = _session->locations()->get_state(); + XMLNode &before = _session->locations()->get_state(); _session->locations()->clear_markers (); - XMLNode &after = _session->locations()->get_state(); + XMLNode &after = _session->locations()->get_state(); _session->add_command(new MementoCommand(*(_session->locations()), &before, &after)); _session->commit_reversible_command (); } @@ -2135,7 +1875,7 @@ Editor::clear_ranges () { if (_session) { _session->begin_reversible_command (_("clear ranges")); - XMLNode &before = _session->locations()->get_state(); + XMLNode &before = _session->locations()->get_state(); Location * looploc = _session->locations()->auto_loop_location(); Location * punchloc = _session->locations()->auto_punch_location(); @@ -2145,7 +1885,7 @@ Editor::clear_ranges () if (looploc) _session->locations()->add (looploc); if (punchloc) _session->locations()->add (punchloc); - XMLNode &after = _session->locations()->get_state(); + XMLNode &after = _session->locations()->get_state(); _session->add_command(new MementoCommand(*(_session->locations()), &before, &after)); _session->commit_reversible_command (); } @@ -2155,9 +1895,9 @@ void Editor::clear_locations () { _session->begin_reversible_command (_("clear locations")); - XMLNode &before = _session->locations()->get_state(); + XMLNode &before = _session->locations()->get_state(); _session->locations()->clear (); - XMLNode &after = _session->locations()->get_state(); + XMLNode &after = _session->locations()->get_state(); _session->add_command(new MementoCommand(*(_session->locations()), &before, &after)); _session->commit_reversible_command (); _session->locations()->clear (); @@ -2192,7 +1932,7 @@ Editor::insert_region_list_drag (boost::shared_ptr region, int x, int y) { double wx, wy; double cx, cy; - nframes64_t where; + framepos_t where; RouteTimeAxisView *rtv = 0; boost::shared_ptr playlist; @@ -2226,8 +1966,8 @@ Editor::insert_region_list_drag (boost::shared_ptr region, int x, int y) snap_to (where); begin_reversible_command (_("insert dragged region")); - playlist->clear_history (); - playlist->add_region (RegionFactory::create (region), where, 1.0); + playlist->clear_changes (); + playlist->add_region (RegionFactory::create (region, true), where, 1.0); _session->add_command(new StatefulDiffCommand (playlist)); commit_reversible_command (); } @@ -2237,7 +1977,7 @@ Editor::insert_route_list_drag (boost::shared_ptr route, int x, int y) { double wx, wy; double cx, cy; - nframes_t where; + framepos_t where; RouteTimeAxisView *dest_rtv = 0; RouteTimeAxisView *source_rtv = 0; @@ -2305,8 +2045,8 @@ Editor::insert_region_list_selection (float times) } begin_reversible_command (_("insert region")); - playlist->clear_history (); - playlist->add_region ((RegionFactory::create (region)), get_preferred_edit_position(), times); + playlist->clear_changes (); + playlist->add_region ((RegionFactory::create (region, true)), get_preferred_edit_position(), times); _session->add_command(new StatefulDiffCommand (playlist)); commit_reversible_command (); } @@ -2368,8 +2108,8 @@ Editor::play_from_edit_point () void Editor::play_from_edit_point_and_return () { - nframes64_t start_frame; - nframes64_t return_frame; + framepos_t start_frame; + framepos_t return_frame; start_frame = get_preferred_edit_position (true); @@ -2399,30 +2139,6 @@ Editor::play_selection () _session->request_play_range (&selection->time, true); } -void -Editor::loop_selected_region () -{ - RegionSelection rs; - - get_regions_for_action (rs); - - if (!rs.empty()) { - RegionView *rv = *(rs.begin()); - Location* tll; - - if ((tll = transport_loop_location()) != 0) { - - tll->set (rv->region()->position(), rv->region()->last_frame()); - - // enable looping, reposition and start rolling - - _session->request_play_loop (true); - _session->request_locate (tll->start(), false); - _session->request_transport_speed (1.0f); - } - } -} - void Editor::play_location (Location& location) { @@ -2477,7 +2193,7 @@ Editor::lower_region_to_bottom () /** Show the region editor for the selected regions */ void -Editor::edit_region () +Editor::show_region_properties () { selection->foreach_regionview (&RegionView::show_region_editor); } @@ -2490,12 +2206,10 @@ Editor::show_midi_list_editor () } void -Editor::rename_region() +Editor::rename_region () { - RegionSelection rs; - - get_regions_for_action (rs); - + RegionSelection rs = get_regions_from_selection_and_entered (); + if (rs.empty()) { return; } @@ -2518,7 +2232,7 @@ Editor::rename_region() d.set_size_request (300, -1); d.set_position (Gtk::WIN_POS_MOUSE); - entry.set_text (rs.front()->region()->name()); + entry.set_text (selection->regions.front()->region()->name()); entry.select_region (0, -1); entry.signal_activate().connect (sigc::bind (sigc::mem_fun (d, &Dialog::response), RESPONSE_OK)); @@ -2527,17 +2241,19 @@ Editor::rename_region() entry.grab_focus(); - int ret = d.run(); + int const ret = d.run(); d.hide (); - if (ret == RESPONSE_OK) { - std::string str = entry.get_text(); - strip_whitespace_edges (str); - if (!str.empty()) { - rs.front()->region()->set_name (str); - _regions->redisplay (); - } + if (ret != RESPONSE_OK) { + return; + } + + std::string str = entry.get_text(); + strip_whitespace_edges (str); + if (!str.empty()) { + rs.front()->region()->set_name (str); + _regions->redisplay (); } } @@ -2564,7 +2280,7 @@ Editor::audition_playlist_region_via_route (boost::shared_ptr region, Ro void Editor::play_edit_range () { - nframes64_t start, end; + framepos_t start, end; if (get_edit_op_range (start, end)) { _session->request_bounded_roll (start, end); @@ -2574,12 +2290,11 @@ Editor::play_edit_range () void Editor::play_selected_region () { - nframes64_t start = max_frames; - nframes64_t end = 0; - RegionSelection rs; - - get_regions_for_action (rs); + framepos_t start = max_framepos; + framepos_t end = 0; + RegionSelection rs = get_regions_from_selection_and_entered (); + if (rs.empty()) { return; } @@ -2613,17 +2328,17 @@ Editor::region_from_selection () return; } - nframes64_t start = selection->time[clicked_selection].start; - nframes64_t end = selection->time[clicked_selection].end; + framepos_t start = selection->time[clicked_selection].start; + framepos_t end = selection->time[clicked_selection].end; TrackViewList tracks = get_tracks_for_range_action (); - nframes64_t selection_cnt = end - start + 1; + framepos_t selection_cnt = end - start + 1; for (TrackSelection::iterator i = tracks.begin(); i != tracks.end(); ++i) { boost::shared_ptr current; boost::shared_ptr pl; - nframes64_t internal_start; + framepos_t internal_start; string new_name; if ((pl = (*i)->playlist()) == 0) { @@ -2655,15 +2370,15 @@ Editor::create_region_from_selection (vector >& new_re return; } - nframes64_t start = selection->time[clicked_selection].start; - nframes64_t end = selection->time[clicked_selection].end; + framepos_t start = selection->time[clicked_selection].start; + framepos_t end = selection->time[clicked_selection].end; sort_track_selection (); for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { boost::shared_ptr current; boost::shared_ptr playlist; - nframes64_t internal_start; + framepos_t internal_start; string new_name; if ((playlist = (*i)->playlist()) == 0) { @@ -2690,10 +2405,8 @@ Editor::create_region_from_selection (vector >& new_re void Editor::split_multichannel_region () { - RegionSelection rs; - - get_regions_for_action (rs); - + RegionSelection rs = get_regions_from_selection_and_entered (); + if (rs.empty()) { return; } @@ -2787,7 +2500,7 @@ Editor::separate_regions_between (const TimeSelection& ts) if ((playlist = rtv->playlist()) != 0) { - playlist->clear_history (); + playlist->clear_changes (); /* XXX need to consider musical time selections here at some point */ @@ -2798,10 +2511,11 @@ Editor::separate_regions_between (const TimeSelection& ts) sigc::connection c = rtv->view()->RegionViewAdded.connect ( sigc::mem_fun(*this, &Editor::collect_new_region_view)); + latest_regionviews.clear (); - playlist->partition ((nframes64_t)((*t).start * speed), - (nframes64_t)((*t).end * speed), true); + playlist->partition ((framepos_t)((*t).start * speed), + (framepos_t)((*t).end * speed), false); c.disconnect (); @@ -2810,11 +2524,20 @@ Editor::separate_regions_between (const TimeSelection& ts) rtv->view()->foreach_regionview (sigc::bind ( sigc::ptr_fun (add_if_covered), &(*t), &new_selection)); - + if (!in_command) { begin_reversible_command (_("separate")); in_command = true; } + + /* pick up changes to existing regions */ + + vector cmds; + playlist->rdiff (cmds); + _session->add_commands (cmds); + + /* pick up changes to the playlist itself (adds/removes) + */ _session->add_command(new StatefulDiffCommand (playlist)); } @@ -2832,6 +2555,11 @@ Editor::separate_regions_between (const TimeSelection& ts) } } +struct PlaylistState { + boost::shared_ptr playlist; + XMLNode* before; +}; + /** Take tracks from get_tracks_for_range_action and cut any regions * on those tracks so that the tracks are empty over the time * selection. @@ -2850,8 +2578,8 @@ Editor::separate_region_from_selection () } else { - nframes64_t start; - nframes64_t end; + framepos_t start; + framepos_t end; if (get_edit_op_range (start, end)) { @@ -2897,6 +2625,82 @@ Editor::separate_regions_using_location (Location& loc) separate_regions_between (ts); } +/** Separate regions under the selected region */ +void +Editor::separate_under_selected_regions () +{ + vector playlists; + + RegionSelection rs; + + rs = get_regions_from_selection_and_entered(); + + if (!_session || rs.empty()) { + return; + } + + begin_reversible_command (_("separate region under")); + + list > regions_to_remove; + + for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { + // we can't just remove the region(s) in this loop because + // this removes them from the RegionSelection, and they thus + // disappear from underneath the iterator, and the ++i above + // SEGVs in a puzzling fashion. + + // so, first iterate over the regions to be removed from rs and + // add them to the regions_to_remove list, and then + // iterate over the list to actually remove them. + + regions_to_remove.push_back ((*i)->region()); + } + + for (list >::iterator rl = regions_to_remove.begin(); rl != regions_to_remove.end(); ++rl) { + + boost::shared_ptr playlist = (*rl)->playlist(); + + if (!playlist) { + // is this check necessary? + continue; + } + + vector::iterator i; + + //only take state if this is a new playlist. + for (i = playlists.begin(); i != playlists.end(); ++i) { + if ((*i).playlist == playlist) { + break; + } + } + + if (i == playlists.end()) { + + PlaylistState before; + before.playlist = playlist; + before.before = &playlist->get_state(); + + playlist->freeze (); + playlists.push_back(before); + } + + //Partition on the region bounds + playlist->partition ((*rl)->first_frame() - 1, (*rl)->last_frame() + 1, true); + + //Re-add region that was just removed due to the partition operation + playlist->add_region( (*rl), (*rl)->first_frame() ); + } + + vector::iterator pl; + + for (pl = playlists.begin(); pl != playlists.end(); ++pl) { + (*pl).playlist->thaw (); + _session->add_command(new MementoCommand(*(*pl).playlist, (*pl).before, &(*pl).playlist->get_state())); + } + + commit_reversible_command (); +} + void Editor::crop_region_to_selection () { @@ -2906,8 +2710,8 @@ Editor::crop_region_to_selection () } else { - nframes64_t start; - nframes64_t end; + framepos_t start; + framepos_t end; if (get_edit_op_range (start, end)) { crop_region_to (start, end); @@ -2917,7 +2721,7 @@ Editor::crop_region_to_selection () } void -Editor::crop_region_to (nframes64_t start, nframes64_t end) +Editor::crop_region_to (framepos_t start, framepos_t end) { vector > playlists; boost::shared_ptr playlist; @@ -2951,9 +2755,9 @@ Editor::crop_region_to (nframes64_t start, nframes64_t end) return; } - nframes64_t the_start; - nframes64_t the_end; - nframes64_t cnt; + framepos_t the_start; + framepos_t the_end; + framepos_t cnt; begin_reversible_command (_("trim to selection")); @@ -2971,16 +2775,16 @@ Editor::crop_region_to (nframes64_t start, nframes64_t end) if the selection extends beyond the region */ - the_start = max (the_start, (nframes64_t) region->position()); - if (max_frames - the_start < region->length()) { + the_start = max (the_start, (framepos_t) region->position()); + if (max_framepos - the_start < region->length()) { the_end = the_start + region->length() - 1; } else { - the_end = max_frames; + the_end = max_framepos; } the_end = min (end, the_end); cnt = the_end - the_start + 1; - region->clear_history (); + region->clear_changes (); region->trim_to (the_start, cnt, this); _session->add_command (new StatefulDiffCommand (region)); } @@ -2991,18 +2795,15 @@ Editor::crop_region_to (nframes64_t start, nframes64_t end) void Editor::region_fill_track () { - nframes64_t end; - RegionSelection rs; - - get_regions_for_action (rs); + RegionSelection rs = get_regions_from_selection_and_entered (); if (!_session || rs.empty()) { return; } - end = _session->current_end_frame (); + framepos_t const end = _session->current_end_frame (); - begin_reversible_command (_("region fill")); + begin_reversible_command (Operations::region_fill); for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { @@ -3020,8 +2821,8 @@ Editor::region_fill_track () return; } - pl->clear_history (); - pl->add_region (RegionFactory::create (region), region->last_frame(), times); + pl->clear_changes (); + pl->add_region (RegionFactory::create (region, true), region->last_frame(), times); _session->add_command (new StatefulDiffCommand (pl)); } @@ -3044,8 +2845,8 @@ Editor::region_fill_selection () return; } - nframes64_t start = selection->time[clicked_selection].start; - nframes64_t end = selection->time[clicked_selection].end; + framepos_t start = selection->time[clicked_selection].start; + framepos_t end = selection->time[clicked_selection].end; boost::shared_ptr playlist; @@ -3053,10 +2854,10 @@ Editor::region_fill_selection () return; } - nframes64_t selection_length = end - start; + framepos_t selection_length = end - start; float times = (float)selection_length / region->length(); - begin_reversible_command (_("fill selection")); + begin_reversible_command (Operations::fill_selection); for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { @@ -3064,8 +2865,8 @@ Editor::region_fill_selection () continue; } - playlist->clear_history (); - playlist->add_region (RegionFactory::create (region), start, times); + playlist->clear_changes (); + playlist->add_region (RegionFactory::create (region, true), start, times); _session->add_command (new StatefulDiffCommand (playlist)); } @@ -3073,16 +2874,13 @@ Editor::region_fill_selection () } void -Editor::set_region_sync_from_edit_point () +Editor::set_region_sync_position () { - nframes64_t where = get_preferred_edit_position (); - RegionSelection rs; - get_regions_for_action (rs); - set_sync_point (where, rs); + set_sync_point (get_preferred_edit_position (), get_regions_from_selection_and_edit_point ()); } void -Editor::set_sync_point (nframes64_t where, const RegionSelection& rs) +Editor::set_sync_point (framepos_t where, const RegionSelection& rs) { bool in_command = false; @@ -3099,7 +2897,7 @@ Editor::set_sync_point (nframes64_t where, const RegionSelection& rs) in_command = true; } - region->clear_history (); + region->clear_changes (); region->set_sync_position (where); _session->add_command(new StatefulDiffCommand (region)); } @@ -3113,73 +2911,66 @@ Editor::set_sync_point (nframes64_t where, const RegionSelection& rs) void Editor::remove_region_sync () { - RegionSelection rs; - - get_regions_for_action (rs); - + RegionSelection rs = get_regions_from_selection_and_entered (); + if (rs.empty()) { return; } - begin_reversible_command (_("remove sync")); + begin_reversible_command (_("remove region sync")); + for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { - (*i)->region()->clear_history (); + (*i)->region()->clear_changes (); (*i)->region()->clear_sync_position (); _session->add_command(new StatefulDiffCommand ((*i)->region())); } + commit_reversible_command (); } void -Editor::naturalize () +Editor::naturalize_region () { - RegionSelection rs; - - get_regions_for_action (rs); + RegionSelection rs = get_regions_from_selection_and_entered (); if (rs.empty()) { return; } - begin_reversible_command (_("naturalize")); + if (rs.size() > 1) { + begin_reversible_command (_("move regions to original position")); + } else { + begin_reversible_command (_("move region to original position")); + } + for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { - (*i)->region()->clear_history (); + (*i)->region()->clear_changes (); (*i)->region()->move_to_natural_position (this); _session->add_command (new StatefulDiffCommand ((*i)->region())); } + commit_reversible_command (); } void -Editor::align (RegionPoint what) +Editor::align_regions (RegionPoint what) { - RegionSelection rs; - - get_regions_for_action (rs); - nframes64_t where = get_preferred_edit_position(); - - if (!rs.empty()) { - align_selection (what, where, rs); - } else { - - RegionSelection rs; - get_regions_at (rs, where, selection->tracks); - align_selection (what, where, rs); + RegionSelection const rs = get_regions_from_selection_and_edit_point (); + + if (rs.empty()) { + return; } -} -void -Editor::align_relative (RegionPoint what) -{ - nframes64_t where = get_preferred_edit_position(); - RegionSelection rs; + begin_reversible_command (_("align selection")); - get_regions_for_action (rs); + framepos_t const position = get_preferred_edit_position (); - if (!rs.empty()) { - align_selection_relative (what, where, rs); + for (RegionSelection::const_iterator i = rs.begin(); i != rs.end(); ++i) { + align_region_internal ((*i)->region(), what, position); } + + commit_reversible_command (); } struct RegionSortByTime { @@ -3189,14 +2980,18 @@ struct RegionSortByTime { }; void -Editor::align_selection_relative (RegionPoint point, nframes64_t position, const RegionSelection& rs) +Editor::align_regions_relative (RegionPoint point) { + RegionSelection const rs = get_regions_from_selection_and_edit_point (); + if (rs.empty()) { return; } - nframes64_t distance = 0; - nframes64_t pos = 0; + framepos_t const position = get_preferred_edit_position (); + + framepos_t distance = 0; + framepos_t pos = 0; int dir = 1; list sorted; @@ -3245,7 +3040,7 @@ Editor::align_selection_relative (RegionPoint point, nframes64_t position, const /* move first one specially */ - r->clear_history (); + r->clear_changes (); r->set_position (pos, this); _session->add_command(new StatefulDiffCommand (r)); @@ -3257,7 +3052,7 @@ Editor::align_selection_relative (RegionPoint point, nframes64_t position, const boost::shared_ptr region ((*i)->region()); - region->clear_history (); + region->clear_changes (); if (dir > 0) { region->set_position (region->position() + distance, this); @@ -3273,23 +3068,7 @@ Editor::align_selection_relative (RegionPoint point, nframes64_t position, const } void -Editor::align_selection (RegionPoint point, nframes64_t position, const RegionSelection& rs) -{ - if (rs.empty()) { - return; - } - - begin_reversible_command (_("align selection")); - - for (RegionSelection::const_iterator i = rs.begin(); i != rs.end(); ++i) { - align_region_internal ((*i)->region(), point, position); - } - - commit_reversible_command (); -} - -void -Editor::align_region (boost::shared_ptr region, RegionPoint point, nframes64_t position) +Editor::align_region (boost::shared_ptr region, RegionPoint point, framepos_t position) { begin_reversible_command (_("align region")); align_region_internal (region, point, position); @@ -3297,9 +3076,9 @@ Editor::align_region (boost::shared_ptr region, RegionPoint point, nfram } void -Editor::align_region_internal (boost::shared_ptr region, RegionPoint point, nframes64_t position) +Editor::align_region_internal (boost::shared_ptr region, RegionPoint point, framepos_t position) { - region->clear_history (); + region->clear_changes (); switch (point) { case SyncPoint: @@ -3335,25 +3114,31 @@ Editor::trim_region_back () void Editor::trim_region (bool front) { - nframes64_t where = get_preferred_edit_position(); - RegionSelection rs; + framepos_t where = get_preferred_edit_position(); + RegionSelection rs = get_regions_from_selection_and_edit_point (); - get_regions_for_action (rs); + cerr << "trim regions\n"; if (rs.empty()) { + cerr << " no regions\n"; return; } + cerr << "where = " << where << endl; + begin_reversible_command (front ? _("trim front") : _("trim back")); for (list::const_iterator i = rs.by_layer().begin(); i != rs.by_layer().end(); ++i) { if (!(*i)->region()->locked()) { - (*i)->region()->clear_history (); + + (*i)->region()->clear_changes (); + if (front) { (*i)->region()->trim_front (where, this); } else { (*i)->region()->trim_end (where, this); } + _session->add_command (new StatefulDiffCommand ((*i)->region())); } } @@ -3381,12 +3166,11 @@ Editor::trim_region_to_punch () } trim_region_to_location (*loc, _("trim to punch")); } + void Editor::trim_region_to_location (const Location& loc, const char* str) { - RegionSelection rs; - - get_regions_for_action (rs); + RegionSelection rs = get_regions_from_selection_and_entered (); begin_reversible_command (str); @@ -3407,8 +3191,8 @@ Editor::trim_region_to_location (const Location& loc, const char* str) } float speed = 1.0; - nframes64_t start; - nframes64_t end; + framepos_t start; + framepos_t end; if (tav->track() != 0) { speed = tav->track()->speed(); @@ -3417,7 +3201,7 @@ Editor::trim_region_to_location (const Location& loc, const char* str) start = session_frame_to_track_frame (loc.start(), speed); end = session_frame_to_track_frame (loc.end(), speed); - rv->region()->clear_history (); + rv->region()->clear_changes (); rv->region()->trim_to (start, (end - start), this); _session->add_command(new StatefulDiffCommand (rv->region())); } @@ -3425,82 +3209,6 @@ Editor::trim_region_to_location (const Location& loc, const char* str) commit_reversible_command (); } -void -Editor::trim_region_to_edit_point () -{ - RegionSelection rs; - - get_regions_for_action (rs); - - nframes64_t where = get_preferred_edit_position(); - - begin_reversible_command (_("trim region start to edit point")); - - for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ++x) { - RegionView* rv = (*x); - - /* require region to cover trim */ - if (!rv->region()->covers (where)) { - continue; - } - - RouteTimeAxisView* tav = dynamic_cast (&rv->get_time_axis_view()); - if (!tav) { - return; - } - - float speed = 1.0; - - if (tav->track() != 0) { - speed = tav->track()->speed(); - } - - rv->region()->clear_history (); - rv->region()->trim_end (session_frame_to_track_frame(where, speed), this); - _session->add_command(new StatefulDiffCommand (rv->region())); - } - - commit_reversible_command (); -} - -void -Editor::trim_region_from_edit_point () -{ - RegionSelection rs; - - get_regions_for_action (rs); - - nframes64_t where = get_preferred_edit_position(); - - begin_reversible_command (_("trim region end to edit point")); - - for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ++x) { - RegionView* rv = (*x); - - /* require region to cover trim */ - if (!rv->region()->covers (where)) { - continue; - } - - RouteTimeAxisView* tav = dynamic_cast (&rv->get_time_axis_view()); - if (!tav) { - return; - } - - float speed = 1.0; - - if (tav->track() != 0) { - speed = tav->track()->speed(); - } - - rv->region()->clear_history (); - rv->region()->trim_front (session_frame_to_track_frame(where, speed), this); - _session->add_command(new StatefulDiffCommand (rv->region())); - } - - commit_reversible_command (); -} - void Editor::trim_region_to_previous_region_end () { @@ -3516,9 +3224,7 @@ Editor::trim_region_to_next_region_start () void Editor::trim_to_region(bool forward) { - RegionSelection rs; - - get_regions_for_action (rs); + RegionSelection rs = get_regions_from_selection_and_entered (); begin_reversible_command (_("trim to region")); @@ -3548,17 +3254,17 @@ Editor::trim_to_region(bool forward) boost::shared_ptr region = arv->region(); boost::shared_ptr playlist (region->playlist()); - region->clear_history (); + region->clear_changes (); - if(forward){ + if (forward) { next_region = playlist->find_next_region (region->first_frame(), Start, 1); - if(!next_region){ + if (!next_region) { continue; } - region->trim_end((nframes64_t) (next_region->first_frame() * speed), this); + region->trim_end((framepos_t) ( (next_region->first_frame() - 1) * speed), this); arv->region_changed (PropertyChange (ARDOUR::Properties::length)); } else { @@ -3569,7 +3275,7 @@ Editor::trim_to_region(bool forward) continue; } - region->trim_front((nframes64_t) ((next_region->last_frame() + 1) * speed), this); + region->trim_front((framepos_t) ((next_region->last_frame() + 1) * speed), this); arv->region_changed (ARDOUR::bounds_change); } @@ -3613,6 +3319,19 @@ Editor::freeze_route () return; } + if (!clicked_routeview->track()->bounceable()) { + RouteTimeAxisView* rtv = dynamic_cast (clicked_routeview); + if (rtv && !rtv->track()->bounceable()) { + MessageDialog d ( + _("This route cannot be frozen because it has more outputs than inputs. " + "You can fix this by increasing the number of inputs.") + ); + d.set_title (_("Cannot freeze")); + d.run (); + return; + } + } + InterThreadInfo itt; current_interthread_info = &itt; @@ -3620,14 +3339,14 @@ Editor::freeze_route () pthread_create_and_store (X_("freezer"), &itt.thread, _freeze_thread, this); - track_canvas->get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH)); + set_canvas_cursor (_cursors->wait); while (!itt.done && !itt.cancel) { gtk_main_iteration (); } current_interthread_info = 0; - track_canvas->get_window()->set_cursor (*current_canvas_cursor); + set_canvas_cursor (current_canvas_cursor); } void @@ -3639,9 +3358,22 @@ Editor::bounce_range_selection (bool replace, bool enable_processing) TrackSelection views = selection->tracks; - nframes64_t start = selection->time[clicked_selection].start; - nframes64_t end = selection->time[clicked_selection].end; - nframes64_t cnt = end - start + 1; + for (TrackViewList::iterator i = views.begin(); i != views.end(); ++i) { + RouteTimeAxisView* rtv = dynamic_cast (*i); + if (rtv && !rtv->track()->bounceable()) { + MessageDialog d ( + _("One or more selected tracks cannot be bounced because it has more outputs than inputs. " + "You can fix this by increasing the number of inputs on that track.") + ); + d.set_title (_("Cannot bounce")); + d.run (); + return; + } + } + + framepos_t start = selection->time[clicked_selection].start; + framepos_t end = selection->time[clicked_selection].end; + framepos_t cnt = end - start + 1; begin_reversible_command (_("bounce range")); @@ -3661,7 +3393,9 @@ Editor::bounce_range_selection (bool replace, bool enable_processing) InterThreadInfo itt; - playlist->clear_history (); + playlist->clear_changes (); + playlist->clear_owned_changes (); + boost::shared_ptr r = rtv->track()->bounce_range (start, start+cnt, itt, enable_processing); if (replace) { @@ -3671,6 +3405,10 @@ Editor::bounce_range_selection (bool replace, bool enable_processing) playlist->add_region (r, start); } + vector cmds; + playlist->rdiff (cmds); + _session->add_commands (cmds); + _session->add_command (new StatefulDiffCommand (playlist)); } @@ -3787,7 +3525,7 @@ Editor::cut_copy (CutCopyOp op) /* we only want to cut regions if some are selected */ if (!selection->regions.empty()) { - get_regions_for_action (rs, false, false); + rs = selection->regions; } switch (current_mouse_mode()) { @@ -3823,7 +3561,7 @@ Editor::cut_copy (CutCopyOp op) case MouseRange: if (selection->time.empty()) { - nframes64_t start, end; + framepos_t start, end; if (!get_edit_op_range (start, end)) { return; } @@ -3878,6 +3616,14 @@ Editor::cut_copy_midi (CutCopyOp op) } } + + +struct lt_playlist { + bool operator () (const PlaylistState& a, const PlaylistState& b) { + return a.playlist < b.playlist; + } +}; + struct PlaylistMapping { TimeAxisView* tv; boost::shared_ptr pl; @@ -3896,7 +3642,7 @@ Editor::remove_clicked_region () boost::shared_ptr playlist = clicked_routeview->playlist(); begin_reversible_command (_("remove region")); - playlist->clear_history (); + playlist->clear_changes (); playlist->remove_region (clicked_regionview->region()); _session->add_command(new StatefulDiffCommand (playlist)); commit_reversible_command (); @@ -3907,14 +3653,9 @@ Editor::remove_clicked_region () void Editor::remove_selected_regions () { - RegionSelection rs; - get_regions_for_action (rs); - - if (!_session) { - return; - } + RegionSelection rs = get_regions_from_selection_and_entered (); - if (rs.empty()) { + if (!_session || rs.empty()) { return; } @@ -3935,7 +3676,7 @@ Editor::remove_selected_regions () regions_to_remove.push_back ((*i)->region()); } - vector > playlists; + vector > playlists; for (list >::iterator rl = regions_to_remove.begin(); rl != regions_to_remove.end(); ++rl) { @@ -3957,7 +3698,7 @@ Editor::remove_selected_regions () if (i == playlists.end()) { - playlist->clear_history (); + playlist->clear_changes (); playlist->freeze (); playlists.push_back (playlist); @@ -3988,10 +3729,10 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs) vector pmap; - nframes64_t first_position = max_frames; + framepos_t first_position = max_framepos; typedef set > FreezeList; - FreezeList freezelist; + FreezeList freezelist; /* get ordering correct before we cut/copy */ @@ -3999,7 +3740,7 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs) for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ++x) { - first_position = min ((nframes64_t) (*x)->region()->position(), first_position); + first_position = min ((framepos_t) (*x)->region()->position(), first_position); if (op == Cut || op == Clear) { boost::shared_ptr pl = (*x)->region()->playlist(); @@ -4015,14 +3756,14 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs) } if (fl == freezelist.end()) { - pl->clear_history(); + pl->clear_changes(); pl->freeze (); freezelist.insert (pl); } } } - TimeAxisView* tv = &(*x)->get_trackview(); + TimeAxisView* tv = &(*x)->get_time_axis_view(); vector::iterator z; for (z = pmap.begin(); z != pmap.end(); ++z) { @@ -4041,11 +3782,14 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs) boost::shared_ptr pl = (*x)->region()->playlist(); if (!pl) { - /* impossible, but this handles it for the future */ + /* region not yet associated with a playlist (e.g. unfinished + capture pass. + */ + ++x; continue; } - TimeAxisView& tv = (*x)->get_trackview(); + TimeAxisView& tv = (*x)->get_time_axis_view(); boost::shared_ptr npl; RegionSelection::iterator tmp; @@ -4100,14 +3844,21 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs) /* the pmap is in the same order as the tracks in which selected regions occured */ for (vector::iterator i = pmap.begin(); i != pmap.end(); ++i) { - (*i).pl->thaw(); - foo.push_back ((*i).pl); + if ((*i).pl) { + (*i).pl->thaw(); + foo.push_back ((*i).pl); + } } - if (!foo.empty()) { cut_buffer->set (foo); } + + if (pmap.empty()) { + _last_cut_copy_source_track = 0; + } else { + _last_cut_copy_source_track = pmap.front().tv; + } for (FreezeList::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) { (*pl)->thaw (); @@ -4139,13 +3890,14 @@ Editor::cut_copy_ranges (CutCopyOp op) void Editor::paste (float times) { + DEBUG_TRACE (DEBUG::CutNPaste, "paste to preferred edit pos\n"); paste_internal (get_preferred_edit_position(), times); } void Editor::mouse_paste () { - nframes64_t where; + framepos_t where; bool ignored; if (!mouse_frame (where, ignored)) { @@ -4157,9 +3909,9 @@ Editor::mouse_paste () } void -Editor::paste_internal (nframes64_t position, float times) +Editor::paste_internal (framepos_t position, float times) { - bool commit = false; + DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("apparent paste position is %1\n", position)); if (internal_editing()) { if (cut_buffer->midi_notes.empty()) { @@ -4171,12 +3923,11 @@ Editor::paste_internal (nframes64_t position, float times) } } - if (position == max_frames) { + if (position == max_framepos) { position = get_preferred_edit_position(); + DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("preferred edit position is %1\n", position)); } - begin_reversible_command (_("paste")); - TrackViewList ts; TrackViewList::iterator i; size_t nth; @@ -4184,24 +3935,28 @@ Editor::paste_internal (nframes64_t position, float times) /* get everything in the correct order */ if (!selection->tracks.empty()) { + /* there are some selected tracks, so paste to them */ sort_track_selection (); ts = selection->tracks; - } else if (entered_track) { - ts.push_back (entered_track); + } else if (_last_cut_copy_source_track) { + /* otherwise paste to the track that the cut/copy came from; + see discussion in mants #3333. + */ + ts.push_back (_last_cut_copy_source_track); } - for (nth = 0, i = ts.begin(); i != ts.end(); ++i, ++nth) { + if (internal_editing ()) { /* undo/redo is handled by individual tracks/regions */ - - if (internal_editing()) { - + + for (nth = 0, i = ts.begin(); i != ts.end(); ++i, ++nth) { + RegionSelection rs; RegionSelection::iterator r; MidiNoteSelection::iterator cb; - + get_regions_at (rs, position, ts); - + for (cb = cut_buffer->midi_notes.begin(), r = rs.begin(); cb != cut_buffer->midi_notes.end() && r != rs.end(); ++r) { MidiRegionView* mrv = dynamic_cast (*r); @@ -4210,16 +3965,18 @@ Editor::paste_internal (nframes64_t position, float times) ++cb; } } + } + + } else { - } else { + /* we do redo (do you do voodoo?) */ - if ((*i)->paste (position, times, *cut_buffer, nth)) { - commit = true; - } + begin_reversible_command (Operations::paste); + + for (nth = 0, i = ts.begin(); i != ts.end(); ++i, ++nth) { + (*i)->paste (position, times, *cut_buffer, nth); } - } - - if (commit) { + commit_reversible_command (); } } @@ -4231,10 +3988,10 @@ Editor::duplicate_some_regions (RegionSelection& regions, float times) RegionSelection sel = regions; // clear (below) may clear the argument list if its the current region selection RegionSelection foo; - nframes_t const start_frame = regions.start (); - nframes_t const end_frame = regions.end_frame (); + framepos_t const start_frame = regions.start (); + framepos_t const end_frame = regions.end_frame (); - begin_reversible_command (_("duplicate region")); + begin_reversible_command (Operations::duplicate_region); selection->clear_regions (); @@ -4248,8 +4005,8 @@ Editor::duplicate_some_regions (RegionSelection& regions, float times) sigc::connection c = rtv->view()->RegionViewAdded.connect (sigc::mem_fun(*this, &Editor::collect_new_region_view)); playlist = (*i)->region()->playlist(); - playlist->clear_history (); - playlist->duplicate (r, end_frame + (r->first_frame() - start_frame) + 1, times); + playlist->clear_changes (); + playlist->duplicate (r, end_frame + (r->first_frame() - start_frame), times); _session->add_command(new StatefulDiffCommand (playlist)); c.disconnect (); @@ -4289,7 +4046,7 @@ Editor::duplicate_selection (float times) if ((playlist = (*i)->playlist()) == 0) { continue; } - playlist->clear_history (); + playlist->clear_changes (); playlist->duplicate (*ri, selection->time[clicked_selection].end, times); _session->add_command (new StatefulDiffCommand (playlist)); @@ -4331,23 +4088,22 @@ Editor::center_edit_point () center_screen_internal (get_preferred_edit_position(), page); } +/** Caller must begin and commit a reversible command */ void Editor::clear_playlist (boost::shared_ptr playlist) { - begin_reversible_command (_("clear playlist")); - playlist->clear_history (); + playlist->clear_changes (); playlist->clear (); _session->add_command (new StatefulDiffCommand (playlist)); - commit_reversible_command (); } void Editor::nudge_track (bool use_edit, bool forwards) { boost::shared_ptr playlist; - nframes64_t distance; - nframes64_t next_distance; - nframes64_t start; + framepos_t distance; + framepos_t next_distance; + framepos_t start; if (use_edit) { start = get_preferred_edit_position(); @@ -4371,20 +4127,17 @@ Editor::nudge_track (bool use_edit, bool forwards) continue; } - playlist->clear_history (); - playlist->clear_owned_history (); + playlist->clear_changes (); + playlist->clear_owned_changes (); playlist->nudge_after (start, distance, forwards); - - vector cmds; - - playlist->rdiff (cmds); - - for (vector::iterator c = cmds.begin(); c != cmds.end(); ++c) { - _session->add_command (*c); - } - - _session->add_command (new StatefulDiffCommand (playlist)); + + vector cmds; + + playlist->rdiff (cmds); + _session->add_commands (cmds); + + _session->add_command (new StatefulDiffCommand (playlist)); } commit_reversible_command (); @@ -4411,10 +4164,12 @@ Editor::remove_last_capture () if (prompter.run () == 1) { _session->remove_last_capture (); + _regions->redisplay (); } } else { _session->remove_last_capture(); + _regions->redisplay (); } } @@ -4425,54 +4180,69 @@ Editor::normalize_region () return; } - RegionSelection rs; - get_regions_for_action (rs); - + RegionSelection rs = get_regions_from_selection_and_entered (); + if (rs.empty()) { return; } - Dialog dialog (rs.size() > 1 ? _("Normalize regions") : _("Normalize region")); - HBox hbox; - hbox.set_spacing (6); - hbox.set_border_width (6); - hbox.pack_start (*manage (new Label (_("Normalize to:")))); - SpinButton spin (0.2, 2); - spin.set_range (-112, 0); - spin.set_increments (0.1, 1); - spin.set_value (0); - hbox.pack_start (spin); - spin.set_value (_last_normalization_value); - hbox.pack_start (*manage (new Label (_("dbFS")))); - hbox.show_all (); - dialog.get_vbox()->set_spacing (12); - dialog.get_vbox()->pack_start (hbox); - dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL); - dialog.add_button (_("Normalize"), RESPONSE_ACCEPT); + NormalizeDialog dialog (rs.size() > 1); if (dialog.run () == RESPONSE_CANCEL) { return; } - begin_reversible_command (_("normalize")); - - track_canvas->get_window()->set_cursor (*wait_cursor); + set_canvas_cursor (_cursors->wait); gdk_flush (); + /* XXX: should really only count audio regions here */ + int const regions = rs.size (); + + /* Make a list of the selected audio regions' maximum amplitudes, and also + obtain the maximum amplitude of them all. + */ + list max_amps; + double max_amp = 0; + for (RegionSelection::const_iterator i = rs.begin(); i != rs.end(); ++i) { + AudioRegionView const * arv = dynamic_cast (*i); + if (arv) { + dialog.descend (1.0 / regions); + double const a = arv->audio_region()->maximum_amplitude (&dialog); + + if (a == -1) { + /* the user cancelled the operation */ + set_canvas_cursor (current_canvas_cursor); + return; + } + + max_amps.push_back (a); + max_amp = max (max_amp, a); + dialog.ascend (); + } + } + + begin_reversible_command (_("normalize")); + + list::const_iterator a = max_amps.begin (); + for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) { - AudioRegionView* const arv = dynamic_cast(*r); - if (!arv) + AudioRegionView* const arv = dynamic_cast (*r); + if (!arv) { continue; - arv->region()->clear_history (); - arv->audio_region()->normalize_to (spin.get_value()); + } + + arv->region()->clear_changes (); + + double const amp = dialog.normalize_individually() ? *a : max_amp; + + arv->audio_region()->normalize (amp, dialog.target ()); _session->add_command (new StatefulDiffCommand (arv->region())); - + + ++a; } commit_reversible_command (); - track_canvas->get_window()->set_cursor (*current_canvas_cursor); - - _last_normalization_value = spin.get_value (); + set_canvas_cursor (current_canvas_cursor); } @@ -4483,9 +4253,7 @@ Editor::reset_region_scale_amplitude () return; } - RegionSelection rs; - - get_regions_for_action (rs); + RegionSelection rs = get_regions_from_selection_and_entered (); if (rs.empty()) { return; @@ -4497,7 +4265,7 @@ Editor::reset_region_scale_amplitude () AudioRegionView* const arv = dynamic_cast(*r); if (!arv) continue; - arv->region()->clear_history (); + arv->region()->clear_changes (); arv->audio_region()->set_scale_amplitude (1.0f); _session->add_command (new StatefulDiffCommand (arv->region())); } @@ -4506,51 +4274,33 @@ Editor::reset_region_scale_amplitude () } void -Editor::adjust_region_scale_amplitude (bool up) +Editor::adjust_region_gain (bool up) { - if (!_session) { - return; - } - - RegionSelection rs; - - get_regions_for_action (rs); + RegionSelection rs = get_regions_from_selection_and_entered (); - if (rs.empty()) { + if (!_session || rs.empty()) { return; } - begin_reversible_command ("denormalize"); + begin_reversible_command ("adjust region gain"); for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) { AudioRegionView* const arv = dynamic_cast(*r); if (!arv) { continue; - } - - arv->region()->clear_history (); - - double fraction = gain_to_slider_position (arv->audio_region()->scale_amplitude ()); - - if (up) { - fraction += 0.05; - fraction = min (fraction, 1.0); - } else { - fraction -= 0.05; - fraction = max (fraction, 0.0); } - if (!up && fraction <= 0) { - continue; - } + arv->region()->clear_changes (); - fraction = slider_position_to_gain (fraction); + double dB = accurate_coefficient_to_dB (arv->audio_region()->scale_amplitude ()); - if (up && fraction >= 2.0) { - continue; + if (up) { + dB += 1; + } else { + dB -= 1; } - arv->audio_region()->set_scale_amplitude (fraction); + arv->audio_region()->set_scale_amplitude (dB_to_coefficient (dB)); _session->add_command (new StatefulDiffCommand (arv->region())); } @@ -4576,36 +4326,39 @@ Editor::strip_region_silence () return; } - RegionSelection rs; - get_regions_for_action (rs); + RegionSelection rs = get_regions_from_selection_and_entered (); if (rs.empty()) { return; } - std::list > ar; + std::list audio_only; for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { AudioRegionView* const arv = dynamic_cast (*i); if (arv) { - ar.push_back (arv->audio_region ()); + audio_only.push_back (arv); } } - StripSilenceDialog d (_session, ar); + StripSilenceDialog d (_session, audio_only); int const r = d.run (); - if (r == Gtk::RESPONSE_OK) { - StripSilence s (*_session, d.threshold (), d.minimum_length (), d.fade_length ()); - apply_filter (s, _("strip silence")); - } + d.drop_rects (); + + if (r == Gtk::RESPONSE_OK) { + ARDOUR::AudioIntervalMap silences; + d.silences (silences); + StripSilence s (*_session, silences, d.fade_length()); + apply_filter (s, _("strip silence"), &d); + } } Command* Editor::apply_midi_note_edit_op_to_region (MidiOperator& op, MidiRegionView& mrv) { Evoral::Sequence::Notes selected; - mrv.selection_as_notelist (selected); + mrv.selection_as_notelist (selected, true); vector::Notes> v; v.push_back (selected); @@ -4616,10 +4369,9 @@ Editor::apply_midi_note_edit_op_to_region (MidiOperator& op, MidiRegionView& mrv void Editor::apply_midi_note_edit_op (MidiOperator& op) { - RegionSelection rs; Command* cmd; - get_regions_for_action (rs); + RegionSelection rs = get_regions_from_selection_and_entered (); if (rs.empty()) { return; @@ -4645,15 +4397,12 @@ Editor::apply_midi_note_edit_op (MidiOperator& op) } commit_reversible_command (); - rs.clear (); } void Editor::fork_region () { - RegionSelection rs; - - get_regions_for_action (rs); + RegionSelection rs = get_regions_from_selection_and_entered (); if (rs.empty()) { return; @@ -4661,7 +4410,7 @@ Editor::fork_region () begin_reversible_command (_("Fork Region(s)")); - track_canvas->get_window()->set_cursor (*wait_cursor); + set_canvas_cursor (_cursors->wait); gdk_flush (); for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ) { @@ -4672,30 +4421,47 @@ Editor::fork_region () if (mrv) { boost::shared_ptr playlist = mrv->region()->playlist(); - boost::shared_ptr newregion = mrv->midi_region()->clone (); + boost::shared_ptr newregion = mrv->midi_region()->clone (); - playlist->clear_history (); - cerr << "Replace region with " << newregion->name() << endl; - playlist->replace_region (mrv->region(), newregion, mrv->region()->position()); - _session->add_command(new StatefulDiffCommand (playlist)); + playlist->clear_changes (); + playlist->replace_region (mrv->region(), newregion, mrv->region()->position()); + _session->add_command(new StatefulDiffCommand (playlist)); } r = tmp; } commit_reversible_command (); - rs.clear (); - track_canvas->get_window()->set_cursor (*current_canvas_cursor); + set_canvas_cursor (current_canvas_cursor); } void Editor::quantize_region () { + int selected_midi_region_cnt = 0; + if (!_session) { return; } + RegionSelection rs = get_regions_from_selection_and_entered (); + + if (rs.empty()) { + return; + } + + for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) { + MidiRegionView* const mrv = dynamic_cast (*r); + if (mrv) { + selected_midi_region_cnt++; + } + } + + if (selected_midi_region_cnt == 0) { + return; + } + QuantizeDialog* qd = new QuantizeDialog (*this); qd->present (); @@ -4713,11 +4479,36 @@ Editor::quantize_region () } void -Editor::apply_filter (Filter& filter, string command) +Editor::insert_patch_change () { - RegionSelection rs; + RegionSelection rs = get_regions_from_selection_and_entered (); + if (rs.empty ()) { + return; + } - get_regions_for_action (rs); + framepos_t const p = get_preferred_edit_position (false); + + Evoral::PatchChange empty (0, 0, 0, 0); + PatchChangeDialog d (0, _session, empty, Gtk::Stock::ADD); + + if (d.run() == RESPONSE_CANCEL) { + return; + } + + for (RegionSelection::iterator i = rs.begin (); i != rs.end(); ++i) { + MidiRegionView* const mrv = dynamic_cast (*i); + if (mrv) { + if (p >= mrv->region()->first_frame() && p <= mrv->region()->last_frame()) { + mrv->add_patch_change (p - mrv->region()->position(), d.patch ()); + } + } + } +} + +void +Editor::apply_filter (Filter& filter, string command, ProgressReporter* progress) +{ + RegionSelection rs = get_regions_from_selection_and_entered (); if (rs.empty()) { return; @@ -4725,9 +4516,12 @@ Editor::apply_filter (Filter& filter, string command) begin_reversible_command (command); - track_canvas->get_window()->set_cursor (*wait_cursor); + set_canvas_cursor (_cursors->wait); gdk_flush (); + int n = 0; + int const N = rs.size (); + for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ) { RegionSelection::iterator tmp = r; ++tmp; @@ -4736,10 +4530,14 @@ Editor::apply_filter (Filter& filter, string command) if (arv) { boost::shared_ptr playlist = arv->region()->playlist(); - if (arv->audio_region()->apply (filter) == 0) { + if (progress) { + progress->descend (1.0 / N); + } + + if (arv->audio_region()->apply (filter, progress) == 0) { + + playlist->clear_changes (); - playlist->clear_history (); - if (filter.results.empty ()) { /* no regions returned; remove the old one */ @@ -4765,44 +4563,20 @@ Editor::apply_filter (Filter& filter, string command) } else { goto out; } + + if (progress) { + progress->ascend (); + } } r = tmp; + ++n; } commit_reversible_command (); - rs.clear (); out: - track_canvas->get_window()->set_cursor (*current_canvas_cursor); -} - -void -Editor::region_selection_op (void (Region::*pmf)(void)) -{ - for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { - Region* region = (*i)->region().get(); - (region->*pmf)(); - } -} - - -void -Editor::region_selection_op (void (Region::*pmf)(void*), void *arg) -{ - for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { - Region* region = (*i)->region().get(); - (region->*pmf)(arg); - } -} - -void -Editor::region_selection_op (void (Region::*pmf)(bool), bool yn) -{ - for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { - Region* region = (*i)->region().get(); - (region->*pmf)(yn); - } + set_canvas_cursor (current_canvas_cursor); } void @@ -4811,29 +4585,10 @@ Editor::external_edit_region () /* more to come */ } -void -Editor::brush (nframes64_t pos) -{ - RegionSelection sel; - RegionSelection rs; - - get_regions_for_action (rs); - - snap_to (pos); - - if (rs.empty()) { - return; - } - - for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { - mouse_brush_insert_region ((*i), pos); - } -} - void Editor::reset_region_gain_envelopes () { - RegionSelection rs = get_equivalent_regions (selection->regions, ARDOUR::Properties::edit.property_id); + RegionSelection rs = get_regions_from_selection_and_entered (); if (!_session || rs.empty()) { return; @@ -4858,7 +4613,11 @@ Editor::reset_region_gain_envelopes () void Editor::toggle_gain_envelope_visibility () { - RegionSelection rs = get_equivalent_regions (selection->regions, ARDOUR::Properties::edit.property_id); + if (_ignore_region_action) { + return; + } + + RegionSelection rs = get_regions_from_selection_and_entered (); if (!_session || rs.empty()) { return; @@ -4869,7 +4628,7 @@ Editor::toggle_gain_envelope_visibility () for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { AudioRegionView* const arv = dynamic_cast(*i); if (arv) { - arv->region()->clear_history (); + arv->region()->clear_changes (); arv->set_envelope_visible (!arv->envelope_visible()); _session->add_command (new StatefulDiffCommand (arv->region())); } @@ -4881,7 +4640,11 @@ Editor::toggle_gain_envelope_visibility () void Editor::toggle_gain_envelope_active () { - RegionSelection rs = get_equivalent_regions (selection->regions, ARDOUR::Properties::edit.property_id); + if (_ignore_region_action) { + return; + } + + RegionSelection rs = get_regions_from_selection_and_entered (); if (!_session || rs.empty()) { return; @@ -4892,7 +4655,7 @@ Editor::toggle_gain_envelope_active () for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { AudioRegionView* const arv = dynamic_cast(*i); if (arv) { - arv->region()->clear_history (); + arv->region()->clear_changes (); arv->audio_region()->set_envelope_active (!arv->audio_region()->envelope_active()); _session->add_command (new StatefulDiffCommand (arv->region())); } @@ -4904,16 +4667,20 @@ Editor::toggle_gain_envelope_active () void Editor::toggle_region_lock () { - RegionSelection rs = get_equivalent_regions (selection->regions, ARDOUR::Properties::edit.property_id); + if (_ignore_region_action) { + return; + } + + RegionSelection rs = get_regions_from_selection_and_entered (); if (!_session || rs.empty()) { return; } - _session->begin_reversible_command (_("region lock")); + _session->begin_reversible_command (_("toggle region lock")); for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { - (*i)->region()->clear_history (); + (*i)->region()->clear_changes (); (*i)->region()->set_locked (!(*i)->region()->locked()); _session->add_command (new StatefulDiffCommand ((*i)->region())); } @@ -4924,7 +4691,11 @@ Editor::toggle_region_lock () void Editor::toggle_region_lock_style () { - RegionSelection rs = get_equivalent_regions (selection->regions, ARDOUR::Properties::edit.property_id); + if (_ignore_region_action) { + return; + } + + RegionSelection rs = get_regions_from_selection_and_entered (); if (!_session || rs.empty()) { return; @@ -4933,8 +4704,8 @@ Editor::toggle_region_lock_style () _session->begin_reversible_command (_("region lock style")); for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { - (*i)->region()->clear_history (); - Region::PositionLockStyle const ns = (*i)->region()->positional_lock_style() == Region::AudioTime ? Region::MusicTime : Region::AudioTime; + (*i)->region()->clear_changes (); + PositionLockStyle const ns = (*i)->region()->position_lock_style() == AudioTime ? MusicTime : AudioTime; (*i)->region()->set_position_lock_style (ns); _session->add_command (new StatefulDiffCommand ((*i)->region())); } @@ -4942,40 +4713,23 @@ Editor::toggle_region_lock_style () _session->commit_reversible_command (); } - void -Editor::toggle_region_mute () +Editor::toggle_opaque_region () { - RegionSelection rs = get_equivalent_regions (selection->regions, ARDOUR::Properties::edit.property_id); - - if (!_session || rs.empty()) { + if (_ignore_region_action) { return; } - - _session->begin_reversible_command (_("region mute")); - - for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { - (*i)->region()->clear_history (); - (*i)->region()->set_muted (!(*i)->region()->muted()); - _session->add_command (new StatefulDiffCommand ((*i)->region())); - } - - _session->commit_reversible_command (); -} - -void -Editor::toggle_region_opaque () -{ - RegionSelection rs = get_equivalent_regions (selection->regions, ARDOUR::Properties::edit.property_id); + + RegionSelection rs = get_regions_from_selection_and_entered (); if (!_session || rs.empty()) { return; } - _session->begin_reversible_command (_("region opacity")); + _session->begin_reversible_command (_("change region opacity")); for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { - (*i)->region()->clear_history (); + (*i)->region()->clear_changes (); (*i)->region()->set_opaque (!(*i)->region()->opaque()); _session->add_command (new StatefulDiffCommand ((*i)->region())); } @@ -5000,7 +4754,7 @@ Editor::toggle_record_enable () first = false; } - rtav->track()->set_record_enable(new_state, this); + rtav->track()->set_record_enabled (new_state, this); } } @@ -5008,9 +4762,7 @@ Editor::toggle_record_enable () void Editor::set_fade_length (bool in) { - RegionSelection rs; - - get_regions_for_action (rs, true); + RegionSelection rs = get_regions_from_selection_and_entered (); if (rs.empty()) { return; @@ -5020,8 +4772,8 @@ Editor::set_fade_length (bool in) RegionView* rv = rs.front (); - nframes64_t pos = get_preferred_edit_position(); - nframes64_t len; + framepos_t pos = get_preferred_edit_position(); + framepos_t len; char const * cmd; if (pos > rv->region()->last_frame() || pos < rv->region()->first_frame()) { @@ -5079,62 +4831,9 @@ Editor::set_fade_length (bool in) } void -Editor::toggle_fade_active (bool in) +Editor::set_fade_in_shape (FadeShape shape) { - RegionSelection rs; - - get_regions_for_action (rs); - - if (rs.empty()) { - return; - } - - const char* cmd = (in ? _("toggle fade in active") : _("toggle fade out active")); - bool have_switch = false; - bool yn = false; - - begin_reversible_command (cmd); - - for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ++x) { - AudioRegionView* tmp = dynamic_cast (*x); - - if (!tmp) { - return; - } - - boost::shared_ptr region (tmp->audio_region()); - - /* make the behaviour consistent across all regions */ - - if (!have_switch) { - if (in) { - yn = region->fade_in_active(); - } else { - yn = region->fade_out_active(); - } - have_switch = true; - } - - region->clear_history (); - - if (in) { - region->set_fade_in_active (!yn); - } else { - region->set_fade_out_active (!yn); - } - - _session->add_command(new StatefulDiffCommand (region)); - } - - commit_reversible_command (); -} - -void -Editor::set_fade_in_shape (AudioRegion::FadeShape shape) -{ - RegionSelection rs; - - get_regions_for_action (rs); + RegionSelection rs = get_regions_from_selection_and_entered (); if (rs.empty()) { return; @@ -5163,11 +4862,9 @@ Editor::set_fade_in_shape (AudioRegion::FadeShape shape) } void -Editor::set_fade_out_shape (AudioRegion::FadeShape shape) +Editor::set_fade_out_shape (FadeShape shape) { - RegionSelection rs; - - get_regions_for_action (rs); + RegionSelection rs = get_regions_from_selection_and_entered (); if (rs.empty()) { return; @@ -5197,9 +4894,7 @@ Editor::set_fade_out_shape (AudioRegion::FadeShape shape) void Editor::set_fade_in_active (bool yn) { - RegionSelection rs; - - get_regions_for_action (rs); + RegionSelection rs = get_regions_from_selection_and_entered (); if (rs.empty()) { return; @@ -5217,7 +4912,7 @@ Editor::set_fade_in_active (bool yn) boost::shared_ptr ar (tmp->audio_region()); - ar->clear_history (); + ar->clear_changes (); ar->set_fade_in_active (yn); _session->add_command (new StatefulDiffCommand (ar)); } @@ -5228,9 +4923,7 @@ Editor::set_fade_in_active (bool yn) void Editor::set_fade_out_active (bool yn) { - RegionSelection rs; - - get_regions_for_action (rs); + RegionSelection rs = get_regions_from_selection_and_entered (); if (rs.empty()) { return; @@ -5247,7 +4940,7 @@ Editor::set_fade_out_active (bool yn) boost::shared_ptr ar (tmp->audio_region()); - ar->clear_history (); + ar->clear_changes (); ar->set_fade_out_active (yn); _session->add_command(new StatefulDiffCommand (ar)); } @@ -5256,19 +4949,18 @@ Editor::set_fade_out_active (bool yn) } void -Editor::toggle_selected_region_fades (int dir) +Editor::toggle_region_fades (int dir) { - RegionSelection rs; - RegionSelection::iterator i; boost::shared_ptr ar; bool yn; - get_regions_for_action (rs); + RegionSelection rs = get_regions_from_selection_and_entered (); if (rs.empty()) { return; } + RegionSelection::iterator i; for (i = rs.begin(); i != rs.end(); ++i) { if ((ar = boost::dynamic_pointer_cast((*i)->region())) != 0) { if (dir == -1) { @@ -5340,7 +5032,7 @@ Editor::update_xfade_visibility () void Editor::set_edit_point () { - nframes64_t where; + framepos_t where; bool ignored; if (!mouse_frame (where, ignored)) { @@ -5370,7 +5062,7 @@ Editor::set_playhead_cursor () if (entered_marker) { _session->request_locate (entered_marker->position(), _session->transport_rolling()); } else { - nframes64_t where; + framepos_t where; bool ignored; if (!mouse_frame (where, ignored)) { @@ -5386,13 +5078,18 @@ Editor::set_playhead_cursor () } void -Editor::split () +Editor::split_region () { - RegionSelection rs; + if (((mouse_mode == MouseRange) || + (mouse_mode != MouseObject && _join_object_range_state == JOIN_OBJECT_RANGE_RANGE)) && + !selection->time.empty()) { + separate_regions_between (selection->time); + return; + } - get_regions_for_action (rs, true); + RegionSelection rs = get_regions_from_selection_and_edit_point (); - nframes64_t where = get_preferred_edit_position(); + framepos_t where = get_preferred_edit_position (); if (rs.empty()) { return; @@ -5502,7 +5199,7 @@ Editor::ensure_track_visible(TimeAxisView *track) double const track_max_y = track->y_position () + track->effective_height (); if (track_min_y >= current_view_min_y && - track_max_y <= current_view_max_y) { + track_max_y <= current_view_max_y) { return; } @@ -5526,8 +5223,8 @@ Editor::set_loop_from_selection (bool play) return; } - nframes64_t start = selection->time[clicked_selection].start; - nframes64_t end = selection->time[clicked_selection].end; + framepos_t start = selection->time[clicked_selection].start; + framepos_t end = selection->time[clicked_selection].end; set_loop_range (start, end, _("set loop range from selection")); @@ -5544,8 +5241,8 @@ Editor::set_loop_from_edit_range (bool play) return; } - nframes64_t start; - nframes64_t end; + framepos_t start; + framepos_t end; if (!get_edit_op_range (start, end)) { return; @@ -5562,12 +5259,10 @@ Editor::set_loop_from_edit_range (bool play) void Editor::set_loop_from_region (bool play) { - nframes64_t start = max_frames; - nframes64_t end = 0; + framepos_t start = max_framepos; + framepos_t end = 0; - RegionSelection rs; - - get_regions_for_action (rs); + RegionSelection rs = get_regions_from_selection_and_entered (); if (rs.empty()) { return; @@ -5597,8 +5292,8 @@ Editor::set_punch_from_selection () return; } - nframes64_t start = selection->time[clicked_selection].start; - nframes64_t end = selection->time[clicked_selection].end; + framepos_t start = selection->time[clicked_selection].start; + framepos_t end = selection->time[clicked_selection].end; set_punch_range (start, end, _("set punch range from selection")); } @@ -5610,8 +5305,8 @@ Editor::set_punch_from_edit_range () return; } - nframes64_t start; - nframes64_t end; + framepos_t start; + framepos_t end; if (!get_edit_op_range (start, end)) { return; @@ -5623,12 +5318,10 @@ Editor::set_punch_from_edit_range () void Editor::set_punch_from_region () { - nframes64_t start = max_frames; - nframes64_t end = 0; - - RegionSelection rs; + framepos_t start = max_framepos; + framepos_t end = 0; - get_regions_for_action (rs); + RegionSelection rs = get_regions_from_selection_and_entered (); if (rs.empty()) { return; @@ -5647,11 +5340,9 @@ Editor::set_punch_from_region () } void -Editor::pitch_shift_regions () +Editor::pitch_shift_region () { - RegionSelection rs; - - get_regions_for_action (rs); + RegionSelection rs = get_regions_from_selection_and_entered (); if (rs.empty()) { return; @@ -5661,17 +5352,11 @@ Editor::pitch_shift_regions () } void -Editor::use_region_as_bar () +Editor::set_tempo_from_region () { - if (!_session) { - return; - } - - RegionSelection rs; - - get_regions_for_action (rs); + RegionSelection rs = get_regions_from_selection_and_entered (); - if (rs.empty()) { + if (!_session || rs.empty()) { return; } @@ -5683,16 +5368,16 @@ Editor::use_region_as_bar () void Editor::use_range_as_bar () { - nframes64_t start, end; + framepos_t start, end; if (get_edit_op_range (start, end)) { define_one_bar (start, end); } } void -Editor::define_one_bar (nframes64_t start, nframes64_t end) +Editor::define_one_bar (framepos_t start, framepos_t end) { - nframes64_t length = end - start; + framepos_t length = end - start; const Meter& m (_session->tempo_map().meter_at (start)); @@ -5780,15 +5465,9 @@ Editor::split_region_at_transients () { AnalysisFeatureList positions; - if (!_session) { - return; - } - - RegionSelection rs; - - get_regions_for_action (rs); + RegionSelection rs = get_regions_from_selection_and_entered (); - if (rs.empty()) { + if (!_session || rs.empty()) { return; } @@ -5816,11 +5495,13 @@ Editor::split_region_at_transients () } void -Editor::split_region_at_points (boost::shared_ptr r, AnalysisFeatureList& positions, bool can_ferret) +Editor::split_region_at_points (boost::shared_ptr r, AnalysisFeatureList& positions, bool can_ferret, bool select_new) { bool use_rhythmic_rodent = false; - + boost::shared_ptr pl = r->playlist(); + + list > new_regions; if (!pl) { return; @@ -5831,8 +5512,8 @@ Editor::split_region_at_points (boost::shared_ptr r, AnalysisFeatureList } - if (positions.size() > 20) { - Glib::ustring msgstr = string_compose (_("You are about to split\n%1\ninto %2 pieces.\nThis could take a long time."), r->name(), positions.size() + 1); + if (positions.size() > 20 && can_ferret) { + std::string msgstr = string_compose (_("You are about to split\n%1\ninto %2 pieces.\nThis could take a long time."), r->name(), positions.size() + 1); MessageDialog msg (msgstr, false, Gtk::MESSAGE_INFO, @@ -5850,6 +5531,7 @@ Editor::split_region_at_points (boost::shared_ptr r, AnalysisFeatureList int response = msg.run(); msg.hide (); + switch (response) { case RESPONSE_OK: break; @@ -5868,19 +5550,10 @@ Editor::split_region_at_points (boost::shared_ptr r, AnalysisFeatureList AnalysisFeatureList::const_iterator x; - nframes64_t pos = r->position(); - - pl->clear_history (); + pl->clear_changes (); x = positions.begin(); - while (x != positions.end()) { - if ((*x) > pos) { - break; - } - ++x; - } - if (x == positions.end()) { return; } @@ -5888,18 +5561,26 @@ Editor::split_region_at_points (boost::shared_ptr r, AnalysisFeatureList pl->freeze (); pl->remove_region (r); + framepos_t pos = 0; + while (x != positions.end()) { + + /* deal with positons that are out of scope of present region bounds */ + if (*x <= 0 || *x > r->length()) { + ++x; + continue; + } /* file start = original start + how far we from the initial position ? */ - nframes64_t file_start = r->start() + (pos - r->position()); + framepos_t file_start = r->start() + pos; /* length = next position - current position */ - nframes64_t len = (*x) - pos; - + framepos_t len = (*x) - pos; + /* XXX we do we really want to allow even single-sample regions? shouldn't we have some kind of lower limit on region size? */ @@ -5924,35 +5605,225 @@ Editor::split_region_at_points (boost::shared_ptr r, AnalysisFeatureList plist.add (ARDOUR::Properties::layer, 0); boost::shared_ptr nr = RegionFactory::create (r->sources(), plist, false); - pl->add_region (nr, pos); + + pl->add_region (nr, r->position() + pos); + + if (select_new) { + new_regions.push_front(nr); + } pos += len; ++x; + } - if (*x > r->last_frame()) { + string new_name; - /* add final fragment */ + RegionFactory::region_name (new_name, r->name()); + + /* Add the final region */ + PropertyList plist; + + plist.add (ARDOUR::Properties::start, r->start() + pos); + plist.add (ARDOUR::Properties::length, r->last_frame() - (r->position() + pos) + 1); + plist.add (ARDOUR::Properties::name, new_name); + plist.add (ARDOUR::Properties::layer, 0); - file_start = r->start() + (pos - r->position()); - len = r->last_frame() - pos; + boost::shared_ptr nr = RegionFactory::create (r->sources(), plist, false); + pl->add_region (nr, r->position() + pos); + + if (select_new) { + new_regions.push_front(nr); + } - PropertyList plist2; - - plist2.add (ARDOUR::Properties::start, file_start); - plist2.add (ARDOUR::Properties::length, len); - plist2.add (ARDOUR::Properties::name, new_name); - plist2.add (ARDOUR::Properties::layer, 0); + pl->thaw (); - nr = RegionFactory::create (r->sources(), plist2); - pl->add_region (nr, pos); + _session->add_command (new StatefulDiffCommand (pl)); + + if (select_new) { - break; + for (list >::iterator i = new_regions.begin(); i != new_regions.end(); ++i){ + set_selected_regionview_from_region_list ((*i), Selection::Add); } } +} - pl->thaw (); +void +Editor::place_transient() +{ + if (!_session) { + return; + } - _session->add_command (new StatefulDiffCommand (pl)); + RegionSelection rs = get_regions_from_selection_and_edit_point (); + + if (rs.empty()) { + return; + } + + framepos_t where = get_preferred_edit_position(); + + _session->begin_reversible_command (_("place transient")); + + for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) { + framepos_t position = (*r)->region()->position(); + (*r)->region()->add_transient(where - position); + } + + _session->commit_reversible_command (); +} + +void +Editor::remove_transient(ArdourCanvas::Item* item) +{ + if (!_session) { + return; + } + + ArdourCanvas::Line* _line = reinterpret_cast (item); + assert (_line); + + AudioRegionView* _arv = reinterpret_cast (item->get_data ("regionview")); + _arv->remove_transient (*(float*) _line->get_data ("position")); +} + +void +Editor::snap_regions_to_grid () +{ + list > used_playlists; + + RegionSelection rs = get_regions_from_selection_and_entered (); + + if (!_session || rs.empty()) { + return; + } + + _session->begin_reversible_command (_("snap regions to grid")); + + for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) { + + boost::shared_ptr pl = (*r)->region()->playlist(); + + if (!pl->frozen()) { + /* we haven't seen this playlist before */ + + /* remember used playlists so we can thaw them later */ + used_playlists.push_back(pl); + pl->freeze(); + } + + framepos_t start_frame = (*r)->region()->first_frame (); + snap_to (start_frame); + (*r)->region()->set_position (start_frame, this); + } + + while (used_playlists.size() > 0) { + list >::iterator i = used_playlists.begin(); + (*i)->thaw(); + used_playlists.pop_front(); + } + + _session->commit_reversible_command (); +} + +void +Editor::close_region_gaps () +{ + list > used_playlists; + + RegionSelection rs = get_regions_from_selection_and_entered (); + + if (!_session || rs.empty()) { + return; + } + + Dialog dialog (_("Close Region Gaps")); + + Table table (2, 3); + table.set_spacings (12); + table.set_border_width (12); + Label* l = manage (new Label (_("Crossfade length"))); + l->set_alignment (0, 0.5); + table.attach (*l, 0, 1, 0, 1); + + SpinButton spin_crossfade (1, 0); + spin_crossfade.set_range (0, 15); + spin_crossfade.set_increments (1, 1); + spin_crossfade.set_value (5); + table.attach (spin_crossfade, 1, 2, 0, 1); + + table.attach (*manage (new Label (_("ms"))), 2, 3, 0, 1); + + l = manage (new Label (_("Pull-back length"))); + l->set_alignment (0, 0.5); + table.attach (*l, 0, 1, 1, 2); + + SpinButton spin_pullback (1, 0); + spin_pullback.set_range (0, 100); + spin_pullback.set_increments (1, 1); + spin_pullback.set_value(30); + table.attach (spin_pullback, 1, 2, 1, 2); + + table.attach (*manage (new Label (_("ms"))), 2, 3, 1, 2); + + dialog.get_vbox()->pack_start (table); + dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL); + dialog.add_button (_("Ok"), RESPONSE_ACCEPT); + dialog.show_all (); + + if (dialog.run () == RESPONSE_CANCEL) { + return; + } + + framepos_t crossfade_len = spin_crossfade.get_value(); + framepos_t pull_back_frames = spin_pullback.get_value(); + + crossfade_len = lrintf (crossfade_len * _session->frame_rate()/1000); + pull_back_frames = lrintf (pull_back_frames * _session->frame_rate()/1000); + + /* Iterate over the region list and make adjacent regions overlap by crossfade_len_ms */ + + _session->begin_reversible_command (_("close region gaps")); + + int idx = 0; + boost::shared_ptr last_region; + + rs.sort_by_position_and_track(); + + for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) { + + boost::shared_ptr pl = (*r)->region()->playlist(); + + if (!pl->frozen()) { + /* we haven't seen this playlist before */ + + /* remember used playlists so we can thaw them later */ + used_playlists.push_back(pl); + pl->freeze(); + } + + framepos_t position = (*r)->region()->position(); + + if (idx == 0 || position < last_region->position()){ + last_region = (*r)->region(); + idx++; + continue; + } + + (*r)->region()->trim_front( (position - pull_back_frames), this ); + last_region->trim_end( (position - pull_back_frames + crossfade_len), this ); + + last_region = (*r)->region(); + + idx++; + } + + while (used_playlists.size() > 0) { + list >::iterator i = used_playlists.begin(); + (*i)->thaw(); + used_playlists.pop_front(); + } + + _session->commit_reversible_command (); } void @@ -5960,11 +5831,13 @@ Editor::tab_to_transient (bool forward) { AnalysisFeatureList positions; + RegionSelection rs = get_regions_from_selection_and_entered (); + if (!_session) { return; } - nframes64_t pos = _session->audible_frame (); + framepos_t pos = _session->audible_frame (); if (!selection->tracks.empty()) { @@ -5977,7 +5850,7 @@ Editor::tab_to_transient (bool forward) if (tr) { boost::shared_ptr pl = tr->playlist (); if (pl) { - nframes64_t result = pl->find_next_transient (pos, forward ? 1 : -1); + framepos_t result = pl->find_next_transient (pos, forward ? 1 : -1); if (result >= 0) { positions.push_back (result); @@ -5989,10 +5862,6 @@ Editor::tab_to_transient (bool forward) } else { - RegionSelection rs; - - get_regions_for_action (rs); - if (rs.empty()) { return; } @@ -6031,12 +5900,13 @@ Editor::tab_to_transient (bool forward) } } } + void Editor::playhead_forward_to_grid () { if (!_session) return; - nframes64_t pos = playhead_cursor->current_frame; - if (pos < max_frames - 1) { + framepos_t pos = playhead_cursor->current_frame; + if (pos < max_framepos - 1) { pos += 2; snap_to_internal (pos, 1, false); _session->request_locate (pos); @@ -6048,7 +5918,7 @@ void Editor::playhead_backward_to_grid () { if (!_session) return; - nframes64_t pos = playhead_cursor->current_frame; + framepos_t pos = playhead_cursor->current_frame; if (pos > 2) { pos -= 2; snap_to_internal (pos, -1, false); @@ -6062,7 +5932,7 @@ Editor::set_track_height (Height h) TrackSelection& ts (selection->tracks); for (TrackSelection::iterator x = ts.begin(); x != ts.end(); ++x) { - (*x)->set_height (h); + (*x)->set_height_enum (h); } } @@ -6085,7 +5955,7 @@ Editor::toggle_tracks_active () target = !rtv->_route->active(); first = false; } - rtv->_route->set_active (target); + rtv->_route->set_active (target, this); } } } @@ -6106,6 +5976,7 @@ Editor::remove_tracks () const char* trackstr; const char* busstr; vector > routes; + bool special_bus = false; for (TrackSelection::iterator x = ts.begin(); x != ts.end(); ++x) { RouteTimeAxisView* rtv = dynamic_cast (*x); @@ -6117,10 +5988,32 @@ Editor::remove_tracks () } } routes.push_back (rtv->_route); + + if (rtv->route()->is_master() || rtv->route()->is_monitor()) { + special_bus = true; + } + } + + if (special_bus && !Config->get_allow_special_bus_removal()) { + MessageDialog msg (_("That would be bad news ...."), + false, + Gtk::MESSAGE_INFO, + Gtk::BUTTONS_OK); + msg.set_secondary_text (string_compose (_( + "Removing the master or monitor bus is such a bad idea\n\ +that %1 is not going to allow it.\n\ +\n\ +If you really want to do this sort of thing\n\ +edit your ardour.rc file to set the\n\ +\"allow-special-bus-removal\" option to be \"yes\""), PROGRAM_NAME)); + + msg.present (); + msg.run (); + return; } if (ntracks + nbusses == 0) { - return; + return; } if (ntracks > 1) { @@ -6139,16 +6032,17 @@ Editor::remove_tracks () if (nbusses) { prompt = string_compose (_("Do you really want to remove %1 %2 and %3 %4?\n" "(You may also lose the playlists associated with the %2)\n\n" - "This action cannot be undone!"), + "This action cannot be undone, and the session file will be overwritten!"), ntracks, trackstr, nbusses, busstr); } else { prompt = string_compose (_("Do you really want to remove %1 %2?\n" "(You may also lose the playlists associated with the %2)\n\n" - "This action cannot be undone!"), + "This action cannot be undone, and the session file will be overwritten!"), ntracks, trackstr); } } else if (nbusses) { - prompt = string_compose (_("Do you really want to remove %1 %2?"), + prompt = string_compose (_("Do you really want to remove %1 %2?\n\n" + "This action cannot be undon, and the session file will be overwritten"), nbusses, busstr); } @@ -6184,81 +6078,34 @@ Editor::do_insert_time () return; } - ArdourDialog d (*this, _("Insert Time")); - - nframes64_t const pos = get_preferred_edit_position (); - - d.get_vbox()->set_border_width (12); - d.get_vbox()->set_spacing (4); - - Table table (2, 2); - table.set_spacings (4); - - Label time_label (_("Time to insert:")); - time_label.set_alignment (1, 0.5); - table.attach (time_label, 0, 1, 0, 1, FILL | EXPAND); - AudioClock clock ("insertTimeClock", true, X_("InsertTimeClock"), true, false, true, true); - clock.set (0); - clock.set_session (_session); - clock.set_bbt_reference (pos); - table.attach (clock, 1, 2, 0, 1); - - Label intersected_label (_("Intersected regions should:")); - intersected_label.set_alignment (1, 0.5); - table.attach (intersected_label, 0, 1, 1, 2, FILL | EXPAND); - ComboBoxText intersected_combo; - intersected_combo.append_text (_("stay in position")); - intersected_combo.append_text (_("move")); - intersected_combo.append_text (_("be split")); - intersected_combo.set_active (0); - table.attach (intersected_combo, 1, 2, 1, 2); - - d.get_vbox()->pack_start (table); - - CheckButton move_glued (_("Move glued regions")); - d.get_vbox()->pack_start (move_glued); - CheckButton move_markers (_("Move markers")); - d.get_vbox()->pack_start (move_markers); - CheckButton move_tempos (_("Move tempo and meter changes")); - d.get_vbox()->pack_start (move_tempos); - - d.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); - d.add_button (_("Insert time"), Gtk::RESPONSE_OK); - d.show_all (); - + InsertTimeDialog d (*this); int response = d.run (); if (response != RESPONSE_OK) { return; } - nframes64_t distance = clock.current_duration (pos); - - if (distance == 0) { + if (d.distance() == 0) { return; } - /* only setting this to keep GCC quiet */ - InsertTimeOption opt = LeaveIntersected; - - switch (intersected_combo.get_active_row_number ()) { - case 0: - opt = LeaveIntersected; - break; - case 1: - opt = MoveIntersected; - break; - case 2: - opt = SplitIntersected; - break; - } + InsertTimeOption opt = d.intersected_region_action (); - insert_time (pos, distance, opt, move_glued.get_active(), move_markers.get_active(), move_tempos.get_active()); + insert_time ( + get_preferred_edit_position(), + d.distance(), + opt, + d.move_glued(), + d.move_markers(), + d.move_glued_markers(), + d.move_locked_markers(), + d.move_tempos() + ); } void -Editor::insert_time (nframes64_t pos, nframes64_t frames, InsertTimeOption opt, - bool ignore_music_glue, bool markers_too, bool tempo_too) +Editor::insert_time (framepos_t pos, framecnt_t frames, InsertTimeOption opt, + bool ignore_music_glue, bool markers_too, bool glued_markers_too, bool locked_markers_too, bool tempo_too) { bool commit = false; @@ -6274,8 +6121,8 @@ Editor::insert_time (nframes64_t pos, nframes64_t frames, InsertTimeOption opt, if (pl) { - pl->clear_history (); - pl->clear_owned_history (); + pl->clear_changes (); + pl->clear_owned_changes (); if (opt == SplitIntersected) { pl->split (pos); @@ -6283,16 +6130,10 @@ Editor::insert_time (nframes64_t pos, nframes64_t frames, InsertTimeOption opt, pl->shift (pos, frames, (opt == MoveIntersected), ignore_music_glue); - vector cmds; - - pl->rdiff (cmds); - - cerr << "Shift generated " << cmds.size() << " sdc's\n"; - - for (vector::iterator c = cmds.begin(); c != cmds.end(); ++c) { - _session->add_command (*c); - } - + vector cmds; + pl->rdiff (cmds); + _session->add_commands (cmds); + _session->add_command (new StatefulDiffCommand (pl)); commit = true; } @@ -6315,12 +6156,25 @@ Editor::insert_time (nframes64_t pos, nframes64_t frames, InsertTimeOption opt, Locations::LocationList::const_iterator tmp; - if ((*i)->start() >= pos) { - (*i)->set_start ((*i)->start() + frames); - if (!(*i)->is_mark()) { - (*i)->set_end ((*i)->end() + frames); + bool const was_locked = (*i)->locked (); + if (locked_markers_too) { + (*i)->unlock (); + } + + if ((*i)->position_lock_style() == AudioTime || glued_markers_too) { + + if ((*i)->start() >= pos) { + (*i)->set_start ((*i)->start() + frames); + if (!(*i)->is_mark()) { + (*i)->set_end ((*i)->end() + frames); + } + moved = true; } - moved = true; + + } + + if (was_locked) { + (*i)->lock (); } } @@ -6342,7 +6196,31 @@ Editor::insert_time (nframes64_t pos, nframes64_t frames, InsertTimeOption opt, void Editor::fit_selected_tracks () { - fit_tracks (selection->tracks); + if (!selection->tracks.empty()) { + fit_tracks (selection->tracks); + } else { + TrackViewList tvl; + + /* no selected tracks - use tracks with selected regions */ + + if (!selection->regions.empty()) { + for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) { + tvl.push_back (&(*r)->get_time_axis_view ()); + } + + if (!tvl.empty()) { + fit_tracks (tvl); + } + } else if (internal_editing()) { + /* no selected tracks, or regions, but in internal edit mode, so follow the mouse and use + the entered track + */ + if (entered_track) { + tvl.push_back (entered_track); + fit_tracks (tvl); + } + } + } } void @@ -6353,6 +6231,7 @@ Editor::fit_tracks (TrackViewList & tracks) } uint32_t child_heights = 0; + int visible_tracks = 0; for (TrackSelection::iterator t = tracks.begin(); t != tracks.end(); ++t) { @@ -6361,9 +6240,10 @@ Editor::fit_tracks (TrackViewList & tracks) } child_heights += (*t)->effective_height() - (*t)->current_height(); + ++visible_tracks; } - uint32_t h = (uint32_t) floor ((_canvas_height - child_heights - canvas_timebars_vsize) / tracks.size()); + uint32_t h = (uint32_t) floor ((_canvas_height - child_heights - canvas_timebars_vsize) / visible_tracks); double first_y_pos = DBL_MAX; if (h < TimeAxisView::preset_height (HeightSmall)) { @@ -6374,31 +6254,44 @@ Editor::fit_tracks (TrackViewList & tracks) undo_visual_stack.push_back (current_visual_state()); + /* build a list of all tracks, including children */ + + TrackViewList all; + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + all.push_back (*i); + TimeAxisView::Children c = (*i)->get_child_list (); + for (TimeAxisView::Children::iterator j = c.begin(); j != c.end(); ++j) { + all.push_back (j->get()); + } + } + /* operate on all tracks, hide unselected ones that are in the middle of selected ones */ bool prev_was_selected = false; - bool is_selected = tracks.contains (track_views.front()); + bool is_selected = tracks.contains (all.front()); bool next_is_selected; - for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) { + for (TrackViewList::iterator t = all.begin(); t != all.end(); ++t) { TrackViewList::iterator next; next = t; ++next; - if (next != track_views.end()) { + if (next != all.end()) { next_is_selected = tracks.contains (*next); } else { next_is_selected = false; } - if (is_selected) { - (*t)->set_height (h); - first_y_pos = std::min ((*t)->y_position (), first_y_pos); - } else { - if (prev_was_selected && next_is_selected) { - hide_track_in_display (*t); + if ((*t)->marked_for_display ()) { + if (is_selected) { + (*t)->set_height (h); + first_y_pos = std::min ((*t)->y_position (), first_y_pos); + } else { + if (prev_was_selected && next_is_selected) { + hide_track_in_display (*t); + } } } @@ -6481,3 +6374,33 @@ Editor::end_visual_state_op (uint32_t n) return false; // do not call again } +void +Editor::toggle_region_mute () +{ + if (_ignore_region_action) { + return; + } + + RegionSelection rs = get_regions_from_selection_and_entered (); + + if (rs.empty ()) { + return; + } + + if (rs.size() > 1) { + begin_reversible_command (_("mute regions")); + } else { + begin_reversible_command (_("mute region")); + } + + for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { + + (*i)->region()->playlist()->clear_changes (); + (*i)->region()->set_muted (!(*i)->region()->muted ()); + _session->add_command (new StatefulDiffCommand ((*i)->region()->playlist())); + + } + + commit_reversible_command (); +} +