triggerbox UI: lots of work on first pass control of follow action, launch style, quantization via context menu

This commit is contained in:
Paul Davis 2021-08-05 15:04:02 -06:00
parent d0e9b5d66d
commit def9392ac6
3 changed files with 204 additions and 5 deletions

View file

@ -4169,6 +4169,7 @@ Editor::get_grid_type_as_beats (bool& success, timepos_t const & position)
} }
break; break;
default: default:
#warning NUTEMPO need to implement all other subdivs
success = false; success = false;
break; break;
} }

View file

@ -17,6 +17,8 @@
*/ */
#include <gtkmm/filechooserdialog.h> #include <gtkmm/filechooserdialog.h>
#include <gtkmm/menu.h>
#include <gtkmm/menuitem.h>
#include <gtkmm/stock.h> #include <gtkmm/stock.h>
#include "pbd/i18n.h" #include "pbd/i18n.h"
@ -31,8 +33,11 @@
#include "gtkmm2ext/utils.h" #include "gtkmm2ext/utils.h"
#include "ardour_ui.h"
#include "triggerbox_ui.h" #include "triggerbox_ui.h"
#include "public_editor.h"
#include "ui_config.h" #include "ui_config.h"
#include "utils.h"
using namespace ARDOUR; using namespace ARDOUR;
using namespace ArdourCanvas; using namespace ArdourCanvas;
@ -126,6 +131,7 @@ TriggerBoxUI::build ()
te->play_button->Event.connect (sigc::bind (sigc::mem_fun (*this, &TriggerBoxUI::bang), n)); te->play_button->Event.connect (sigc::bind (sigc::mem_fun (*this, &TriggerBoxUI::bang), n));
te->name_text->Event.connect (sigc::bind (sigc::mem_fun (*this, &TriggerBoxUI::text_event), n)); te->name_text->Event.connect (sigc::bind (sigc::mem_fun (*this, &TriggerBoxUI::text_event), n));
te->Event.connect (sigc::bind (sigc::mem_fun (*this, &TriggerBoxUI::event), n));
++n; ++n;
} }
@ -149,14 +155,49 @@ TriggerBoxUI::text_event (GdkEvent *ev, size_t n)
return false; return false;
} }
bool
TriggerBoxUI::event (GdkEvent* ev, size_t n)
{
switch (ev->type) {
case GDK_BUTTON_RELEASE:
switch (ev->button.button) {
case 3:
context_menu (n);
return true;
default:
break;
}
break;
default:
break;
}
return false;
}
bool bool
TriggerBoxUI::bang (GdkEvent *ev, size_t n) TriggerBoxUI::bang (GdkEvent *ev, size_t n)
{ {
switch (ev->type) { switch (ev->type) {
case GDK_BUTTON_PRESS: case GDK_BUTTON_PRESS:
if (ev->button.button == 1) { switch (ev->button.button) {
_triggerbox.queue_trigger (&_slots[n]->trigger()); case 1:
_triggerbox.bang_trigger (&_slots[n]->trigger());
return true; return true;
default:
break;
}
break;
case GDK_BUTTON_RELEASE:
switch (ev->button.button) {
case 1:
if (_triggerbox.trigger (n)->launch_style() == Trigger::Gate) {
_triggerbox.unbang_trigger (&_slots[n]->trigger());
}
break;
default:
break;
} }
break; break;
default: default:
@ -165,6 +206,137 @@ TriggerBoxUI::bang (GdkEvent *ev, size_t n)
return false; return false;
} }
void
TriggerBoxUI::context_menu (size_t n)
{
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 (CheckMenuElem (_("Stop"), sigc::bind (sigc::mem_fun (*this, &TriggerBoxUI::set_follow_action), n, Trigger::Stop)));
if (_triggerbox.trigger (n)->follow_action() == Trigger::Stop) {
dynamic_cast<Gtk::CheckMenuItem*> (&fitems.back ())->set_active (true);
}
fitems.push_back (CheckMenuElem (_("Queued"), sigc::bind (sigc::mem_fun (*this, &TriggerBoxUI::set_follow_action), n, Trigger::QueuedTrigger)));
if (_triggerbox.trigger (n)->follow_action() == Trigger::QueuedTrigger) {
dynamic_cast<Gtk::CheckMenuItem*> (&fitems.back ())->set_active (true);
}
fitems.push_back (CheckMenuElem (_("Next"), sigc::bind (sigc::mem_fun (*this, &TriggerBoxUI::set_follow_action), n, Trigger::NextTrigger)));
if (_triggerbox.trigger (n)->follow_action() == Trigger::NextTrigger) {
dynamic_cast<Gtk::CheckMenuItem*> (&fitems.back ())->set_active (true);
}
fitems.push_back (CheckMenuElem (_("Previous"), sigc::bind (sigc::mem_fun (*this, &TriggerBoxUI::set_follow_action), n, Trigger::PrevTrigger)));
if (_triggerbox.trigger (n)->follow_action() == Trigger::PrevTrigger) {
dynamic_cast<Gtk::CheckMenuItem*> (&fitems.back ())->set_active (true);
}
fitems.push_back (CheckMenuElem (_("First"), sigc::bind (sigc::mem_fun (*this, &TriggerBoxUI::set_follow_action), n, Trigger::FirstTrigger)));
if (_triggerbox.trigger (n)->follow_action() == Trigger::FirstTrigger) {
dynamic_cast<Gtk::CheckMenuItem*> (&fitems.back ())->set_active (true);
}
fitems.push_back (CheckMenuElem (_("Last"), sigc::bind (sigc::mem_fun (*this, &TriggerBoxUI::set_follow_action), n, Trigger::LastTrigger)));
if (_triggerbox.trigger (n)->follow_action() == Trigger::LastTrigger) {
dynamic_cast<Gtk::CheckMenuItem*> (&fitems.back ())->set_active (true);
}
fitems.push_back (CheckMenuElem (_("Any"), sigc::bind (sigc::mem_fun (*this, &TriggerBoxUI::set_follow_action), n, Trigger::AnyTrigger)));
if (_triggerbox.trigger (n)->follow_action() == Trigger::AnyTrigger) {
dynamic_cast<Gtk::CheckMenuItem*> (&fitems.back ())->set_active (true);
}
fitems.push_back (CheckMenuElem (_("Other"), sigc::bind (sigc::mem_fun (*this, &TriggerBoxUI::set_follow_action), n, Trigger::OtherTrigger)));
if (_triggerbox.trigger (n)->follow_action() == Trigger::OtherTrigger) {
dynamic_cast<Gtk::CheckMenuItem*> (&fitems.back ())->set_active (true);
}
Menu* launch_menu = manage (new Menu);
MenuList& litems = launch_menu->items();
litems.push_back (CheckMenuElem (_("Loop"), sigc::bind (sigc::mem_fun (*this, &TriggerBoxUI::set_launch_style), n, Trigger::Loop)));
if (_triggerbox.trigger (n)->launch_style() == Trigger::Loop) {
dynamic_cast<Gtk::CheckMenuItem*> (&litems.back ())->set_active (true);
}
litems.push_back (CheckMenuElem (_("Gate"), sigc::bind (sigc::mem_fun (*this, &TriggerBoxUI::set_launch_style), n, Trigger::Gate)));
if (_triggerbox.trigger (n)->launch_style() == Trigger::Gate) {
dynamic_cast<Gtk::CheckMenuItem*> (&litems.back ())->set_active (true);
}
litems.push_back (CheckMenuElem (_("Toggle"), sigc::bind (sigc::mem_fun (*this, &TriggerBoxUI::set_launch_style), n, Trigger::Toggle)));
if (_triggerbox.trigger (n)->launch_style() == Trigger::Toggle) {
dynamic_cast<Gtk::CheckMenuItem*> (&litems.back ())->set_active (true);
}
litems.push_back (CheckMenuElem (_("Repeat"), sigc::bind (sigc::mem_fun (*this, &TriggerBoxUI::set_launch_style), n, Trigger::Repeat)));
if (_triggerbox.trigger (n)->launch_style() == Trigger::Repeat) {
dynamic_cast<Gtk::CheckMenuItem*> (&litems.back ())->set_active (true);
}
Menu* quant_menu = manage (new Menu);
MenuList& qitems = quant_menu->items();
bool success;
Beats grid_beats (PublicEditor::instance().get_grid_type_as_beats (success, timepos_t (0)));
BBT_Offset b;
if (success) {
b = BBT_Offset (0, grid_beats.get_beats(), grid_beats.get_ticks());
qitems.push_back (CheckMenuElem (_("Main Grid"), sigc::bind (sigc::mem_fun (*this, &TriggerBoxUI::set_quantization), n, b)));
/* can't mark this active because the actual setting just a
* precise setting below */
}
b = BBT_Offset (1, 0, 0);
qitems.push_back (CheckMenuElem (_("Bars"), sigc::bind (sigc::mem_fun (*this, &TriggerBoxUI::set_quantization), n, b)));
if (_triggerbox.trigger (n)->quantization() == b) {
dynamic_cast<Gtk::CheckMenuItem*> (&qitems.back ())->set_active (true);
}
b = BBT_Offset (0, 1, 0);
qitems.push_back (CheckMenuElem (_("Quarters"), sigc::bind (sigc::mem_fun (*this, &TriggerBoxUI::set_quantization), n, b)));
if (_triggerbox.trigger (n)->quantization() == b) {
dynamic_cast<Gtk::CheckMenuItem*> (&qitems.back ())->set_active (true);
}
b = BBT_Offset (0, 0, ticks_per_beat/2);
qitems.push_back (CheckMenuElem (_("Eighths"), sigc::bind (sigc::mem_fun (*this, &TriggerBoxUI::set_quantization), n, b)));
if (_triggerbox.trigger (n)->quantization() == b) {
dynamic_cast<Gtk::CheckMenuItem*> (&qitems.back ())->set_active (true);
}
b = BBT_Offset (0, 0, ticks_per_beat/4);
qitems.push_back (CheckMenuElem (_("Sixteenths"), sigc::bind (sigc::mem_fun (*this, &TriggerBoxUI::set_quantization), n, b)));
if (_triggerbox.trigger (n)->quantization() == b) {
dynamic_cast<Gtk::CheckMenuItem*> (&qitems.back ())->set_active (true);
}
items.push_back (MenuElem (_("Follow Action..."), *follow_menu));
items.push_back (MenuElem (_("Launch Style..."), *launch_menu));
items.push_back (MenuElem (_("Quantization..."), *quant_menu));
_context_menu->popup (1, gtk_get_current_event_time());
}
void
TriggerBoxUI::set_follow_action (size_t n, Trigger::FollowAction fa)
{
_triggerbox.trigger (n)->set_follow_action (fa);
}
void
TriggerBoxUI::set_launch_style (size_t n, Trigger::LaunchStyle ls)
{
_triggerbox.trigger (n)->set_launch_style (ls);
}
void
TriggerBoxUI::set_quantization (size_t n, Temporal::BBT_Offset const & q)
{
_triggerbox.trigger (n)->set_quantization (q);
}
void void
TriggerBoxUI::choose_sample (size_t n) TriggerBoxUI::choose_sample (size_t n)
{ {
@ -227,3 +399,18 @@ TriggerBoxWindow::TriggerBoxWindow (TriggerBox& tb)
add (*tbw); add (*tbw);
tbw->show (); tbw->show ();
} }
bool
TriggerBoxWindow::on_key_press_event (GdkEventKey* ev)
{
Gtk::Window& main_window (ARDOUR_UI::instance()->main_window());
return ARDOUR_UI_UTILS::relay_key_press (ev, &main_window);
}
bool
TriggerBoxWindow::on_key_release_event (GdkEventKey* ev)
{
Gtk::Window& main_window (ARDOUR_UI::instance()->main_window());
return ARDOUR_UI_UTILS::relay_key_press (ev, &main_window);
}

View file

@ -23,17 +23,19 @@
#include <gtkmm/window.h> #include <gtkmm/window.h>
#include "ardour/triggerbox.h"
#include "canvas/box.h" #include "canvas/box.h"
#include "canvas/canvas.h" #include "canvas/canvas.h"
#include "canvas/rectangle.h" #include "canvas/rectangle.h"
namespace Gtk { namespace Gtk {
class FileChooserDialog; class FileChooserDialog;
class Menu;
} }
namespace ARDOUR { namespace Temporal {
class Trigger; struct BBT_Offset;
class TriggerBox;
} }
namespace ArdourCanvas { namespace ArdourCanvas {
@ -68,12 +70,18 @@ class TriggerBoxUI : public ArdourCanvas::Box
Slots _slots; Slots _slots;
Gtk::FileChooserDialog* file_chooser; Gtk::FileChooserDialog* file_chooser;
sigc::connection file_chooser_connection; sigc::connection file_chooser_connection;
Gtk::Menu* _context_menu;
bool bang (GdkEvent*, size_t); bool bang (GdkEvent*, size_t);
bool text_event (GdkEvent*, size_t); bool text_event (GdkEvent*, size_t);
bool event (GdkEvent*, size_t);
void choose_sample (size_t n); void choose_sample (size_t n);
void sample_chosen (int r, size_t n); void sample_chosen (int r, size_t n);
void context_menu (size_t n);
void set_follow_action (size_t slot, ARDOUR::Trigger::FollowAction);
void set_launch_style (size_t slot, ARDOUR::Trigger::LaunchStyle);
void set_quantization (size_t slot, Temporal::BBT_Offset const &);
void build (); void build ();
}; };
@ -95,6 +103,9 @@ class TriggerBoxWindow : public Gtk::Window
{ {
public: public:
TriggerBoxWindow (ARDOUR::TriggerBox&); TriggerBoxWindow (ARDOUR::TriggerBox&);
bool on_key_press_event (GdkEventKey*);
bool on_key_release_event (GdkEventKey*);
}; };
#endif /* __ardour_gtk_triggerbox_ui_h__ */ #endif /* __ardour_gtk_triggerbox_ui_h__ */