From 128ae396b04cc21ea8adb6f9ef3f5fe20ecf4974 Mon Sep 17 00:00:00 2001
From: Nathan Stewart <therealnathanstewart@gmail.com>
Date: Mon, 15 Aug 2016 22:29:27 -0400
Subject: [PATCH] Single Button, Multi-press Auto Punch In/Out with punch range
 set from the playhead

---
 gtk2_ardour/editor.h          |  1 +
 gtk2_ardour/editor_actions.cc |  1 +
 gtk2_ardour/editor_ops.cc     | 53 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 55 insertions(+)

diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index 7d754ed..75ba686 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -1451,6 +1451,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
 	void set_loop_from_selection (bool play);
 	void set_punch_from_selection ();
 	void set_punch_from_region ();
+	void set_auto_punch_range();
 
 	void set_session_start_from_playhead ();
 	void set_session_end_from_playhead ();
diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc
index 44c66e3..660a051 100644
--- a/gtk2_ardour/editor_actions.cc
+++ b/gtk2_ardour/editor_actions.cc
@@ -330,6 +330,7 @@ Editor::register_actions ()
 
 	reg_sens (editor_actions, "set-playhead", _("Playhead to Mouse"), sigc::mem_fun(*this, &Editor::set_playhead_cursor));
 	reg_sens (editor_actions, "set-edit-point", _("Active Marker to Mouse"), sigc::mem_fun(*this, &Editor::set_edit_point));
+	reg_sens (editor_actions, "set-auto-punch-range", _("Set Auto Punch In/Out from Playhead"), sigc::mem_fun(*this, &Editor::set_auto_punch_range));
 
 	reg_sens (editor_actions, "duplicate-range", _("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false));
 
diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc
index e5d7623..16cce62 100644
--- a/gtk2_ardour/editor_ops.cc
+++ b/gtk2_ardour/editor_ops.cc
@@ -6345,6 +6345,59 @@ Editor::set_punch_from_selection ()
 }
 
 void
+Editor::set_auto_punch_range ()
+{
+	// auto punch in/out button from a single button
+	// If Punch In is unset, set punch range from playhead to end, enable punch in
+	// If Punch In is set, the next punch sets Punch Out, unless the playhead has been
+	//   rewound beyond the Punch In marker, in which case that marker will be moved back
+	//   to the current playhead position.
+	// If punch out is set, it clears the punch range and Punch In/Out buttons
+
+	if (_session == 0) {
+		return;
+	}
+
+	Location* tpl = transport_punch_location();
+	framepos_t now = playhead_cursor->current_frame();
+	framepos_t begin = now;
+	framepos_t end = _session->current_end_frame();
+
+	if (!_session->config.get_punch_in()) {
+		// First Press - set punch in and create range from here to eternity
+		set_punch_range (begin, end, _("Auto Punch In"));
+		_session->config.set_punch_in(true);
+	} else if (tpl && !_session->config.get_punch_out()) {
+		// Second press - update end range marker and set punch_out
+		if (now < tpl->start()) {
+			// playhead has been rewound - move start back  and pretend nothing happened
+			begin = now;
+			set_punch_range (begin, end, _("Auto Punch In/Out"));
+		} else {
+			// normal case for 2nd press - set the punch out
+			end = playhead_cursor->current_frame ();
+			set_punch_range (tpl->start(), now, _("Auto Punch In/Out"));
+			_session->config.set_punch_out(true);
+		}
+	} else 	{
+		if (_session->config.get_punch_out()) {
+			_session->config.set_punch_out(false);
+		}
+
+		if (_session->config.get_punch_in()) {
+			_session->config.set_punch_in(false);
+		}
+
+		if (tpl)
+		{
+			// third press - unset punch in/out and remove range
+			_session->locations()->remove(tpl);
+		}
+	}
+
+}
+
+void
 Editor::set_session_extents_from_selection ()
 {
 	if (_session == 0) {
-- 
2.7.4

