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 @wvis|Common/toggle-meterbridge|<@SECONDARY@>b|show meter bridge
@edtrk|Editor/track-record-enable-toggle|<@TERTIARY@>b|toggle track rec-enable @edtrk|Editor/track-record-enable-toggle|<@TERTIARY@>b|toggle track rec-enable
@sess|Main/AddTrackBus|<@PRIMARY@><@TERTIARY@>n|add track(s) or bus(ses) @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 @sess|Main/New|<@PRIMARY@>n|open a new session
@wvis|Window/toggle-midi-connection-manager|<@SECONDARY@><@TERTIARY@>m|toggle global midi patchbay @wvis|Window/toggle-midi-connection-manager|<@SECONDARY@><@TERTIARY@>m|toggle global midi patchbay
@wvis|Common/show-mixer|<@SECONDARY@>m|show mixer window @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); 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); RegionSelection get_regions_from_selection_and_mouse (samplepos_t);
void do_remove_gaps (); 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_tempo_event (samplepos_t where);
void mouse_add_new_meter_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 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 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 Drag;
friend class RegionCutDrag; friend class RegionCutDrag;
friend class RegionDrag; friend class RegionDrag;

View file

@ -8739,6 +8739,14 @@ Editor::add_region_marker ()
return; 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); ArdourDialog d (_("New Cue Marker Name"), true, false);
Gtk::Entry e; Gtk::Entry e;
d.get_vbox()->pack_start (e); d.get_vbox()->pack_start (e);
@ -8755,8 +8763,7 @@ Editor::add_region_marker ()
return; return;
} }
RegionSelection rs = get_regions_from_selection_and_edit_point ();
samplepos_t position = get_preferred_edit_position ();
bool in_command = false; bool in_command = false;
for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) { 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()); boost::shared_ptr<Region> region ((*r)->region());
if (position < region->position() || position >= region->position() + region->length()) { if (position < region->position() || position >= region->position() + region->length()) {
cerr << "nope on that one\n";
continue; continue;
} }
@ -8946,8 +8954,11 @@ Editor::do_remove_gaps ()
hpacker2.pack_start (label2, true, false); hpacker2.pack_start (label2, true, false);
hpacker2.pack_start (e2, false, 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 (hpacker1);
d.get_vbox()->pack_start (hpacker2); d.get_vbox()->pack_start (hpacker2);
d.get_vbox()->pack_start (markers_too);
d.get_vbox()->show_all (); d.get_vbox()->show_all ();
e2.set_activates_default (); e2.set_activates_default ();
@ -8971,8 +8982,8 @@ Editor::do_remove_gaps ()
goto again; goto again;
} }
if (threshold_secs <= 0) { if (threshold_secs < 0) {
ArdourMessageDialog msg (_("The threshold value must be larger than zero")); ArdourMessageDialog msg (_("The threshold value must be larger than or equal to zero"));
msg.run(); msg.run();
goto again; goto again;
} }
@ -8997,14 +9008,39 @@ Editor::do_remove_gaps ()
d.hide (); 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 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; bool in_command = false;
TrackViewList ts = selection->tracks.filter_to_unique_playlists (); 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) { 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. * playlist.
*/ */
set<boost::shared_ptr<Playlist> > pl;
if ((*x)->playlist ()) { if ((*x)->playlist ()) {
if (!first_selected_playlist) {
first_selected_playlist = (*x)->playlist();
}
pl.insert ((*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_changes ();
(*i)->clear_owned_changes (); (*i)->clear_owned_changes ();
if (!in_command) { if (!in_command) {
begin_reversible_command (_("remove gaps")); begin_reversible_command (_("remove gaps"));
in_command = true; 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));
} }
/* 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 (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 (); commit_reversible_command ();
} else {
if (markers_too) {
delete locations_before;
}
} }
} }