+ 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::SimpleLine* _line = reinterpret_cast<ArdourCanvas::SimpleLine*> (item);
+ assert (_line);
+
+ AudioRegionView* _arv = reinterpret_cast<AudioRegionView*> (item->get_data ("regionview"));
+ _arv->remove_transient(_line->property_x1());
+}
+
+void
+Editor::snap_regions_to_grid ()
+{
+ 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) {
+ framepos_t start_frame = (*r)->region()->first_frame ();
+ snap_to (start_frame);
+ (*r)->region()->set_position (start_frame, this);
+ }
+
+ _session->commit_reversible_command ();
+}
+
+void
+Editor::close_region_gaps ()
+{
+ 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 (3);
+ 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, 15);
+ spin_pullback.set_increments (1, 1);
+ spin_pullback.set_value (5);
+ 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<Region> last_region;
+
+ rs.sort_by_position_and_track();
+
+ for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) {
+
+ 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++;
+ }
+
+ _session->commit_reversible_command ();