implement option to move markers during a "remove gaps" operation

This commit is contained in:
Paul Davis 2021-05-28 17:43:25 -06:00
parent 3d15b61e37
commit b17629bddf
3 changed files with 81 additions and 24 deletions

View File

@ -231,6 +231,7 @@ This mode provides many different operations on both regions and control points,
@wvis|Common/toggle-meterbridge|<@SECONDARY@>b|show meter bridge
@edtrk|Editor/track-record-enable-toggle|<@TERTIARY@>b|toggle track rec-enable
@sess|Main/AddTrackBus|<@PRIMARY@><@TERTIARY@>n|add track(s) or bus(ses)
@rop|Region/add-region-cue-marker|m|add a region/cue marker
@sess|Main/New|<@PRIMARY@>n|open a new session
@wvis|Window/toggle-midi-connection-manager|<@SECONDARY@><@TERTIARY@>m|toggle global midi patchbay
@wvis|Common/show-mixer|<@SECONDARY@>m|show mixer window

View File

@ -580,7 +580,7 @@ public:
void split_region_at_points (boost::shared_ptr<ARDOUR::Region>, ARDOUR::AnalysisFeatureList&, bool can_ferret, bool select_new = false);
RegionSelection get_regions_from_selection_and_mouse (samplepos_t);
void do_remove_gaps ();
void remove_gaps (samplecnt_t threshold, samplecnt_t leave);
void remove_gaps (samplecnt_t threshold, samplecnt_t leave, bool markers_too);
void mouse_add_new_tempo_event (samplepos_t where);
void mouse_add_new_meter_event (samplepos_t where);
@ -2370,6 +2370,8 @@ private:
void toggle_reg_sens (Glib::RefPtr<Gtk::ActionGroup> group, char const* name, char const* label, sigc::slot<void> slot);
void radio_reg_sens (Glib::RefPtr<Gtk::ActionGroup> action_group, Gtk::RadioAction::Group& radio_group, char const* name, char const* label, sigc::slot<void> slot);
void remove_gap_marker_callback (samplepos_t at, samplecnt_t distance);
friend class Drag;
friend class RegionCutDrag;
friend class RegionDrag;

View File

@ -8739,6 +8739,14 @@ Editor::add_region_marker ()
return;
}
/* get these before we display the dialog, since it will interfere if
the edit point is "mouse"
*/
RegionSelection rs = get_regions_from_selection_and_edit_point ();
samplepos_t position = get_preferred_edit_position ();
cerr << "adding cue marker @ " << position << " in " << rs.size() << endl;
ArdourDialog d (_("New Cue Marker Name"), true, false);
Gtk::Entry e;
d.get_vbox()->pack_start (e);
@ -8755,8 +8763,7 @@ Editor::add_region_marker ()
return;
}
RegionSelection rs = get_regions_from_selection_and_edit_point ();
samplepos_t position = get_preferred_edit_position ();
bool in_command = false;
for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) {
@ -8764,6 +8771,7 @@ Editor::add_region_marker ()
boost::shared_ptr<Region> region ((*r)->region());
if (position < region->position() || position >= region->position() + region->length()) {
cerr << "nope on that one\n";
continue;
}
@ -8946,8 +8954,11 @@ Editor::do_remove_gaps ()
hpacker2.pack_start (label2, true, false);
hpacker2.pack_start (e2, false, false);
Gtk::CheckButton markers_too (_("Shift global markers too"));
d.get_vbox()->pack_start (hpacker1);
d.get_vbox()->pack_start (hpacker2);
d.get_vbox()->pack_start (markers_too);
d.get_vbox()->show_all ();
e2.set_activates_default ();
@ -8971,8 +8982,8 @@ Editor::do_remove_gaps ()
goto again;
}
if (threshold_secs <= 0) {
ArdourMessageDialog msg (_("The threshold value must be larger than zero"));
if (threshold_secs < 0) {
ArdourMessageDialog msg (_("The threshold value must be larger than or equal to zero"));
msg.run();
goto again;
}
@ -8997,14 +9008,39 @@ Editor::do_remove_gaps ()
d.hide ();
remove_gaps (threshold_samples, leave_samples);
remove_gaps (threshold_samples, leave_samples, markers_too.get_active());
}
/* one day, we can use an empty lambda for this */
static
void gap_marker_callback_relax (samplepos_t, samplecnt_t)
{
}
void
Editor::remove_gaps (samplecnt_t gap_threshold, samplecnt_t leave_gap)
Editor::remove_gap_marker_callback (samplepos_t at, samplecnt_t distance)
{
_session->locations()->ripple (at, distance, false, false);
}
void
Editor::remove_gaps (samplecnt_t gap_threshold, samplecnt_t leave_gap, bool markers_too)
{
bool in_command = false;
TrackViewList ts = selection->tracks.filter_to_unique_playlists ();
XMLNode* locations_before (0);
if (markers_too) {
locations_before = &_session->locations()->get_state();
}
set<boost::shared_ptr<Playlist> > pl;
/* it will not be possible to infer this from the set<>, so keep track
* of it explicitly
*/
boost::shared_ptr<Playlist> first_selected_playlist;
for (TrackSelection::iterator x = ts.begin(); x != ts.end(); ++x) {
@ -9013,33 +9049,51 @@ Editor::remove_gaps (samplecnt_t gap_threshold, samplecnt_t leave_gap)
* playlist.
*/
set<boost::shared_ptr<Playlist> > pl;
if ((*x)->playlist ()) {
if (!first_selected_playlist) {
first_selected_playlist = (*x)->playlist();
}
pl.insert ((*x)->playlist ());
}
}
for (set<boost::shared_ptr<Playlist> >::iterator i = pl.begin(); i != pl.end(); ++i) {
for (set<boost::shared_ptr<Playlist> >::iterator i = pl.begin(); i != pl.end(); ++i) {
(*i)->clear_changes ();
(*i)->clear_owned_changes ();
(*i)->clear_changes ();
(*i)->clear_owned_changes ();
if (!in_command) {
begin_reversible_command (_("remove gaps"));
in_command = true;
}
(*i)->remove_gaps (gap_threshold, leave_gap);
vector<Command*> cmds;
(*i)->rdiff (cmds);
_session->add_commands (cmds);
_session->add_command (new StatefulDiffCommand (*i));
if (!in_command) {
begin_reversible_command (_("remove gaps"));
in_command = true;
}
/* only move markers when closing gaps on the first
* selected track/playlist
*/
if (markers_too && (*i == first_selected_playlist)) {
boost::function<void (samplepos_t, samplecnt_t)> callback (boost::bind (&Editor::remove_gap_marker_callback, this, _1, _2));
(*i)->remove_gaps (gap_threshold, leave_gap, callback);
} else {
boost::function<void (samplepos_t, samplecnt_t)> callback (boost::bind (gap_marker_callback_relax, _1, _2));
(*i)->remove_gaps (gap_threshold, leave_gap, callback);
}
vector<Command*> cmds;
(*i)->rdiff (cmds);
_session->add_commands (cmds);
_session->add_command (new StatefulDiffCommand (*i));
}
if (in_command) {
if (markers_too) {
XMLNode* locations_after = &_session->locations()->get_state();
_session->add_command (new MementoCommand<Locations> (*_session->locations(), locations_before, locations_after));
}
commit_reversible_command ();
} else {
if (markers_too) {
delete locations_before;
}
}
}