diff --git a/gtk2_ardour/ardour.keys.in b/gtk2_ardour/ardour.keys.in
index 4cb4aabf0a..f53032e785 100644
--- a/gtk2_ardour/ardour.keys.in
+++ b/gtk2_ardour/ardour.keys.in
@@ -175,7 +175,7 @@ This mode provides many different operations on both regions and control points,
@edit|Editor/alternate-redo| <@PRIMARY@>y|redo
@select|Editor/select-all-between-cursors| <@PRIMARY@>u|select all regions enclosed by Range
@select|Editor/select-all-within-cursors| u|select all regions touched by Range
-@rop|Region/fork-region| <@TERTIARY@>u|unlink midi from other regions
+@rop|Region/fork-regions-from-unselected| <@TERTIARY@>u|unlink midi from unselected regions
@eep|Region/insert-region-from-source-list| i|insert from region list
@sess|Common/addExistingAudioFiles| <@PRIMARY@>i|import audio files
@gselect|Common/invert-selection| <@PRIMARY@><@TERTIARY@>i|invert selection
diff --git a/gtk2_ardour/ardour.menus.in b/gtk2_ardour/ardour.menus.in
index 7c56127275..11256260ed 100644
--- a/gtk2_ardour/ardour.menus.in
+++ b/gtk2_ardour/ardour.menus.in
@@ -357,7 +357,8 @@
-
+
+
@@ -857,7 +858,8 @@
-
+
+
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index 7b85928603..cf37bf50a7 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -1368,7 +1368,8 @@ private:
void transpose_region ();
void transpose_regions (const RegionSelection& rs);
void insert_patch_change (bool from_context);
- void fork_region ();
+ void fork_selected_regions ();
+ void fork_regions_from_unselected ();
void do_insert_time ();
void insert_time (Temporal::timepos_t const &, Temporal::timecnt_t const &, Editing::InsertTimeOption, bool, bool, bool, bool, bool, bool);
diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc
index ab7200e876..4a0bb6f0cd 100644
--- a/gtk2_ardour/editor_actions.cc
+++ b/gtk2_ardour/editor_actions.cc
@@ -1910,7 +1910,8 @@ Editor::register_region_actions ()
register_region_action (_region_actions, RegionActionTarget (SelectedRegions|EnteredRegions), "remove-overlap", _("Remove Overlap"), sigc::bind(sigc::mem_fun (*this, &Editor::legatize_region), true));
register_region_action (_region_actions, RegionActionTarget (SelectedRegions|EnteredRegions), "insert-patch-change", _("Insert Patch Change..."), sigc::bind (sigc::mem_fun (*this, &Editor::insert_patch_change), false));
register_region_action (_region_actions, RegionActionTarget (SelectedRegions|EnteredRegions), "insert-patch-change-context", _("Insert Patch Change..."), sigc::bind (sigc::mem_fun (*this, &Editor::insert_patch_change), true));
- register_region_action (_region_actions, RegionActionTarget (SelectedRegions|EnteredRegions), "fork-region", _("Unlink from other copies"), sigc::mem_fun (*this, &Editor::fork_region));
+ register_region_action (_region_actions, RegionActionTarget (SelectedRegions|EnteredRegions), "fork-selected-regions", _("Unlink all selected regions"), sigc::mem_fun (*this, &Editor::fork_selected_regions));
+ register_region_action (_region_actions, RegionActionTarget (SelectedRegions|EnteredRegions), "fork-regions-from-unselected", _("Unlink from unselected"), sigc::mem_fun (*this, &Editor::fork_regions_from_unselected));
register_region_action (_region_actions, RegionActionTarget (SelectedRegions|EnteredRegions), "strip-region-silence", _("Strip Silence..."), sigc::mem_fun (*this, &Editor::strip_region_silence));
register_region_action (_region_actions, RegionActionTarget (SelectedRegions), "set-selection-from-region", _("Set Range Selection"), sigc::mem_fun (*this, &Editor::set_selection_from_region));
diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc
index 7f564e3297..4e1ff668f2 100644
--- a/gtk2_ardour/editor_ops.cc
+++ b/gtk2_ardour/editor_ops.cc
@@ -5871,8 +5871,91 @@ Editor::apply_midi_note_edit_op (MidiOperator& op, const RegionSelection& rs)
}
}
+#include "ardour/midi_source.h" // MidiSource::name()
+
void
-Editor::fork_region ()
+Editor::fork_regions_from_unselected ()
+{
+ /* keep linkage between regions in the selection, but unlink from unselected regions */
+ RegionSelection rs = get_regions_from_selection_and_entered ();
+
+ if (rs.empty()) {
+ return;
+ }
+
+ CursorContext::Handle cursor_ctx = CursorContext::create(*this, _cursors->wait);
+ bool in_command = false;
+
+ gdk_flush ();
+
+ /* find the set of all MidiSources associated with the selected regions */
+ std::set > sources_list;
+ for (const auto& r : rs) {
+ const MidiRegionView* const mrv = dynamic_cast(r);
+ if (!mrv)
+ continue; // not a MIDI region
+
+ sources_list.insert(mrv->midi_region()->midi_source());
+ }
+
+ std::set > affected_playlists;
+ for (auto r : rs) {
+ const MidiRegionView* const mrv = dynamic_cast(r);
+ if (mrv && sources_list.find(mrv->midi_region()->midi_source()) != sources_list.end()) {
+ affected_playlists.insert(mrv->region()->playlist());
+ }
+ }
+ for (auto p : affected_playlists) {
+ p->clear_changes ();
+ p->freeze ();
+ }
+
+ /* iterate over sources that need to be duplicated */
+ for (const auto& ms : sources_list) {
+ /* duplicate source */
+ boost::shared_ptr new_source = _session->create_midi_source_for_session (ms->name());
+ for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ) {
+ RegionSelection::iterator tmp = r;
+ ++tmp;
+
+ const MidiRegionView* const mrv = dynamic_cast(*r);
+
+ if (!mrv) {
+ r = tmp;
+ continue;
+ }
+ if (mrv->midi_region()->midi_source() != ms) {
+ r = tmp;
+ continue;
+ }
+
+ try {
+ if (!in_command) {
+ begin_reversible_command (_("Unlink from unselected"));
+ in_command = true;
+ }
+ boost::shared_ptr playlist = mrv->region()->playlist();
+ boost::shared_ptr new_region = mrv->midi_region()->clone (new_source);
+ new_region->set_name (mrv->region()->name() + "-unlinked-region");
+ playlist->replace_region (mrv->region(), new_region, mrv->region()->position());
+ } catch (...) {
+ error << string_compose (_("Could not unlink %1"), mrv->region()->name()) << endmsg;
+ }
+ r = tmp;
+ }
+ }
+ if (in_command) {
+ for (auto p : affected_playlists) {
+ p->thaw ();
+ _session->add_command(new StatefulDiffCommand (p));
+ }
+
+ commit_reversible_command ();
+ }
+}
+
+void
+Editor::fork_selected_regions ()
{
RegionSelection rs = get_regions_from_selection_and_entered ();
diff --git a/gtk2_ardour/editor_selection.cc b/gtk2_ardour/editor_selection.cc
index 4718515405..c126cf98e2 100644
--- a/gtk2_ardour/editor_selection.cc
+++ b/gtk2_ardour/editor_selection.cc
@@ -1539,7 +1539,8 @@ Editor::sensitize_the_right_region_actions (bool because_canvas_crossing)
_region_actions->get_action("legatize-region")->set_sensitive (false);
_region_actions->get_action("remove-overlap")->set_sensitive (false);
_region_actions->get_action("transform-region")->set_sensitive (false);
- _region_actions->get_action("fork-region")->set_sensitive (false);
+ _region_actions->get_action("fork-selected-regions")->set_sensitive (false);
+ _region_actions->get_action("fork-regions-from-unselected")->set_sensitive (false);
_region_actions->get_action("insert-patch-change-context")->set_sensitive (false);
_region_actions->get_action("insert-patch-change")->set_sensitive (false);
_region_actions->get_action("transpose-region")->set_sensitive (false);