diff --git a/gtk2_ardour/control_slave_ui.cc b/gtk2_ardour/control_slave_ui.cc new file mode 100644 index 0000000000..7be2d5daba --- /dev/null +++ b/gtk2_ardour/control_slave_ui.cc @@ -0,0 +1,205 @@ +/* + Copyright (C) 2016 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include + +#include + +#include "pbd/convert.h" + +#include "ardour/session.h" +#include "ardour/stripable.h" +#include "ardour/types.h" +#include "ardour/vca.h" +#include "ardour/vca_manager.h" + +#include "gtkmm2ext/gtk_ui.h" +#include "gtkmm2ext/utils.h" + +#include "ardour_button.h" +#include "control_slave_ui.h" +#include "gui_thread.h" + +#include "i18n.h" + +using namespace ARDOUR; +using namespace Gtk; +using std::string; + +ControlSlaveUI::ControlSlaveUI (Session* s) + : SessionHandlePtr (s) + , initial_button (ArdourButton::default_elements) +{ + set_no_show_all (true); + + Gtkmm2ext::UI::instance()->set_tip (*this, _("Control Masters")); + + initial_button.set_no_show_all (true); + initial_button.set_name (X_("vca assign")); + initial_button.set_text (_("-vca-")); + initial_button.show (); + initial_button.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK); + initial_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &ControlSlaveUI::vca_button_release), 0), false); + + pack_start (initial_button, true, true); +} + +void +ControlSlaveUI::set_stripable (boost::shared_ptr s) +{ + connections.drop_connections (); + + stripable = s; + + if (stripable) { + boost::shared_ptr ac = stripable->gain_control(); + assert (ac); + + ac->MasterStatusChange.connect (connections, + invalidator (*this), + boost::bind (&ControlSlaveUI::update_vca_display, this), + gui_context()); + + stripable->DropReferences.connect (connections, invalidator (*this), boost::bind (&ControlSlaveUI::set_stripable, this, boost::shared_ptr()), gui_context()); + } + + update_vca_display (); +} + +void +ControlSlaveUI::update_vca_display () +{ + VCAList vcas (_session->vca_manager().vcas()); + bool any = false; + + Gtkmm2ext::container_clear (*this); + + for (VCAList::iterator v = vcas.begin(); v != vcas.end(); ++v) { + if (stripable->gain_control()->slaved_to ((*v)->gain_control())) { + add_vca_button (*v); + any = true; + } + } + + if (!any) { + pack_start (initial_button, true, true); + } + + show (); +} + +void +ControlSlaveUI::vca_menu_toggle (Gtk::CheckMenuItem* menuitem, uint32_t n) +{ + boost::shared_ptr vca = _session->vca_manager().vca_by_number (n); + + if (!vca) { + return; + } + + boost::shared_ptr sl = boost::dynamic_pointer_cast (stripable); + + if (!sl) { + return; + } + + if (!menuitem->get_active()) { + sl->unassign (vca); + } else { + sl->assign (vca); + } +} + +void +ControlSlaveUI::unassign_all () +{ + boost::shared_ptr sl = boost::dynamic_pointer_cast (stripable); + + if (!sl) { + return; + } + + sl->unassign (boost::shared_ptr()); +} + +bool +ControlSlaveUI::specific_vca_button_release (GdkEventButton* ev, uint32_t n) +{ + return vca_button_release (ev, n); +} + +bool +ControlSlaveUI::vca_button_release (GdkEventButton* ev, uint32_t n) +{ + using namespace Gtk::Menu_Helpers; + + if (!_session) { + return false; + } + + /* primary click only */ + + if (ev->button != 1) { + return false; + } + + if (!stripable) { + /* no route - nothing to do */ + return false; + } + + VCAList vcas (_session->vca_manager().vcas()); + + if (vcas.empty()) { + /* the button should not have been visible under these conditions */ + return true; + } + + Menu* menu = new Menu; + MenuList& items = menu->items(); + + for (VCAList::iterator v = vcas.begin(); v != vcas.end(); ++v) { + items.push_back (CheckMenuElem ((*v)->name())); + Gtk::CheckMenuItem* item = dynamic_cast (&items.back()); + if (stripable->gain_control()->slaved_to ((*v)->gain_control())) { + item->set_active (true); + } + item->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &ControlSlaveUI::vca_menu_toggle), item, (*v)->number())); + } + + items.push_back (MenuElem (_("Unassign All"), sigc::mem_fun (*this, &ControlSlaveUI::unassign_all))); + + menu->popup (1, ev->time); + + return true; +} + +void +ControlSlaveUI::add_vca_button (boost::shared_ptr vca) +{ + ArdourButton* vca_button = manage (new ArdourButton (ArdourButton::default_elements)); + + vca_button->set_no_show_all (true); + vca_button->set_name (X_("vca assign")); + vca_button->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK); + vca_button->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &ControlSlaveUI::specific_vca_button_release), vca->number()), false); + vca_button->set_text (PBD::to_string (vca->number(), std::dec)); + + pack_start (*vca_button); + vca_button->show (); +} diff --git a/gtk2_ardour/control_slave_ui.h b/gtk2_ardour/control_slave_ui.h new file mode 100644 index 0000000000..1ce35720ec --- /dev/null +++ b/gtk2_ardour/control_slave_ui.h @@ -0,0 +1,61 @@ +/* + Copyright (C) 2016 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __gtk2_ardour_control_slave_ui_h__ +#define __gtk2_ardour_control_slave_ui_h__ + +#include + +#include + +#include +#include + +#include "pbd/signals.h" + +#include "ardour/session_handle.h" + +#include "ardour_button.h" + +namespace ARDOUR { + class VCA; + class Stripable; + class Session; +} + +class ControlSlaveUI : public Gtk::HBox, public ARDOUR::SessionHandlePtr +{ + public: + ControlSlaveUI (ARDOUR::Session*); + void set_stripable (boost::shared_ptr); + + private: + boost::shared_ptr stripable; + PBD::ScopedConnectionList connections; + ArdourButton initial_button; + + void update_vca_display (); + void vca_menu_toggle (Gtk::CheckMenuItem*, uint32_t n); + bool specific_vca_button_release (GdkEventButton* ev, uint32_t n); + bool vca_event_box_release (GdkEventButton* ev); + bool vca_button_release (GdkEventButton* ev, uint32_t n); + void add_vca_button (boost::shared_ptr); + void unassign_all (); +}; + +#endif /* __gtk2_ardour_control_slave_ui_h__ */