diff options
author | Colin Fletcher <colin.m.fletcher@googlemail.com> | 2013-10-16 22:25:35 +0100 |
---|---|---|
committer | Ben Loftis <ben@harrisonconsoles.com> | 2015-04-21 10:22:27 -0500 |
commit | 84f0dceefb2e4079e1f015a17e538f0cd795ba2e (patch) | |
tree | cfddf5f6e8c45b1bde5dd8a1884a893f7d71bac1 /gtk2_ardour/editor_ops.cc | |
parent | 17546f47b6927c21fe50ce5e784f2f4952d69473 (diff) |
Port 'Cut time' code from Mixbus
Copy the 'Cut time' code from Mixbus, making a few obvious fixes to work in
A3 (e.g. nframes_t => framepos_t / framecnt_t).
Seems to work to move & remove markers, tempo & meter markers, and regions on
selected tracks.
Still TODO:
- use existing A3 'Insert time' dialogue
- make it respect 'No selection = all tracks'
- rename the command to something like 'Remove time' or 'Delete time': 'Cut'
sounds to me as if the removed range should end up on the clipboard ready
to be pasted somewhere, which of course it doesn't.
Diffstat (limited to 'gtk2_ardour/editor_ops.cc')
-rw-r--r-- | gtk2_ardour/editor_ops.cc | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index 116bc4571d..185ab5f1a8 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -7018,6 +7018,175 @@ Editor::insert_time ( commit_reversible_command (); } } +void +Editor::do_cut_time () +{ + if (selection->tracks.empty()) { + return; + } + + framepos_t pos = get_preferred_edit_position (); + ArdourDialog d (*this, _("Cut Time")); + VButtonBox button_box; + VBox option_box; + + CheckButton glue_button (_("Move Glued Regions")); + CheckButton marker_button (_("Move Markers")); + CheckButton tempo_button (_("Move Tempo & Meters")); + AudioClock clock ("insertTimeClock", true, X_("InsertTimeClock"), true, true, true); + HBox clock_box; + + clock.set (0); + clock.set_session (_session); + clock.set_bbt_reference (pos); + + clock_box.pack_start (clock, false, true); + + option_box.set_spacing (6); + option_box.pack_start (button_box, false, false); + option_box.pack_start (glue_button, false, false); + option_box.pack_start (marker_button, false, false); + option_box.pack_start (tempo_button, false, false); + + d.get_vbox()->set_border_width (12); + d.get_vbox()->pack_start (clock_box, false, false); + d.get_vbox()->pack_start (option_box, false, false); + + option_box.show (); + button_box.show (); + glue_button.show (); + clock.show_all(); + clock_box.show (); + marker_button.show (); + tempo_button.show (); + + d.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); + d.add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK); + d.show (); + + int response = d.run (); + + if (response != RESPONSE_OK) { + return; + } + + framecnt_t distance = clock.current_duration (pos); + + if (distance == 0) { + return; + } + + cut_time (pos, distance, SplitIntersected, glue_button.get_active(), marker_button.get_active(), tempo_button.get_active()); +} + +void +Editor::cut_time (framepos_t pos, framecnt_t frames, InsertTimeOption opt, + bool ignore_music_glue, bool markers_too, bool tempo_too) +{ + bool commit = false; + + if (Config->get_edit_mode() == Lock) { + error << (_("Cannot insert or delete time when in Lock edit.")) << endmsg; + return; + } + + begin_reversible_command (_("cut time")); + + for (TrackSelection::iterator x = selection->tracks.begin(); x != selection->tracks.end(); ++x) { + /* regions */ + boost::shared_ptr<Playlist> pl = (*x)->playlist(); + + if (pl) { + + XMLNode &before = pl->get_state(); + + std::list<AudioRange> rl; + AudioRange ar(pos, pos+frames, 0); + rl.push_back(ar); + pl->cut (rl); + pl->shift (pos, -frames, true, ignore_music_glue); + + XMLNode &after = pl->get_state(); + + _session->add_command (new MementoCommand<Playlist> (*pl, &before, &after)); + commit = true; + } + + /* automation */ + RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (*x); + if (rtav) { + rtav->route ()->shift (pos, -frames); + commit = true; + } + } + + std::list<Location*> loc_kill_list; + + /* markers */ + if (markers_too) { + bool moved = false; + XMLNode& before (_session->locations()->get_state()); + Locations::LocationList copy (_session->locations()->list()); + + for (Locations::LocationList::iterator i = copy.begin(); i != copy.end(); ++i) { + + if (!(*i)->is_mark()) { //range; have to handle both start and end + if ((*i)->end() >= pos + && (*i)->end() < pos+frames + && (*i)->start() >= pos + && (*i)->end() < pos+frames) { //range is completely enclosed; kill it + moved = true; + loc_kill_list.push_back(*i); + } else { //ony start or end is included, try to do the right thing + if ((*i)->end() >= pos && (*i)->end() < pos+frames) { + (*i)->set_end (pos); //bring the end to the cut + moved = true; + } else if ((*i)->end() >= pos) { + (*i)->set_end ((*i)->end()-frames); //slip the end marker back + moved = true; + } + if ((*i)->start() >= pos && (*i)->start() < pos+frames) { + (*i)->set_start (pos); //bring the start marker to the beginning of the cut + moved = true; + } else if ((*i)->start() >= pos) { + (*i)->set_start ((*i)->start() -frames); //slip the end marker back + moved = true; + } + } + } else if ((*i)->start() >= pos && (*i)->start() < pos+frames ) { + loc_kill_list.push_back(*i); + moved = true; + } else if ((*i)->start() >= pos) { + (*i)->set_start ((*i)->start() -frames); + moved = true; + } + } + + for (list<Location*>::iterator i = loc_kill_list.begin(); i != loc_kill_list.end(); ++i) { + _session->locations()->remove( *i ); + } + + if (moved) { + XMLNode& after (_session->locations()->get_state()); + _session->add_command (new MementoCommand<Locations>(*_session->locations(), &before, &after)); + commit = true; + } + } + + if (tempo_too) { + XMLNode& before (_session->tempo_map().get_state()); + + if (_session->tempo_map().cut_time (pos, frames) ) { + XMLNode& after (_session->tempo_map().get_state()); + _session->add_command (new MementoCommand<TempoMap>(_session->tempo_map(), &before, &after)); + commit = true; + } + } + + if (commit) { + commit_reversible_command (); + } +} void Editor::fit_selection () |