X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fmixer_ui.cc;h=db904ddf97775b8355b7241f0159eca366d00be2;hb=4050ca5633dda03679f9aa9fab87d3bbf517395b;hp=7a7b10ec90aa622a0cd245fe53a9c02fd3d96fc9;hpb=fc83d044f85872e55d7da02ff2a4bb6f8725714f;p=ardour.git diff --git a/gtk2_ardour/mixer_ui.cc b/gtk2_ardour/mixer_ui.cc index 7a7b10ec90..db904ddf97 100644 --- a/gtk2_ardour/mixer_ui.cc +++ b/gtk2_ardour/mixer_ui.cc @@ -1,21 +1,29 @@ /* - Copyright (C) 2000-2004 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. - -*/ + * Copyright (C) 2005-2006 Taybin Rutkin + * Copyright (C) 2005-2018 Paul Davis + * Copyright (C) 2006-2007 Doug McLain + * Copyright (C) 2007-2012 Carl Hetherington + * Copyright (C) 2007-2012 David Robillard + * Copyright (C) 2007-2016 Tim Mayberry + * Copyright (C) 2013-2015 Nick Mainsbridge + * Copyright (C) 2013-2019 Robin Gareus + * Copyright (C) 2014-2018 Ben Loftis + * Copyright (C) 2016-2018 Len Ovens + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ #ifdef WAF_BUILD #include "gtk2ardour-config.h" @@ -30,6 +38,7 @@ #include #include +#include #include #include "pbd/convert.h" @@ -103,7 +112,6 @@ Mixer_UI::Mixer_UI () , no_track_list_redisplay (false) , in_group_row_change (false) , track_menu (0) - , _monitor_section (0) , _plugin_selector (0) , _strip_width (UIConfiguration::instance().get_default_narrow_ms() ? Narrow : Wide) , _spill_scroll_position (0) @@ -114,8 +122,8 @@ Mixer_UI::Mixer_UI () , _strip_selection_change_without_scroll (false) , _selection (*this, *this) { - register_actions (); load_bindings (); + register_actions (); _content.set_data ("ardour-bindings", bindings); PresentationInfo::Change.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::presentation_info_changed, this, _1), gui_context()); @@ -161,15 +169,14 @@ Mixer_UI::Mixer_UI () #endif _group_tabs = new MixerGroupTabs (this); - VBox* b = manage (new VBox); - b->set_spacing (0); - b->set_border_width (0); - b->pack_start (*_group_tabs, PACK_SHRINK); - b->pack_start (strip_packer); - b->show_all (); - b->signal_scroll_event().connect (sigc::mem_fun (*this, &Mixer_UI::on_scroll_event), false); - - scroller.add (*b); + strip_group_box.set_spacing (0); + strip_group_box.set_border_width (0); + strip_group_box.pack_start (*_group_tabs, PACK_SHRINK); + strip_group_box.pack_start (strip_packer); + strip_group_box.show_all (); + strip_group_box.signal_scroll_event().connect (sigc::mem_fun (*this, &Mixer_UI::on_scroll_event), false); + + scroller.add (strip_group_box); scroller.set_policy (Gtk::POLICY_ALWAYS, Gtk::POLICY_AUTOMATIC); setup_track_display (); @@ -268,6 +275,7 @@ Mixer_UI::Mixer_UI () vca_scroller_base.set_name (X_("MixerWindow")); vca_scroller_base.signal_button_release_event().connect (sigc::mem_fun(*this, &Mixer_UI::masters_scroller_button_release), false); + vca_hpacker.signal_scroll_event().connect (sigc::mem_fun (*this, &Mixer_UI::on_vca_scroll_event), false); vca_scroller.add (vca_hpacker); vca_scroller.set_policy (Gtk::POLICY_ALWAYS, Gtk::POLICY_AUTOMATIC); vca_scroller.signal_button_release_event().connect (sigc::mem_fun(*this, &Mixer_UI::strip_scroller_button_release)); @@ -348,6 +356,11 @@ Mixer_UI::Mixer_UI () favorite_plugins_display.show(); add_button.show (); + XMLNode* mnode = ARDOUR_UI::instance()->tearoff_settings (X_("monitor-section")); + if (mnode) { + _monitor_section.tearoff().set_state (*mnode); + } + MixerStrip::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::remove_strip, this, _1), gui_context()); VCAMasterStrip::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::remove_master, this, _1), gui_context()); @@ -368,10 +381,8 @@ Mixer_UI::Mixer_UI () Mixer_UI::~Mixer_UI () { - if (_monitor_section) { - monitor_section_detached (); - delete _monitor_section; - } + monitor_section_detached (); + delete _plugin_selector; delete track_menu; } @@ -481,6 +492,12 @@ Mixer_UI::masters_scroller_button_release (GdkEventButton* ev) return false; } +void +Mixer_UI::new_masters_created () +{ + ActionManager::get_toggle_action ("Mixer", "ToggleVCAPane")->set_active (true); +} + void Mixer_UI::add_masters (VCAList& vlist) { @@ -563,25 +580,14 @@ Mixer_UI::add_stripables (StripableList& slist) if (route->is_monitor()) { - if (!_monitor_section) { - _monitor_section = new MonitorSection (_session); - - XMLNode* mnode = ARDOUR_UI::instance()->tearoff_settings (X_("monitor-section")); - if (mnode) { - _monitor_section->tearoff().set_state (*mnode); - } - - set_monitor_action_sensitivity(true); - } - - out_packer.pack_end (_monitor_section->tearoff(), false, false); - _monitor_section->set_session (_session); - _monitor_section->tearoff().show_all (); + out_packer.pack_end (_monitor_section.tearoff(), false, false); + _monitor_section.set_session (_session); + _monitor_section.tearoff().show_all (); - _monitor_section->tearoff().Detach.connect (sigc::mem_fun(*this, &Mixer_UI::monitor_section_detached)); - _monitor_section->tearoff().Attach.connect (sigc::mem_fun(*this, &Mixer_UI::monitor_section_attached)); + _monitor_section.tearoff().Detach.connect (sigc::mem_fun(*this, &Mixer_UI::monitor_section_detached)); + _monitor_section.tearoff().Attach.connect (sigc::mem_fun(*this, &Mixer_UI::monitor_section_attached)); - if (_monitor_section->tearoff().torn_off()) { + if (_monitor_section.tearoff().torn_off()) { monitor_section_detached (); } else { monitor_section_attached (); @@ -1036,6 +1042,7 @@ void Mixer_UI::set_session (Session* sess) { SessionHandlePtr::set_session (sess); + _monitor_section.set_session (sess); if (_plugin_selector) { _plugin_selector->set_session (_session); @@ -1043,10 +1050,6 @@ Mixer_UI::set_session (Session* sess) _group_tabs->set_session (sess); - if (_monitor_section) { - _monitor_section->set_session (_session); - } - if (!_session) { _selection.clear (); return; @@ -1071,6 +1074,7 @@ Mixer_UI::set_session (Session* sess) _session->StateSaved.connect (_session_connections, invalidator (*this), boost::bind (&Mixer_UI::update_title, this), gui_context()); _session->vca_manager().VCAAdded.connect (_session_connections, invalidator (*this), boost::bind (&Mixer_UI::add_masters, this, _1), gui_context()); + _session->vca_manager().VCACreated.connect (_session_connections, invalidator (*this), boost::bind (&Mixer_UI::new_masters_created, this), gui_context()); Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::parameter_changed, this, _1), gui_context ()); @@ -1105,9 +1109,7 @@ Mixer_UI::session_going_away () delete (*i); } - if (_monitor_section) { - _monitor_section->tearoff().hide_visible (); - } + _monitor_section.tearoff().hide_visible (); monitor_section_detached (); @@ -1540,14 +1542,11 @@ Mixer_UI::redisplay_track_list () //show/hide the channelstrip VCA assign buttons on channelstrips: UIConfiguration::instance().set_mixer_strip_visibility (VisibilityGroup::add_element (UIConfiguration::instance().get_mixer_strip_visibility(), X_("VCA"))); - Glib::RefPtr act = ActionManager::get_action ("Mixer", "ToggleVCAPane"); - assert (act); + Glib::RefPtr act = ActionManager::get_toggle_action ("Mixer", "ToggleVCAPane"); act->set_sensitive (true); //if we were showing VCAs before, show them now: - Glib::RefPtr tact = Glib::RefPtr::cast_dynamic(act); - assert (tact); - showhide_vcas ( tact->get_active () ); + showhide_vcas (act->get_active ()); } _group_tabs->set_dirty (); @@ -1650,15 +1649,56 @@ Mixer_UI::track_display_button_press (GdkEventButton* ev) return false; } +void +Mixer_UI::move_vca_into_view (boost::shared_ptr s) +{ + if (!vca_scroller.get_hscrollbar()) { + return; + } + + bool found = false; + int x0 = 0; + Gtk::Allocation alloc; + + TreeModel::Children rows = track_model->children(); + for (TreeModel::Children::const_iterator i = rows.begin(); i != rows.end(); ++i) { + AxisView* av = (*i)[stripable_columns.strip]; + VCAMasterStrip* vms = dynamic_cast (av); + if (vms && vms->stripable () == s) { + int y; + found = true; + vms->translate_coordinates (vca_hpacker, 0, 0, x0, y); + alloc = vms->get_allocation (); + break; + } + } + + if (!found) { + return; + } + + Adjustment* adj = vca_scroller.get_hscrollbar()->get_adjustment(); + + if (x0 < adj->get_value()) { + adj->set_value (max (adj->get_lower(), min (adj->get_upper(), (double) x0))); + } else if (x0 + alloc.get_width() >= adj->get_value() + adj->get_page_size()) { + int x1 = x0 + alloc.get_width() - adj->get_page_size(); + adj->set_value (max (adj->get_lower(), min (adj->get_upper(), (double) x1))); + } +} + void Mixer_UI::move_stripable_into_view (boost::shared_ptr s) { if (!scroller.get_hscrollbar()) { return; } - if (s->presentation_info().special () || s->presentation_info().flag_match (PresentationInfo::VCA)) { + if (s->presentation_info().special ()) { return; } + if (s->presentation_info().flag_match (PresentationInfo::VCA)) { + move_vca_into_view (s); + } #ifdef MIXBUS if (s->mixbus ()) { return; @@ -1940,11 +1980,8 @@ Mixer_UI::route_group_property_changed (RouteGroup* group, const PropertyChange& void Mixer_UI::toggle_mixer_list () { - Glib::RefPtr act = ActionManager::get_action ("Mixer", "ToggleMixerList"); - if (act) { - Glib::RefPtr tact = Glib::RefPtr::cast_dynamic(act); - showhide_mixer_list (tact->get_active()); - } + Glib::RefPtr act = ActionManager::get_toggle_action ("Mixer", "ToggleMixerList"); + showhide_mixer_list (act->get_active()); } void @@ -1960,39 +1997,30 @@ Mixer_UI::showhide_mixer_list (bool yn) void Mixer_UI::toggle_monitor_section () { - Glib::RefPtr act = ActionManager::get_action ("Mixer", "ToggleMonitorSection"); - if (act) { - Glib::RefPtr tact = Glib::RefPtr::cast_dynamic(act); - showhide_monitor_section (tact->get_active()); - } + Glib::RefPtr act = ActionManager::get_toggle_action ("Mixer", "ToggleMonitorSection"); + showhide_monitor_section (act->get_active()); } void Mixer_UI::showhide_monitor_section (bool yn) { - if (!monitor_section()) { - return; - } - if (monitor_section()->tearoff().torn_off()) { + if (monitor_section().tearoff().torn_off()) { return; } if (yn) { - monitor_section()->tearoff().show(); + monitor_section().tearoff().show(); } else { - monitor_section()->tearoff().hide(); + monitor_section().tearoff().hide(); } } void Mixer_UI::toggle_vcas () { - Glib::RefPtr act = ActionManager::get_action ("Mixer", "ToggleVCAPane"); - if (act) { - Glib::RefPtr tact = Glib::RefPtr::cast_dynamic(act); - showhide_vcas (tact->get_active()); - } + Glib::RefPtr act = ActionManager::get_toggle_action ("Mixer", "ToggleVCAPane"); + showhide_vcas (act->get_active()); } void @@ -2009,11 +2037,8 @@ Mixer_UI::showhide_vcas (bool yn) void Mixer_UI::toggle_mixbuses () { - Glib::RefPtr act = ActionManager::get_action ("Mixer", "ToggleMixbusPane"); - if (act) { - Glib::RefPtr tact = Glib::RefPtr::cast_dynamic(act); - showhide_mixbuses (tact->get_active()); - } + Glib::RefPtr act = ActionManager::get_toggle_action ("Mixer", "ToggleMixbusPane"); + showhide_mixbuses (act->get_active()); } void @@ -2224,61 +2249,52 @@ Mixer_UI::set_state (const XMLNode& node, int version) node.get_property ("show-mixer", _visible); - if (node.get_property ("maximised", yn)) { - Glib::RefPtr act = ActionManager::get_action (X_("Common"), X_("ToggleMaximalMixer")); - assert (act); - Glib::RefPtr tact = Glib::RefPtr::cast_dynamic(act); - bool fs = tact && tact->get_active(); + yn = false; + node.get_property ("maximised", yn); + { + Glib::RefPtr act = ActionManager::get_toggle_action (X_("Common"), X_("ToggleMaximalMixer")); + bool fs = act && act->get_active(); if (yn ^ fs) { ActionManager::do_action ("Common", "ToggleMaximalMixer"); } } - if (node.get_property ("show-mixer-list", yn)) { - Glib::RefPtr act = ActionManager::get_action (X_("Mixer"), X_("ToggleMixerList")); - assert (act); - Glib::RefPtr tact = Glib::RefPtr::cast_dynamic(act); - assert (tact); - + yn = true; + node.get_property ("show-mixer-list", yn); + { + Glib::RefPtr act = ActionManager::get_toggle_action (X_("Mixer"), X_("ToggleMixerList")); /* do it twice to force the change */ - tact->set_active (!yn); - tact->set_active (yn); + act->set_active (!yn); + act->set_active (yn); } - if (node.get_property ("monitor-section-visible", yn)) { - Glib::RefPtr act = ActionManager::get_action (X_("Mixer"), X_("ToggleMonitorSection")); - assert (act); - Glib::RefPtr tact = Glib::RefPtr::cast_dynamic(act); - assert (tact); - + yn = true; + node.get_property ("monitor-section-visible", yn); + { + Glib::RefPtr act = ActionManager::get_toggle_action (X_("Mixer"), X_("ToggleMonitorSection")); /* do it twice to force the change */ - tact->set_active (!yn); - tact->set_active (yn); + act->set_active (!yn); + act->set_active (yn); } - if (node.get_property ("show-vca-pane", yn)) { - Glib::RefPtr act = ActionManager::get_action (X_("Mixer"), X_("ToggleVCAPane")); - assert (act); - Glib::RefPtr tact = Glib::RefPtr::cast_dynamic(act); - assert (tact); - + yn = true; + node.get_property ("show-vca-pane", yn); + { + Glib::RefPtr act = ActionManager::get_toggle_action (X_("Mixer"), X_("ToggleVCAPane")); /* do it twice to force the change */ - tact->set_active (!yn); - tact->set_active (yn); + act->set_active (!yn); + act->set_active (yn); } #ifdef MIXBUS - if (node.get_property ("show-mixbus-pane", yn)) { - Glib::RefPtr act = ActionManager::get_action (X_("Mixer"), X_("ToggleMixbusPane")); - assert (act); - Glib::RefPtr tact = Glib::RefPtr::cast_dynamic(act); - assert (tact); - + yn = true; + node.get_property ("show-mixbus-pane", yn); + { + Glib::RefPtr act = ActionManager::get_toggle_action (X_("Mixer"), X_("ToggleMixbusPane")); /* do it twice to force the change */ - tact->set_active (!yn); - tact->set_active (yn); + act->set_active (!yn); + act->set_active (yn); } - #endif //check for the user's plugin_order file @@ -2369,22 +2385,18 @@ Mixer_UI::get_state () node->set_property ("show-mixer", _visible); node->set_property ("maximised", _maximised); - Glib::RefPtr act = ActionManager::get_action ("Mixer", "ToggleMixerList"); - assert (act); Glib::RefPtr tact = Glib::RefPtr::cast_dynamic(act); - assert (tact); node->set_property ("show-mixer-list", tact->get_active ()); + Glib::RefPtr act = ActionManager::get_toggle_action ("Mixer", "ToggleMixerList"); + node->set_property ("show-mixer-list", act->get_active ()); - act = ActionManager::get_action ("Mixer", "ToggleMonitorSection"); - assert (act); tact = Glib::RefPtr::cast_dynamic(act); - assert (tact); node->set_property ("monitor-section-visible", tact->get_active ()); + act = ActionManager::get_toggle_action ("Mixer", "ToggleMonitorSection"); + node->set_property ("monitor-section-visible", act->get_active ()); - act = ActionManager::get_action ("Mixer", "ToggleVCAPane"); - assert (act); tact = Glib::RefPtr::cast_dynamic(act); - assert (tact); node->set_property ("show-vca-pane", tact->get_active ()); + act = ActionManager::get_toggle_action ("Mixer", "ToggleVCAPane"); + node->set_property ("show-vca-pane", act->get_active ()); #ifdef MIXBUS - act = ActionManager::get_action ("Mixer", "ToggleMixbusPane"); - assert (act); tact = Glib::RefPtr::cast_dynamic(act); - assert (tact); node->set_property ("show-mixbus-pane", tact->get_active ()); + act = ActionManager::get_toggle_action ("Mixer", "ToggleMixbusPane"); + node->set_property ("show-mixbus-pane", act->get_active ()); #endif return *node; @@ -2482,6 +2494,87 @@ Mixer_UI::on_scroll_event (GdkEventScroll* ev) return false; } +void +Mixer_UI::vca_scroll_left () +{ + if (!vca_scroller.get_hscrollbar()) return; + Adjustment* adj = vca_scroller.get_hscrollbar()->get_adjustment(); + int sc_w = vca_scroller.get_width(); + int sp_w = strip_packer.get_width(); + if (sp_w <= sc_w) { + return; + } + int lp = adj->get_value(); + int lm = 0; + using namespace Gtk::Box_Helpers; + const BoxList& strips = vca_hpacker.children(); + for (BoxList::const_iterator i = strips.begin(); i != strips.end(); ++i) { + if (i->get_widget() == &add_vca_button) { + continue; + } + lm += i->get_widget()->get_width (); + if (lm >= lp) { + lm -= i->get_widget()->get_width (); + break; + } + } + vca_scroller.get_hscrollbar()->set_value (max (adj->get_lower(), min (adj->get_upper(), lm - 1.0))); +} + +void +Mixer_UI::vca_scroll_right () +{ + if (!vca_scroller.get_hscrollbar()) return; + Adjustment* adj = vca_scroller.get_hscrollbar()->get_adjustment(); + int sc_w = vca_scroller.get_width(); + int sp_w = strip_packer.get_width(); + if (sp_w <= sc_w) { + return; + } + int lp = adj->get_value(); + int lm = 0; + using namespace Gtk::Box_Helpers; + const BoxList& strips = vca_hpacker.children(); + for (BoxList::const_iterator i = strips.begin(); i != strips.end(); ++i) { + if (i->get_widget() == &add_vca_button) { + continue; + } + lm += i->get_widget()->get_width (); + if (lm > lp + 1) { + break; + } + } + vca_scroller.get_hscrollbar()->set_value (max (adj->get_lower(), min (adj->get_upper(), lm - 1.0))); +} + +bool +Mixer_UI::on_vca_scroll_event (GdkEventScroll* ev) +{ + switch (ev->direction) { + case GDK_SCROLL_LEFT: + vca_scroll_left (); + return true; + case GDK_SCROLL_UP: + if (ev->state & Keyboard::TertiaryModifier) { + vca_scroll_left (); + return true; + } + return false; + + case GDK_SCROLL_RIGHT: + vca_scroll_right (); + return true; + + case GDK_SCROLL_DOWN: + if (ev->state & Keyboard::TertiaryModifier) { + vca_scroll_right (); + return true; + } + return false; + } + + return false; +} void Mixer_UI::parameter_changed (string const & p) @@ -2633,60 +2726,29 @@ Mixer_UI::set_axis_targets_for_operation () } void -Mixer_UI::set_monitor_action_sensitivity (bool yn) +Mixer_UI::monitor_section_going_away () { - // TODO use ActionMap::find_toggle_action()->set_*(); - Glib::RefPtr act; - Glib::RefPtr tact; - - act = ActionManager::get_action (X_("Monitor"), "UseMonitorSection"); - tact = Glib::RefPtr::cast_dynamic (act); - tact->set_active (yn); - - act = ActionManager::get_action (X_("Monitor"), "monitor-cut-all"); - tact = Glib::RefPtr::cast_dynamic (act); - tact->set_sensitive (yn); - - act = ActionManager::get_action (X_("Monitor"), "monitor-dim-all"); - tact = Glib::RefPtr::cast_dynamic (act); - tact->set_sensitive (yn); + XMLNode* ui_node = Config->extra_xml(X_("UI")); - act = ActionManager::get_action (X_("Monitor"), "monitor-mono"); - tact = Glib::RefPtr::cast_dynamic (act); - tact->set_sensitive (yn); -} + /* immediate state save. + * + * Tearoff settings are otherwise only stored during + * save_ardour_state(). The mon-section may or may not + * exist at that point. + */ -void -Mixer_UI::monitor_section_going_away () -{ - /* Set sensitivity based on existence of the monitor bus */ - - set_monitor_action_sensitivity(false); - - if (_monitor_section) { - - XMLNode* ui_node = Config->extra_xml(X_("UI")); - /* immediate state save. - * - * Tearoff settings are otherwise only stored during - * save_ardour_state(). The mon-section may or may not - * exist at that point. - * */ - if (ui_node) { - XMLNode* tearoff_node = ui_node->child (X_("Tearoffs")); - if (tearoff_node) { - tearoff_node->remove_nodes_and_delete (X_("monitor-section")); - XMLNode* t = new XMLNode (X_("monitor-section")); - _monitor_section->tearoff().add_state (*t); - tearoff_node->add_child_nocopy (*t); - } + if (ui_node) { + XMLNode* tearoff_node = ui_node->child (X_("Tearoffs")); + if (tearoff_node) { + tearoff_node->remove_nodes_and_delete (X_("monitor-section")); + XMLNode* t = new XMLNode (X_("monitor-section")); + _monitor_section.tearoff().add_state (*t); + tearoff_node->add_child_nocopy (*t); } - monitor_section_detached (); - out_packer.remove (_monitor_section->tearoff()); - _monitor_section->set_session (0); - delete _monitor_section; - _monitor_section = 0; } + + monitor_section_detached (); + out_packer.remove (_monitor_section.tearoff()); } void @@ -2742,12 +2804,9 @@ Mixer_UI::restore_mixer_space () void Mixer_UI::monitor_section_attached () { - Glib::RefPtr act = ActionManager::get_action ("Mixer", "ToggleMonitorSection"); - assert (act); act->set_sensitive (true); - - Glib::RefPtr tact = Glib::RefPtr::cast_dynamic(act); - assert (tact); - showhide_monitor_section ( tact->get_active () ); + Glib::RefPtr act = ActionManager::get_toggle_action ("Mixer", "ToggleMonitorSection"); + act->set_sensitive (true); + showhide_monitor_section (act->get_active ()); } void @@ -2926,6 +2985,9 @@ Mixer_UI::sync_treeview_from_favorite_order () vector presets = (*i)->get_presets (true); for (vector::const_iterator j = presets.begin(); j != presets.end(); ++j) { + if (!(*j).user) { + continue; + } Gtk::TreeModel::Row child_row = *(favorite_plugins_model->append (newrow.children())); child_row[favorite_plugins_columns.name] = (*j).label; child_row[favorite_plugins_columns.plugin] = PluginPresetPtr (new PluginPreset(pip, &(*j))); @@ -2943,7 +3005,7 @@ Mixer_UI::popup_note_context_menu (GdkEventButton *ev) { using namespace Gtk::Menu_Helpers; - Gtk::Menu* m = manage (new Menu); + Gtk::Menu* m = ARDOUR_UI::instance()->shared_popup_menu (); MenuList& items = m->items (); if (_selection.axes.empty()) { @@ -3202,18 +3264,10 @@ Mixer_UI::showing_spill_for (boost::shared_ptr s) const return s == spilled_strip.lock(); } -void -Mixer_UI::show_editor_window () const -{ - PublicEditor::instance().make_visible (); -} - void Mixer_UI::register_actions () { - Glib::RefPtr group = ActionManager::create_action_group (X_("Mixer")); - - ActionManager::register_action (group, "show-editor", _("Show Editor"), sigc::mem_fun (*this, &Mixer_UI::show_editor_window)); + Glib::RefPtr group = ActionManager::create_action_group (bindings, X_("Mixer")); ActionManager::register_action (group, "solo", _("Toggle Solo on Mixer-Selected Tracks/Busses"), sigc::mem_fun (*this, &Mixer_UI::solo_action)); ActionManager::register_action (group, "mute", _("Toggle Mute on Mixer-Selected Tracks/Busses"), sigc::mem_fun (*this, &Mixer_UI::mute_action)); @@ -3246,7 +3300,7 @@ Mixer_UI::register_actions () ActionManager::register_toggle_action (group, X_("ToggleVCAPane"), _("Mixer: Show VCAs"), sigc::mem_fun (*this, &Mixer_UI::toggle_vcas)); #ifdef MIXBUS - ActionManager::register_toggle_action (group, X_("ToggleMixbusPane"), _("Mixer: Show Mixbuses"), sigc::mem_fun (*this, &Mixer_UI::toggle_mixbus_pane)); + ActionManager::register_toggle_action (group, X_("ToggleMixbusPane"), _("Mixer: Show Mixbusses"), sigc::mem_fun (*this, &Mixer_UI::toggle_mixbuses)); #endif ActionManager::register_toggle_action (group, X_("ToggleMonitorSection"), _("Mixer: Show Monitor Section"), sigc::mem_fun (*this, &Mixer_UI::toggle_monitor_section)); @@ -3456,3 +3510,83 @@ Mixer_UI::vca_unassign (boost::shared_ptr vca) } } } + +bool +Mixer_UI::screenshot (std::string const& filename) +{ + if (!_session) { + return false; + } + + int height = strip_packer.get_height(); + bool with_vca = vca_vpacker.is_visible (); + MixerStrip* master = strip_by_route (_session->master_out ()); + + Gtk::OffscreenWindow osw; + Gtk::HBox b; + osw.add (b); + b.show (); + + /* unpack widgets, add to OffscreenWindow */ + + strip_group_box.remove (strip_packer); + b.pack_start (strip_packer, false, false); + /* hide extra elements inside strip_packer */ + add_button.hide (); + scroller_base.hide (); +#ifdef MIXBUS + mb_shadow.hide(); +#endif + + if (with_vca) { + /* work around Gtk::ScrolledWindow */ + Gtk::Viewport* viewport = (Gtk::Viewport*) vca_scroller.get_child(); + viewport->remove (); // << vca_hpacker + b.pack_start (vca_hpacker, false, false); + /* hide some growing widgets */ + add_vca_button.hide (); + vca_scroller_base.hide(); + } + + if (master) { + out_packer.remove (*master); + b.pack_start (*master, false, false); + master->hide_master_spacer (true); + } + + /* prepare the OffscreenWindow for rendering */ + osw.set_size_request (-1, height); + osw.show (); + osw.queue_resize (); + osw.queue_draw (); + osw.get_window()->process_updates (true); + + /* create screenshot */ + Glib::RefPtr pb = osw.get_pixbuf (); + pb->save (filename, "png"); + + /* unpack elements before destorying the Box & OffscreenWindow */ + list children = b.get_children(); + for (list::iterator child = children.begin(); child != children.end(); ++child) { + b.remove (**child); + } + osw.remove (); + + /* now re-pack the widgets into the main mixer window */ + add_button.show (); + scroller_base.show (); +#ifdef MIXBUS + mb_shadow.show(); +#endif + strip_group_box.pack_start (strip_packer); + if (with_vca) { + add_vca_button.show (); + vca_scroller_base.show(); + vca_scroller.add (vca_hpacker); + } + if (master) { + master->hide_master_spacer (false); + out_packer.pack_start (*master, false, false); + } + return true; +}