+bool
+VCAMasterStrip::solo_release (GdkEventButton*)
+{
+ /* We use NoGroup because VCA controls are never part of a group. This
+ is redundant, but clear.
+ */
+ _vca->solo_control()->set_value (_vca->solo_control()->self_soloed() ? 0.0 : 1.0, Controllable::NoGroup);
+ return true;
+}
+
+bool
+VCAMasterStrip::mute_release (GdkEventButton*)
+{
+ /* We use NoGroup because VCA controls are never part of a group. This
+ is redundant, but clear.
+ */
+ _vca->mute_control()->set_value (_vca->mute_control()->muted_by_self() ? 0.0 : 1.0, Controllable::NoGroup);
+ return true;
+}
+
+void
+VCAMasterStrip::set_solo_text ()
+{
+ if (Config->get_solo_control_is_listen_control ()) {
+ switch (Config->get_listen_position()) {
+ case AfterFaderListen:
+ solo_button.set_text (_("A"));
+ break;
+ case PreFaderListen:
+ solo_button.set_text (_("P"));
+ break;
+ }
+ } else {
+ solo_button.set_text (_("S"));
+ }
+}
+
+void
+VCAMasterStrip::mute_changed ()
+{
+ if (_vca->mute_control()->muted_by_self()) {
+ mute_button.set_active_state (ExplicitActive);
+ } else if (_vca->mute_control()->muted_by_masters ()) {
+ mute_button.set_active_state (ImplicitActive);
+ } else {
+ mute_button.set_active_state (Gtkmm2ext::Off);
+ }
+}
+
+void
+VCAMasterStrip::solo_changed ()
+{
+ if (_vca->solo_control()->self_soloed()) {
+ solo_button.set_active_state (ExplicitActive);
+ } else if (_vca->solo_control()->soloed_by_masters ()) {
+ solo_button.set_active_state (ImplicitActive);
+ } else {
+ solo_button.set_active_state (Gtkmm2ext::Off);
+ }
+}
+
+void
+VCAMasterStrip::vca_menu_toggle (CheckMenuItem* menuitem, uint32_t n)
+{
+ boost::shared_ptr<VCA> vca = _session->vca_manager().vca_by_number (n);
+
+ if (!menuitem->get_active()) {
+ if (!vca) {
+ /* null VCA means drop all VCA assignments */
+ _vca->unassign (boost::shared_ptr<VCA>());
+
+ } else {
+ _vca->unassign (vca);
+ }
+ } else {
+ if (vca) {
+ _vca->assign (vca);
+ }
+ }
+}
+
+void
+VCAMasterStrip::unassign ()
+{
+ _vca->unassign (boost::shared_ptr<VCA>());
+}
+
+bool
+VCAMasterStrip::vca_button_release (GdkEventButton* ev)
+{
+ using namespace Gtk::Menu_Helpers;
+
+ if (!_session) {
+ return false;
+ }
+
+ /* primary click only */
+
+ if (ev->button != 1) {
+ return false;
+ }
+
+ VCAList vcas (_session->vca_manager().vcas());
+
+ if (vcas.empty()) {
+ /* XXX should probably show a message saying "No VCA masters" */
+ return true;
+ }
+
+ Menu* menu = new Menu;
+ MenuList& items = menu->items();
+
+ items.push_back (MenuElem (_("Unassign"), sigc::mem_fun (*this, &VCAMasterStrip::unassign)));
+
+ for (VCAList::iterator v = vcas.begin(); v != vcas.end(); ++v) {
+
+ if (*v == _vca) {
+ /* no self-mastering */
+ continue;
+ }
+
+ items.push_back (CheckMenuElem ((*v)->name()));
+ CheckMenuItem* item = dynamic_cast<CheckMenuItem*> (&items.back());
+ if (_vca->gain_control()->slaved_to ((*v)->gain_control())) {
+ item->set_active (true);
+ }
+ item->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &VCAMasterStrip::vca_menu_toggle), item, (*v)->number()));
+ }
+
+ menu->popup (1, ev->time);
+
+ return true;
+}
+
+bool
+VCAMasterStrip::vertical_button_press (GdkEventButton* ev)
+{
+ if (ev->button == 1 && ev->type == GDK_2BUTTON_PRESS) {
+ start_name_edit ();
+ return true;
+ }
+
+ if (Keyboard::is_context_menu_event (ev)) {
+ if (!context_menu) {
+ build_context_menu ();
+ }
+ context_menu->popup (1, ev->time);
+ return true;
+ }
+
+ if (ev->button == 1) {
+ spill ();
+ }
+
+ return true;
+}
+
+void
+VCAMasterStrip::start_name_edit ()
+{
+ Gtk::Window* win = dynamic_cast<Gtk::Window*>(get_toplevel());
+ FloatingTextEntry* fte = new FloatingTextEntry (win, _vca->name());
+ fte->use_text.connect (sigc::mem_fun (*this, &VCAMasterStrip::finish_name_edit));
+ fte->present ();
+}
+
+void
+VCAMasterStrip::finish_name_edit (std::string str)
+{
+ _vca->set_name (str);
+}
+
+void
+VCAMasterStrip::vca_property_changed (PropertyChange const & what_changed)
+{
+ if (what_changed.contains (ARDOUR::Properties::name)) {
+ update_vca_name ();
+ }
+}
+
+void
+VCAMasterStrip::update_vca_name ()
+{
+ /* 20 is a rough guess at the number of letters we can fit. */
+ vertical_button.set_text (short_version (_vca->name(), 20));
+}
+
+void
+VCAMasterStrip::build_context_menu ()
+{
+ using namespace Gtk::Menu_Helpers;
+ context_menu = new Menu;
+ MenuList& items = context_menu->items();
+ items.push_back (MenuElem (_("Rename"), sigc::mem_fun (*this, &VCAMasterStrip::start_name_edit)));
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Drop All Slaves"), sigc::mem_fun (*this, &VCAMasterStrip::drop_all_slaves)));
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Remove"), sigc::mem_fun (*this, &VCAMasterStrip::remove)));
+}
+
+void
+VCAMasterStrip::spill ()
+{
+ if (Mixer_UI::instance()->showing_vca_slaves_for (_vca)) {
+ Mixer_UI::instance()->show_vca_slaves (boost::shared_ptr<VCA>());
+ } else {
+ Mixer_UI::instance()->show_vca_slaves (_vca);
+ }
+}
+
+void
+VCAMasterStrip::spill_change (boost::shared_ptr<VCA> vca)
+{
+ if (vca != _vca) {
+ vertical_button.set_active_state (Gtkmm2ext::Off);
+ set_tooltip (vertical_button, _("Click to show slaves only"));
+ } else {
+ vertical_button.set_active_state (Gtkmm2ext::ExplicitActive);
+ set_tooltip (vertical_button, _("Click to show normal mixer"));
+ }
+}
+
+void
+VCAMasterStrip::remove ()
+{
+ if (!_session) {
+ return;
+ }
+
+ _session->vca_manager().remove_vca (_vca);
+}
+
+void
+VCAMasterStrip::drop_all_slaves ()
+{
+ _vca->Drop (); /* EMIT SIGNAL */
+
+ if (Mixer_UI::instance()->showing_vca_slaves_for (_vca)) {
+ Mixer_UI::instance()->show_vca_slaves (boost::shared_ptr<VCA>());
+ }
+}
+
+void
+VCAMasterStrip::drop_button_press ()
+{
+ drop_all_slaves ();
+}