From 68990d2dbda76bf6f0da4c7660e991b2e512bfef Mon Sep 17 00:00:00 2001 From: Ben Loftis Date: Thu, 23 Dec 2021 22:14:48 -0600 Subject: [PATCH] trigger_ui: add a set_all_X context menu to Cue buttons --- gtk2_ardour/cuebox_ui.cc | 137 +++++++++++++++++++++++++++++++++++- gtk2_ardour/cuebox_ui.h | 18 ++++- gtk2_ardour/trigger_page.cc | 1 + 3 files changed, 152 insertions(+), 4 deletions(-) diff --git a/gtk2_ardour/cuebox_ui.cc b/gtk2_ardour/cuebox_ui.cc index 7d581cc358..0b108539b1 100644 --- a/gtk2_ardour/cuebox_ui.cc +++ b/gtk2_ardour/cuebox_ui.cc @@ -20,6 +20,7 @@ #include "pbd/convert.h" #include "ardour/region.h" +#include "ardour/session.h" #include "ardour/triggerbox.h" #include "canvas/polygon.h" @@ -27,6 +28,8 @@ #include "gtkmm2ext/actions.h" #include "gtkmm2ext/colors.h" +#include +#include #include "gtkmm2ext/utils.h" #include "ardour_ui.h" @@ -36,6 +39,7 @@ #include "region_view.h" #include "selection.h" #include "timers.h" +#include "trigger_ui.h" #include "ui_config.h" #include "utils.h" @@ -247,6 +251,7 @@ Glib::RefPtr CueBoxUI::trigger_actions; CueBoxUI::CueBoxUI (ArdourCanvas::Item* parent) : ArdourCanvas::Rectangle (parent) + , _context_menu (0) { set_layout_sensitive (true); // why??? @@ -260,6 +265,128 @@ CueBoxUI::~CueBoxUI () { } +void +CueBoxUI::context_menu (uint64_t idx) +{ + using namespace Gtk; + using namespace Gtk::Menu_Helpers; + using namespace Temporal; + + delete _context_menu; + + _context_menu = new Menu; + MenuList& items = _context_menu->items (); + _context_menu->set_name ("ArdourContextMenu"); + + Menu* follow_menu = manage (new Menu); + MenuList& fitems = follow_menu->items (); + + fitems.push_back (MenuElem (TriggerUI::follow_action_to_string(Trigger::None), sigc::bind (sigc::mem_fun (*this, &CueBoxUI::set_all_follow_action), Trigger::None, idx))); + fitems.push_back (MenuElem (TriggerUI::follow_action_to_string(Trigger::Stop), sigc::bind (sigc::mem_fun (*this, &CueBoxUI::set_all_follow_action), Trigger::Stop, idx))); + fitems.push_back (MenuElem (TriggerUI::follow_action_to_string(Trigger::Again), sigc::bind (sigc::mem_fun (*this, &CueBoxUI::set_all_follow_action), Trigger::Again, idx))); + fitems.push_back (MenuElem (TriggerUI::follow_action_to_string(Trigger::PrevTrigger), sigc::bind (sigc::mem_fun (*this, &CueBoxUI::set_all_follow_action), Trigger::PrevTrigger, idx))); + fitems.push_back (MenuElem (TriggerUI::follow_action_to_string(Trigger::NextTrigger), sigc::bind (sigc::mem_fun (*this, &CueBoxUI::set_all_follow_action), Trigger::NextTrigger, idx))); + fitems.push_back (MenuElem (TriggerUI::follow_action_to_string(Trigger::AnyTrigger), sigc::bind (sigc::mem_fun (*this, &CueBoxUI::set_all_follow_action), Trigger::AnyTrigger, idx))); + fitems.push_back (MenuElem (TriggerUI::follow_action_to_string(Trigger::OtherTrigger), sigc::bind (sigc::mem_fun (*this, &CueBoxUI::set_all_follow_action), Trigger::OtherTrigger, idx))); + + Menu* launch_menu = manage (new Menu); + MenuList& litems = launch_menu->items (); + + litems.push_back (MenuElem (TriggerUI::launch_style_to_string(Trigger::OneShot), sigc::bind (sigc::mem_fun (*this, &CueBoxUI::set_all_launch_style), Trigger::OneShot, idx))); + litems.push_back (MenuElem (TriggerUI::launch_style_to_string(Trigger::Gate), sigc::bind (sigc::mem_fun (*this, &CueBoxUI::set_all_launch_style), Trigger::Gate, idx))); + litems.push_back (MenuElem (TriggerUI::launch_style_to_string(Trigger::Toggle), sigc::bind (sigc::mem_fun (*this, &CueBoxUI::set_all_launch_style), Trigger::Toggle, idx))); + litems.push_back (MenuElem (TriggerUI::launch_style_to_string(Trigger::Repeat), sigc::bind (sigc::mem_fun (*this, &CueBoxUI::set_all_launch_style), Trigger::Repeat, idx))); + + Menu* quant_menu = manage (new Menu); + MenuList& qitems = quant_menu->items (); + + BBT_Offset b; + + b = BBT_Offset (1, 0, 0); + qitems.push_back (MenuElem (_("1 Bar"), sigc::bind (sigc::mem_fun (*this, &CueBoxUI::set_all_quantization), b, idx))); + b = BBT_Offset (0, 4, 0); + qitems.push_back (MenuElem (_("Whole"), sigc::bind (sigc::mem_fun (*this, &CueBoxUI::set_all_quantization), b, idx))); + b = BBT_Offset (0, 2, 0); + qitems.push_back (MenuElem (_("1/2"), sigc::bind (sigc::mem_fun (*this, &CueBoxUI::set_all_quantization), b, idx))); + b = BBT_Offset (0, 1, 0); + qitems.push_back (MenuElem (_("1/4"), sigc::bind (sigc::mem_fun (*this, &CueBoxUI::set_all_quantization), b, idx))); + b = BBT_Offset (0, 0, ticks_per_beat / 2); + qitems.push_back (MenuElem (_("1/8"), sigc::bind (sigc::mem_fun (*this, &CueBoxUI::set_all_quantization), b, idx))); + b = BBT_Offset (0, 0, ticks_per_beat / 4); + qitems.push_back (MenuElem (_("1/16"), sigc::bind (sigc::mem_fun (*this, &CueBoxUI::set_all_quantization), b, idx))); + b = BBT_Offset (0, 0, ticks_per_beat / 8); + qitems.push_back (MenuElem (_("1/32"), sigc::bind (sigc::mem_fun (*this, &CueBoxUI::set_all_quantization), b, idx))); + b = BBT_Offset (0, 0, ticks_per_beat / 16); + qitems.push_back (MenuElem (_("1/64"), sigc::bind (sigc::mem_fun (*this, &CueBoxUI::set_all_quantization), b, idx))); + + Menu* load_menu = manage (new Menu); + MenuList& loitems (load_menu->items ()); + + items.push_back (MenuElem (_("Set All Follow Actions..."), *follow_menu)); + items.push_back (MenuElem (_("Set All Launch Styles..."), *launch_menu)); + items.push_back (MenuElem (_("Set All Quantizations..."), *quant_menu)); + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Clear All..."), sigc::bind (sigc::mem_fun (*this, &CueBoxUI::clear_all_triggers), idx))); + + _context_menu->popup (1, gtk_get_current_event_time ()); +} + +void +CueBoxUI::get_slots (TriggerList &triggerlist, uint64_t idx) +{ + boost::shared_ptr rl = _session->get_routes(); + for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) { + boost::shared_ptr route = *r; + boost::shared_ptr box = route->triggerbox(); +#warning @Ben disambiguate processor *active* vs *visibility* + if (box /*&& box.active*/) { + TriggerPtr trigger = box->trigger(idx); + triggerlist.push_back(trigger); + } + } +} + +void +CueBoxUI::clear_all_triggers (uint64_t idx) +{ + TriggerList tl; + get_slots(tl, idx); + for (TriggerList::iterator t = tl.begin(); t != tl.end(); ++t) { + (*t)->set_region(boost::shared_ptr()); + } +} + +void +CueBoxUI::set_all_follow_action (Trigger::FollowAction fa, uint64_t idx) +{ + TriggerList tl; + get_slots(tl, idx); + for (TriggerList::iterator t = tl.begin(); t != tl.end(); ++t) { + (*t)->set_follow_action(fa, 0); + (*t)->set_follow_action_probability(0); + } +} + +void +CueBoxUI::set_all_launch_style (Trigger::LaunchStyle ls, uint64_t idx) +{ + TriggerList tl; + get_slots(tl, idx); + for (TriggerList::iterator t = tl.begin(); t != tl.end(); ++t) { + (*t)->set_launch_style(ls); + } +} + +void +CueBoxUI::set_all_quantization (Temporal::BBT_Offset const& q, uint64_t idx) +{ + TriggerList tl; + get_slots(tl, idx); + for (TriggerList::iterator t = tl.begin(); t != tl.end(); ++t) { + (*t)->set_quantization(q); + } +} + void CueBoxUI::setup_actions_and_bindings () { @@ -344,12 +471,18 @@ CueBoxUI::event (GdkEvent* ev, uint64_t n) { switch (ev->type) { case GDK_BUTTON_PRESS: - trigger_scene (n); + if (ev->button.button==1) { + trigger_scene (n); + } break; case GDK_2BUTTON_PRESS: break; case GDK_BUTTON_RELEASE: - break; + switch (ev->button.button) { + case 3: + context_menu (n); + return true; + } default: break; } diff --git a/gtk2_ardour/cuebox_ui.h b/gtk2_ardour/cuebox_ui.h index b0bc16b9df..c019e7e5fe 100644 --- a/gtk2_ardour/cuebox_ui.h +++ b/gtk2_ardour/cuebox_ui.h @@ -31,6 +31,8 @@ #include "fitted_canvas_widget.h" +typedef std::list TriggerList; + namespace ArdourCanvas { class Text; @@ -64,7 +66,7 @@ private: double _poly_margin; }; -class CueBoxUI : public ArdourCanvas::Rectangle +class CueBoxUI : public ArdourCanvas::Rectangle, public ARDOUR::SessionHandlePtr { public: CueBoxUI (ArdourCanvas::Item* parent); @@ -82,6 +84,16 @@ private: bool text_event (GdkEvent*, uint64_t); void build (); + void context_menu (uint64_t idx); + void get_slots (TriggerList &triggerlist, uint64_t idx); + + void clear_all_triggers(uint64_t idx); + void set_all_follow_action (ARDOUR::Trigger::FollowAction, uint64_t idx); + void set_all_launch_style (ARDOUR::Trigger::LaunchStyle, uint64_t idx); + void set_all_quantization (Temporal::BBT_Offset const&, uint64_t idx); + + Gtk::Menu* _context_menu; + static Gtkmm2ext::Bindings* bindings; static void load_bindings (); @@ -92,11 +104,13 @@ private: Slots _slots; }; -class CueBoxWidget : public FittedCanvasWidget +class CueBoxWidget : public FittedCanvasWidget, public ARDOUR::SessionHandlePtr { public: CueBoxWidget (float w, float h); + void set_session (ARDOUR::Session* s) {ui->set_session(s); SessionHandlePtr::set_session(s);} + void on_map (); void on_unmap (); diff --git a/gtk2_ardour/trigger_page.cc b/gtk2_ardour/trigger_page.cc index b279e65010..0e4786beaf 100644 --- a/gtk2_ardour/trigger_page.cc +++ b/gtk2_ardour/trigger_page.cc @@ -230,6 +230,7 @@ TriggerPage::set_session (Session* s) { SessionHandlePtr::set_session (s); + _cue_box.set_session (s); _trigger_clip_picker.set_session (s); _master.set_session (s);