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.
This commit is contained in:
parent
17546f47b6
commit
84f0dceefb
@ -364,6 +364,7 @@
|
||||
<menuitem action='track-mute-toggle'/>
|
||||
<separator/>
|
||||
<menuitem action='insert-time'/>
|
||||
<menuitem action='cut-time'/>
|
||||
<menuitem action="move-selected-tracks-up"/>
|
||||
<menuitem action="move-selected-tracks-down"/>
|
||||
<menu action='TrackHeightMenu'>
|
||||
|
@ -1261,6 +1261,9 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
||||
void do_insert_time ();
|
||||
void insert_time (framepos_t, framecnt_t, Editing::InsertTimeOption, bool, bool, bool, bool, bool, bool);
|
||||
|
||||
void do_cut_time ();
|
||||
void cut_time (framepos_t pos, framecnt_t distance, Editing::InsertTimeOption opt, bool ignore_music_glue, bool markers_too, bool tempo_too);
|
||||
|
||||
void tab_to_transient (bool forward);
|
||||
|
||||
void set_tempo_from_region ();
|
||||
|
@ -398,6 +398,10 @@ Editor::register_actions ()
|
||||
|
||||
act = reg_sens (editor_actions, "insert-time", _("Insert Time"), (sigc::mem_fun(*this, &Editor::do_insert_time)));
|
||||
ActionManager::track_selection_sensitive_actions.push_back (act);
|
||||
act = ActionManager::register_action (editor_actions, "cut-time", _("Cut Time"), (mem_fun(*this, &Editor::do_cut_time)));
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
ActionManager::track_selection_sensitive_actions.push_back (act);
|
||||
|
||||
|
||||
act = reg_sens (editor_actions, "toggle-track-active", _("Toggle Active"), (sigc::mem_fun(*this, &Editor::toggle_tracks_active)));
|
||||
ActionManager::track_selection_sensitive_actions.push_back (act);
|
||||
|
@ -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 ()
|
||||
|
@ -323,6 +323,7 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
|
||||
void change_initial_tempo (double bpm, double note_type);
|
||||
|
||||
void insert_time (framepos_t, framecnt_t);
|
||||
bool cut_time (framepos_t where, framecnt_t amount); //returns true if anything was moved
|
||||
|
||||
int n_tempos () const;
|
||||
int n_meters () const;
|
||||
|
@ -1900,6 +1900,58 @@ TempoMap::insert_time (framepos_t where, framecnt_t amount)
|
||||
|
||||
PropertyChanged (PropertyChange ());
|
||||
}
|
||||
bool
|
||||
TempoMap::cut_time (framepos_t where, framecnt_t amount)
|
||||
{
|
||||
bool moved = false;
|
||||
|
||||
std::list<MetricSection*> metric_kill_list;
|
||||
|
||||
TempoSection* last_tempo = NULL;
|
||||
MeterSection* last_meter = NULL;
|
||||
{
|
||||
Glib::Threads::RWLock::WriterLock lm (lock);
|
||||
for (Metrics::iterator i = metrics.begin(); i != metrics.end(); ++i) {
|
||||
if ((*i)->frame() >= where && (*i)->frame() < where+amount) {
|
||||
metric_kill_list.push_back(*i);
|
||||
TempoSection *lt = dynamic_cast<TempoSection*> (*i);
|
||||
if (lt)
|
||||
last_tempo = lt;
|
||||
MeterSection *lm = dynamic_cast<MeterSection*> (*i);
|
||||
if (lm)
|
||||
last_meter = lm;
|
||||
}
|
||||
else if ((*i)->frame() >= where) {
|
||||
(*i)->set_frame ((*i)->frame() - amount);
|
||||
moved = true;
|
||||
}
|
||||
}
|
||||
|
||||
//find the last TEMPO and METER metric (if any) and move it to the cut point so future stuff is correct
|
||||
if (last_tempo) {
|
||||
metric_kill_list.remove(last_tempo);
|
||||
last_tempo->set_frame(where);
|
||||
moved = true;
|
||||
}
|
||||
if (last_meter) {
|
||||
metric_kill_list.remove(last_meter);
|
||||
last_meter->set_frame(where);
|
||||
moved = true;
|
||||
}
|
||||
|
||||
//remove all the remaining metrics
|
||||
for (std::list<MetricSection*>::iterator i = metric_kill_list.begin(); i != metric_kill_list.end(); ++i) {
|
||||
metrics.remove(*i);
|
||||
moved = true;
|
||||
}
|
||||
|
||||
if (moved) {
|
||||
recompute_map (true);
|
||||
}
|
||||
}
|
||||
PropertyChanged (PropertyChange ());
|
||||
return moved;
|
||||
}
|
||||
|
||||
/** Add some (fractional) beats to a session frame position, and return the result in frames.
|
||||
* pos can be -ve, if required.
|
||||
|
Loading…
Reference in New Issue
Block a user