diff options
author | Robin Gareus <robin@gareus.org> | 2017-06-09 14:48:33 +0200 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2017-06-15 16:06:32 +0200 |
commit | af6941ac3409167cc7e4eb799035fbcdc9e835dd (patch) | |
tree | 027c6de093e8b49d041e1980b40f6feb32f121bd | |
parent | 5957a4619ae06158dda68f92f346fbb26d7bb724 (diff) |
Prepare VCA Automation Lanes -- refactor TAV
* add an abstract StripableTimeAxisView (Route TAV + VCA TAV)
* move common strip-methods into STAV
* Add Automation Lanes to VCA TAV
* Allow ATAV without Automatable for VCA Controls
-rw-r--r-- | gtk2_ardour/automation_time_axis.cc | 9 | ||||
-rw-r--r-- | gtk2_ardour/route_time_axis.cc | 189 | ||||
-rw-r--r-- | gtk2_ardour/route_time_axis.h | 31 | ||||
-rw-r--r-- | gtk2_ardour/route_ui.cc | 8 | ||||
-rw-r--r-- | gtk2_ardour/route_ui.h | 2 | ||||
-rw-r--r-- | gtk2_ardour/stripable_time_axis.cc | 259 | ||||
-rw-r--r-- | gtk2_ardour/stripable_time_axis.h | 83 | ||||
-rw-r--r-- | gtk2_ardour/vca_time_axis.cc | 187 | ||||
-rw-r--r-- | gtk2_ardour/vca_time_axis.h | 22 | ||||
-rw-r--r-- | gtk2_ardour/wscript | 1 |
10 files changed, 551 insertions, 240 deletions
diff --git a/gtk2_ardour/automation_time_axis.cc b/gtk2_ardour/automation_time_axis.cc index ef06068c52..f575cb2a45 100644 --- a/gtk2_ardour/automation_time_axis.cc +++ b/gtk2_ardour/automation_time_axis.cc @@ -324,6 +324,9 @@ AutomationTimeAxisView::set_automation_state (AutoState state) if (_automatable) { _automatable->set_parameter_automation_state (_parameter, state); } + else if (_control) { + _control->set_automation_state (state); + } if (_view) { _view->set_automation_state (state); @@ -916,14 +919,14 @@ AutomationTimeAxisView::lines () const string AutomationTimeAxisView::state_id() const { - if (_automatable != _stripable && _control) { - return string("automation ") + _control->id().to_s(); - } else if (_parameter) { + if (_parameter && _stripable && _automatable == _stripable) { const string parameter_str = PBD::to_string (_parameter.type()) + "/" + PBD::to_string (_parameter.id()) + "/" + PBD::to_string (_parameter.channel ()); return string("automation ") + PBD::to_string(_stripable->id()) + " " + parameter_str; + } else if (_automatable != _stripable && _control) { + return string("automation ") + _control->id().to_s(); } else { error << "Automation time axis has no state ID" << endmsg; return ""; diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc index a32f6b27df..b60f35e8b7 100644 --- a/gtk2_ardour/route_time_axis.cc +++ b/gtk2_ardour/route_time_axis.cc @@ -97,10 +97,8 @@ using std::list; RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session* sess, ArdourCanvas::Canvas& canvas) : RouteUI(sess) - , TimeAxisView(sess,ed,(TimeAxisView*) 0, canvas) + , StripableTimeAxisView(ed, sess, canvas) , _view (0) - , parent_canvas (canvas) - , no_redraw (false) , button_table (3, 3) , route_group_button (S_("RTAV|G")) , playlist_button (S_("RTAV|P")) @@ -113,9 +111,6 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session* sess, ArdourCan , color_mode_menu (0) , gm (sess, true, 75, 14) , _ignore_set_layer_display (false) - , gain_automation_item(NULL) - , trim_automation_item(NULL) - , mute_automation_item(NULL) , pan_automation_item(NULL) { number_label.set_name("tracknumber label"); @@ -141,6 +136,7 @@ void RouteTimeAxisView::set_route (boost::shared_ptr<Route> rt) { RouteUI::set_route (rt); + StripableTimeAxisView::set_stripable (rt); CANVAS_DEBUG_NAME (_canvas_display, string_compose ("main for %1", rt->name())); CANVAS_DEBUG_NAME (selection_group, string_compose ("selections for %1", rt->name())); @@ -320,7 +316,6 @@ RouteTimeAxisView::set_route (boost::shared_ptr<Route> rt) } - _editor.ZoomChanged.connect (sigc::mem_fun(*this, &RouteTimeAxisView::reset_samples_per_pixel)); UIConfiguration::instance().ColorsChanged.connect (sigc::mem_fun (*this, &RouteTimeAxisView::color_handler)); PropertyList* plist = new PropertyList(); @@ -1093,12 +1088,6 @@ RouteTimeAxisView::route_color_changed () } void -RouteTimeAxisView::reset_samples_per_pixel () -{ - set_samples_per_pixel (_editor.get_current_zoom()); -} - -void RouteTimeAxisView::set_samples_per_pixel (double fpp) { double speed = 1.0; @@ -1111,7 +1100,7 @@ RouteTimeAxisView::set_samples_per_pixel (double fpp) _view->set_samples_per_pixel (fpp * speed); } - TimeAxisView::set_samples_per_pixel (fpp * speed); + StripableTimeAxisView::set_samples_per_pixel (fpp * speed); } void @@ -1881,79 +1870,6 @@ RouteTimeAxisView::toggle_automation_track (const Evoral::Parameter& param) } void -RouteTimeAxisView::automation_track_hidden (Evoral::Parameter param) -{ - boost::shared_ptr<AutomationTimeAxisView> track = automation_child (param); - - if (!track) { - return; - } - - Gtk::CheckMenuItem* menu = automation_child_menu_item (param); - - if (menu && !_hidden) { - ignore_toggle = true; - menu->set_active (false); - ignore_toggle = false; - } - - if (_route && !no_redraw) { - request_redraw (); - } -} - -void -RouteTimeAxisView::update_gain_track_visibility () -{ - bool const showit = gain_automation_item->get_active(); - - bool visible; - if (gain_track->get_gui_property ("visible", visible) && visible != showit) { - gain_track->set_marked_for_display (showit); - - /* now trigger a redisplay */ - - if (!no_redraw) { - _route->gui_changed (X_("visible_tracks"), (void *) 0); /* EMIT_SIGNAL */ - } - } -} - -void -RouteTimeAxisView::update_trim_track_visibility () -{ - bool const showit = trim_automation_item->get_active(); - - bool visible; - if (trim_track->get_gui_property ("visible", visible) && visible != showit) { - trim_track->set_marked_for_display (showit); - - /* now trigger a redisplay */ - - if (!no_redraw) { - _route->gui_changed (X_("visible_tracks"), (void *) 0); /* EMIT_SIGNAL */ - } - } -} - -void -RouteTimeAxisView::update_mute_track_visibility () -{ - bool const showit = mute_automation_item->get_active(); - - bool visible; - if (mute_track->get_gui_property ("visible", visible) && visible != showit) { - mute_track->set_marked_for_display (showit); - - /* now trigger a redisplay */ - - if (!no_redraw) { - _route->gui_changed (X_("visible_tracks"), (void *) 0); /* EMIT_SIGNAL */ - } - } -} - -void RouteTimeAxisView::update_pan_track_visibility () { bool const showit = pan_automation_item->get_active(); @@ -2034,18 +1950,7 @@ RouteTimeAxisView::show_all_automation (bool apply_to_selection) } else { no_redraw = true; - /* Show our automation */ - - for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) { - i->second->set_marked_for_display (true); - - Gtk::CheckMenuItem* menu = automation_child_menu_item (i->first); - - if (menu) { - menu->set_active(true); - } - } - + StripableTimeAxisView::show_all_automation (); /* Show processor automation */ @@ -2075,21 +1980,9 @@ RouteTimeAxisView::show_existing_automation (bool apply_to_selection) } else { no_redraw = true; - /* Show our automation */ - - for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) { - if (i->second->has_automation()) { - i->second->set_marked_for_display (true); - - Gtk::CheckMenuItem* menu = automation_child_menu_item (i->first); - if (menu) { - menu->set_active(true); - } - } - } + StripableTimeAxisView::show_existing_automation (); /* Show processor automation */ - for (list<ProcessorAutomationInfo*>::iterator i = processor_automation.begin(); i != processor_automation.end(); ++i) { for (vector<ProcessorAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) { if ((*i)->processor->control((*ii)->what)->list()->size() > 0) { @@ -2099,7 +1992,6 @@ RouteTimeAxisView::show_existing_automation (bool apply_to_selection) } no_redraw = false; - request_redraw (); } } @@ -2111,21 +2003,9 @@ RouteTimeAxisView::hide_all_automation (bool apply_to_selection) _editor.get_selection().tracks.foreach_route_time_axis (boost::bind (&RouteTimeAxisView::hide_all_automation, _1, false)); } else { no_redraw = true; - - /* Hide our automation */ - - for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) { - i->second->set_marked_for_display (false); - - Gtk::CheckMenuItem* menu = automation_child_menu_item (i->first); - - if (menu) { - menu->set_active (false); - } - } + StripableTimeAxisView::hide_all_automation (); /* Hide processor automation */ - for (list<ProcessorAutomationInfo*>::iterator i = processor_automation.begin(); i != processor_automation.end(); ++i) { for (vector<ProcessorAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) { (*ii)->menu_item->set_active (false); @@ -2137,7 +2017,6 @@ RouteTimeAxisView::hide_all_automation (bool apply_to_selection) } } - void RouteTimeAxisView::region_view_added (RegionView* rv) { @@ -2272,41 +2151,6 @@ RouteTimeAxisView::add_existing_processor_automation_curves (boost::weak_ptr<Pro } void -RouteTimeAxisView::add_automation_child (Evoral::Parameter param, boost::shared_ptr<AutomationTimeAxisView> track, bool show) -{ - using namespace Menu_Helpers; - - add_child (track); - - track->Hiding.connect (sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::automation_track_hidden), param)); - - _automation_tracks[param] = track; - - /* existing state overrides "show" argument */ - bool visible; - if (track->get_gui_property ("visible", visible)) { - show = visible; - } - - /* this might or might not change the visibility status, so don't rely on it */ - track->set_marked_for_display (show); - - if (show && !no_redraw) { - request_redraw (); - } - - if (!ARDOUR::parameter_is_midi((AutomationType)param.type())) { - /* MIDI-related parameters are always in the menu, there's no - reason to rebuild the menu just because we added a automation - lane for one of them. But if we add a non-MIDI automation - lane, then we need to invalidate the display menu. - */ - delete display_menu; - display_menu = 0; - } -} - -void RouteTimeAxisView::add_processor_to_subplugin_menu (boost::weak_ptr<Processor> p) { boost::shared_ptr<Processor> processor (p.lock ()); @@ -2543,19 +2387,6 @@ RouteTimeAxisView::layer_display () const return Overlaid; } - - -boost::shared_ptr<AutomationTimeAxisView> -RouteTimeAxisView::automation_child(Evoral::Parameter param) -{ - AutomationTracks::iterator i = _automation_tracks.find(param); - if (i != _automation_tracks.end()) { - return i->second; - } else { - return boost::shared_ptr<AutomationTimeAxisView>(); - } -} - void RouteTimeAxisView::fast_update () { @@ -2761,12 +2592,12 @@ RouteTimeAxisView::set_button_names () Gtk::CheckMenuItem* RouteTimeAxisView::automation_child_menu_item (Evoral::Parameter param) { - ParameterMenuMap::iterator i = _main_automation_menu_map.find (param); - if (i != _main_automation_menu_map.end()) { - return i->second; + Gtk::CheckMenuItem* rv = StripableTimeAxisView::automation_child_menu_item (param); + if (rv) { + return rv; } - i = _subplugin_menu_map.find (param); + ParameterMenuMap::iterator i = _subplugin_menu_map.find (param); if (i != _subplugin_menu_map.end()) { return i->second; } diff --git a/gtk2_ardour/route_time_axis.h b/gtk2_ardour/route_time_axis.h index 3566d6624e..fe33a002f4 100644 --- a/gtk2_ardour/route_time_axis.h +++ b/gtk2_ardour/route_time_axis.h @@ -42,7 +42,7 @@ #include "ardour_dialog.h" #include "route_ui.h" #include "enums.h" -#include "time_axis_view.h" +#include "stripable_time_axis.h" #include "gain_meter.h" namespace ARDOUR { @@ -72,7 +72,7 @@ class TimeSelection; class RouteGroupMenu; class ItemCounts; -class RouteTimeAxisView : public RouteUI, public TimeAxisView +class RouteTimeAxisView : public RouteUI, public StripableTimeAxisView { public: RouteTimeAxisView (PublicEditor&, ARDOUR::Session*, ArdourCanvas::Canvas& canvas); @@ -129,12 +129,6 @@ public: int set_state (const XMLNode&, int version); - virtual void create_automation_child (const Evoral::Parameter& param, bool show) = 0; - - typedef std::map<Evoral::Parameter, boost::shared_ptr<AutomationTimeAxisView> > AutomationTracks; - const AutomationTracks& automation_tracks() const { return _automation_tracks; } - - boost::shared_ptr<AutomationTimeAxisView> automation_child(Evoral::Parameter param); virtual Gtk::CheckMenuItem* automation_child_menu_item (Evoral::Parameter); StreamView* view() const { return _view; } @@ -195,7 +189,6 @@ protected: void processor_automation_track_hidden (ProcessorAutomationNode*, boost::shared_ptr<ARDOUR::Processor>); - void automation_track_hidden (Evoral::Parameter param); ProcessorAutomationNode* find_processor_automation_node (boost::shared_ptr<ARDOUR::Processor> i, Evoral::Parameter); @@ -206,7 +199,6 @@ protected: void add_processor_automation_curve (boost::shared_ptr<ARDOUR::Processor> r, Evoral::Parameter); void add_existing_processor_automation_curves (boost::weak_ptr<ARDOUR::Processor>); - void add_automation_child(Evoral::Parameter param, boost::shared_ptr<AutomationTimeAxisView> track, bool show=true); void reset_processor_automation_curves (); @@ -220,8 +212,6 @@ protected: virtual void label_view (); - void reset_samples_per_pixel (); - virtual void build_automation_action_menu (bool); virtual void append_extra_display_menu_items () {} void build_display_menu (); @@ -252,13 +242,7 @@ protected: void route_color_changed (); bool can_edit_name() const; - boost::shared_ptr<AutomationTimeAxisView> gain_track; - boost::shared_ptr<AutomationTimeAxisView> trim_track; - boost::shared_ptr<AutomationTimeAxisView> mute_track; - StreamView* _view; - ArdourCanvas::Canvas& parent_canvas; - bool no_redraw; Gtk::HBox other_button_hbox; Gtk::Table button_table; @@ -293,11 +277,6 @@ protected: typedef std::vector<boost::shared_ptr<AutomationLine> > ProcessorAutomationCurves; ProcessorAutomationCurves processor_automation_curves; - - AutomationTracks _automation_tracks; - typedef std::map<Evoral::Parameter, Gtk::CheckMenuItem*> ParameterMenuMap; - /** parameter -> menu item map for the main automation menu */ - ParameterMenuMap _main_automation_menu_map; /** parameter -> menu item map for the plugin automation menu */ ParameterMenuMap _subplugin_menu_map; @@ -316,9 +295,6 @@ protected: bool _ignore_set_layer_display; protected: - void update_gain_track_visibility (); - void update_trim_track_visibility (); - void update_mute_track_visibility (); void update_pan_track_visibility (); /** Ensure that we have the appropriate automation lanes for panners. @@ -327,9 +303,6 @@ protected: */ void ensure_pan_views (bool show = true); - Gtk::CheckMenuItem* gain_automation_item; - Gtk::CheckMenuItem* trim_automation_item; - Gtk::CheckMenuItem* mute_automation_item; std::list<boost::shared_ptr<AutomationTimeAxisView> > pan_tracks; Gtk::CheckMenuItem* pan_automation_item; diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc index 765461f4ab..c35d80d848 100644 --- a/gtk2_ardour/route_ui.cc +++ b/gtk2_ardour/route_ui.cc @@ -2181,14 +2181,6 @@ RouteUI::set_invert_sensitive (bool yn) } } -void -RouteUI::request_redraw () -{ - if (_route) { - _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ - } -} - /** The Route's gui_changed signal has been emitted */ void RouteUI::route_gui_changed (PropertyChange const& what_changed) diff --git a/gtk2_ardour/route_ui.h b/gtk2_ardour/route_ui.h index 7e4dd2e968..7baf99d32a 100644 --- a/gtk2_ardour/route_ui.h +++ b/gtk2_ardour/route_ui.h @@ -104,8 +104,6 @@ class RouteUI : public virtual Selectable, public virtual ARDOUR::SessionHandleP boost::shared_ptr<ARDOUR::Route> _route; - void request_redraw (); - virtual void set_color (uint32_t c); Gdk::Color route_color () const; void choose_color (); diff --git a/gtk2_ardour/stripable_time_axis.cc b/gtk2_ardour/stripable_time_axis.cc new file mode 100644 index 0000000000..e5f02ee6b9 --- /dev/null +++ b/gtk2_ardour/stripable_time_axis.cc @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2017 Robin Gareus <robin@gareus.org> + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <gtkmm/menu.h> +#include <gtkmm/menuitem.h> + +#include "ardour/parameter_descriptor.h" +#include "ardour/parameter_types.h" +#include "ardour/stripable.h" + +#include "public_editor.h" +#include "stripable_time_axis.h" + +#include "pbd/i18n.h" + +using namespace PBD; +using namespace ARDOUR; +using namespace Gtk; + +StripableTimeAxisView::StripableTimeAxisView (PublicEditor& ed, ARDOUR::Session* s, ArdourCanvas::Canvas& canvas) + : TimeAxisView(s, ed, (TimeAxisView*) 0, canvas) + , gain_automation_item(NULL) + , trim_automation_item(NULL) + , mute_automation_item(NULL) + , parent_canvas (canvas) + , no_redraw (false) +{ +} + +StripableTimeAxisView::~StripableTimeAxisView () +{ +} + +void +StripableTimeAxisView::set_stripable (boost::shared_ptr<ARDOUR::Stripable> s) +{ + _stripable = s; + _editor.ZoomChanged.connect (sigc::mem_fun(*this, &StripableTimeAxisView::reset_samples_per_pixel)); +} + +void +StripableTimeAxisView::reset_samples_per_pixel () +{ + set_samples_per_pixel (_editor.get_current_zoom()); +} + +void +StripableTimeAxisView::set_samples_per_pixel (double fpp) +{ + TimeAxisView::set_samples_per_pixel (fpp); +} + + +void +StripableTimeAxisView::add_automation_child (Evoral::Parameter param, boost::shared_ptr<AutomationTimeAxisView> track, bool show) +{ + using namespace Menu_Helpers; + + add_child (track); + + track->Hiding.connect (sigc::bind (sigc::mem_fun (*this, &StripableTimeAxisView::automation_track_hidden), param)); + + _automation_tracks[param] = track; + + /* existing state overrides "show" argument */ + bool visible; + if (track->get_gui_property ("visible", visible)) { + show = visible; + } + + /* this might or might not change the visibility status, so don't rely on it */ + track->set_marked_for_display (show); + + if (show && !no_redraw) { + request_redraw (); + } + + if (!ARDOUR::parameter_is_midi((AutomationType)param.type())) { + /* MIDI-related parameters are always in the menu, there's no + reason to rebuild the menu just because we added a automation + lane for one of them. But if we add a non-MIDI automation + lane, then we need to invalidate the display menu. + */ + delete display_menu; + display_menu = 0; + } +} + +void +StripableTimeAxisView::update_gain_track_visibility () +{ + bool const showit = gain_automation_item->get_active(); + + bool visible; + if (gain_track->get_gui_property ("visible", visible) && visible != showit) { + gain_track->set_marked_for_display (showit); + + /* now trigger a redisplay */ + + if (!no_redraw) { + _stripable->gui_changed (X_("visible_tracks"), (void *) 0); /* EMIT_SIGNAL */ + } + } +} + +void +StripableTimeAxisView::update_trim_track_visibility () +{ + bool const showit = trim_automation_item->get_active(); + + bool visible; + if (trim_track->get_gui_property ("visible", visible) && visible != showit) { + trim_track->set_marked_for_display (showit); + + /* now trigger a redisplay */ + + if (!no_redraw) { + _stripable->gui_changed (X_("visible_tracks"), (void *) 0); /* EMIT_SIGNAL */ + } + } +} + +void +StripableTimeAxisView::update_mute_track_visibility () +{ + bool const showit = mute_automation_item->get_active(); + + bool visible; + if (mute_track->get_gui_property ("visible", visible) && visible != showit) { + mute_track->set_marked_for_display (showit); + + /* now trigger a redisplay */ + + if (!no_redraw) { + _stripable->gui_changed (X_("visible_tracks"), (void *) 0); /* EMIT_SIGNAL */ + } + } +} + +Gtk::CheckMenuItem* +StripableTimeAxisView::automation_child_menu_item (Evoral::Parameter param) +{ + ParameterMenuMap::iterator i = _main_automation_menu_map.find (param); + if (i != _main_automation_menu_map.end()) { + return i->second; + } + + return 0; +} + +void +StripableTimeAxisView::automation_track_hidden (Evoral::Parameter param) +{ + boost::shared_ptr<AutomationTimeAxisView> track = automation_child (param); + + if (!track) { + return; + } + + Gtk::CheckMenuItem* menu = automation_child_menu_item (param); + + if (menu && !_hidden && menu->get_active()) { + menu->set_active (false); + } + + if (_stripable && !no_redraw) { + request_redraw (); + } +} + +boost::shared_ptr<AutomationTimeAxisView> +StripableTimeAxisView::automation_child(Evoral::Parameter param) +{ + AutomationTracks::iterator i = _automation_tracks.find(param); + if (i != _automation_tracks.end()) { + return i->second; + } else { + return boost::shared_ptr<AutomationTimeAxisView>(); + } +} + +void +StripableTimeAxisView::request_redraw () +{ + if (_stripable) { + _stripable->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ + } +} + +void +StripableTimeAxisView::show_all_automation (bool apply_to_selection) +{ + /* this protected member should not be called directly */ + assert (!apply_to_selection); + assert (no_redraw); + + for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) { + i->second->set_marked_for_display (true); + + Gtk::CheckMenuItem* menu = automation_child_menu_item (i->first); + + if (menu) { + menu->set_active(true); + } + } +} + +void +StripableTimeAxisView::show_existing_automation (bool apply_to_selection) +{ + /* this protected member should not be called directly */ + assert (!apply_to_selection); + assert (no_redraw); + + for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) { + if (i->second->has_automation()) { + i->second->set_marked_for_display (true); + + Gtk::CheckMenuItem* menu = automation_child_menu_item (i->first); + if (menu) { + menu->set_active(true); + } + } + } +} + +void +StripableTimeAxisView::hide_all_automation (bool apply_to_selection) +{ + /* this protected member should not be called directly */ + assert (!apply_to_selection); + assert (no_redraw); + + for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) { + i->second->set_marked_for_display (false); + + Gtk::CheckMenuItem* menu = automation_child_menu_item (i->first); + + if (menu) { + menu->set_active (false); + } + } +} diff --git a/gtk2_ardour/stripable_time_axis.h b/gtk2_ardour/stripable_time_axis.h new file mode 100644 index 0000000000..4734c1bf85 --- /dev/null +++ b/gtk2_ardour/stripable_time_axis.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2017 Robin Gareus <robin@gareus.org> + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __ardour_stripable_time_axis_h__ +#define __ardour_stripable_time_axis_h__ + +#include "automation_time_axis.h" +#include "time_axis_view.h" + +class StripableTimeAxisView : public TimeAxisView +{ +public: + StripableTimeAxisView (PublicEditor&, ARDOUR::Session*, ArdourCanvas::Canvas& canvas); + virtual ~StripableTimeAxisView (); + + void set_stripable (boost::shared_ptr<ARDOUR::Stripable>); + boost::shared_ptr<ARDOUR::Stripable> stripable() const { return _stripable; } + + typedef std::map<Evoral::Parameter, boost::shared_ptr<AutomationTimeAxisView> > AutomationTracks; + const AutomationTracks& automation_tracks() const { return _automation_tracks; } + virtual Gtk::CheckMenuItem* automation_child_menu_item (Evoral::Parameter); + + virtual void create_automation_child (const Evoral::Parameter& param, bool show) = 0; + boost::shared_ptr<AutomationTimeAxisView> automation_child(Evoral::Parameter param); + + void request_redraw (); + +protected: + void reset_samples_per_pixel (); + virtual void set_samples_per_pixel (double); + void add_automation_child(Evoral::Parameter param, boost::shared_ptr<AutomationTimeAxisView> track, bool show=true); + + virtual void create_gain_automation_child (const Evoral::Parameter &, bool) = 0; + virtual void create_trim_automation_child (const Evoral::Parameter &, bool) = 0; + virtual void create_mute_automation_child (const Evoral::Parameter &, bool) = 0; + + void automation_track_hidden (Evoral::Parameter param); + + void update_gain_track_visibility (); + void update_trim_track_visibility (); + void update_mute_track_visibility (); + + virtual void show_all_automation (bool apply_to_selection = false); + virtual void show_existing_automation (bool apply_to_selection = false); + virtual void hide_all_automation (bool apply_to_selection = false); + + boost::shared_ptr<ARDOUR::Stripable> _stripable; + + boost::shared_ptr<AutomationTimeAxisView> gain_track; + boost::shared_ptr<AutomationTimeAxisView> trim_track; + boost::shared_ptr<AutomationTimeAxisView> mute_track; + + typedef std::map<Evoral::Parameter, Gtk::CheckMenuItem*> ParameterMenuMap; + /** parameter -> menu item map for the main automation menu */ + ParameterMenuMap _main_automation_menu_map; + + Gtk::CheckMenuItem* gain_automation_item; + Gtk::CheckMenuItem* trim_automation_item; + Gtk::CheckMenuItem* mute_automation_item; + + AutomationTracks _automation_tracks; + + ArdourCanvas::Canvas& parent_canvas; + bool no_redraw; +}; + +#endif /* __ardour_stripable_time_axis_h__ */ diff --git a/gtk2_ardour/vca_time_axis.cc b/gtk2_ardour/vca_time_axis.cc index 811437b585..39ce9c0aa0 100644 --- a/gtk2_ardour/vca_time_axis.cc +++ b/gtk2_ardour/vca_time_axis.cc @@ -17,6 +17,8 @@ */ +#include <gtkmm/menu.h> + #include "pbd/string_convert.h" #include "ardour/mute_control.h" @@ -26,6 +28,7 @@ #include "ardour/vca.h" #include "gtkmm2ext/doi.h" +#include <gtkmm2ext/utils.h> #include "gui_thread.h" #include "public_editor.h" @@ -37,50 +40,54 @@ using namespace ARDOUR; using namespace ARDOUR_UI_UTILS; +using namespace Gtk; using namespace Gtkmm2ext; using namespace PBD; VCATimeAxisView::VCATimeAxisView (PublicEditor& ed, Session* s, ArdourCanvas::Canvas& canvas) : SessionHandlePtr (s) - , TimeAxisView (s, ed, (TimeAxisView*) 0, canvas) + , StripableTimeAxisView (ed, s, canvas) , gain_meter (s, true, 75, 14) // XXX stupid magic numbers, match sizes in RouteTimeAxisView + , automation_action_menu (0) { solo_button.set_name ("solo button"); set_tooltip (solo_button, _("Solo slaves")); solo_button.signal_button_release_event().connect (sigc::mem_fun (*this, &VCATimeAxisView::solo_release), false); - mute_button.unset_flags (Gtk::CAN_FOCUS); + solo_button.unset_flags (Gtk::CAN_FOCUS); mute_button.set_name ("mute button"); - mute_button.set_text (_("M")); + mute_button.set_text (S_("Mute|M")); set_tooltip (mute_button, _("Mute slaves")); mute_button.signal_button_release_event().connect (sigc::mem_fun (*this, &VCATimeAxisView::mute_release), false); - solo_button.unset_flags (Gtk::CAN_FOCUS); + mute_button.unset_flags (Gtk::CAN_FOCUS); drop_button.set_name ("mute button"); - drop_button.set_text (_("D")); + drop_button.set_text (S_("VCA|D")); set_tooltip (drop_button, _("Unassign all slaves")); drop_button.signal_button_release_event().connect (sigc::mem_fun (*this, &VCATimeAxisView::drop_release), false); + drop_button.unset_flags (Gtk::CAN_FOCUS); - spill_button.set_name ("mute button"); - spill_button.set_text (_("V")); - set_tooltip (spill_button, _("Show only slaves")); - spill_button.signal_button_release_event().connect (sigc::mem_fun (*this, &VCATimeAxisView::spill_release), false); + automation_button.set_name ("route button"); + automation_button.set_text (S_("RTAV|A")); + set_tooltip (automation_button, _("Automation")); + automation_button.signal_button_press_event().connect (sigc::mem_fun (*this, &VCATimeAxisView::automation_click), false); + automation_button.unset_flags (Gtk::CAN_FOCUS); mute_button.set_tweaks(ArdourButton::TrackHeader); solo_button.set_tweaks(ArdourButton::TrackHeader); drop_button.set_tweaks(ArdourButton::TrackHeader); - spill_button.set_tweaks(ArdourButton::TrackHeader); + automation_button.set_tweaks(ArdourButton::TrackHeader); controls_table.attach (mute_button, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0); controls_table.attach (solo_button, 3, 4, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0); - controls_table.attach (drop_button, 2, 3, 1, 2, Gtk::SHRINK, Gtk::SHRINK, 0, 0); - controls_table.attach (spill_button, 3, 4, 1, 2, Gtk::SHRINK, Gtk::SHRINK, 0, 0); + controls_table.attach (automation_button, 2, 3, 1, 2, Gtk::SHRINK, Gtk::SHRINK, 0, 0); + controls_table.attach (drop_button, 3, 4, 1, 2, Gtk::SHRINK, Gtk::SHRINK, 0, 0); controls_table.attach (gain_meter.get_gain_slider(), 0, 2, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 1, 0); mute_button.show (); solo_button.show (); drop_button.show (); - spill_button.show (); + automation_button.show (); gain_meter.get_gain_slider().show (); controls_ebox.set_name ("ControlMasterBaseUnselected"); @@ -136,6 +143,7 @@ VCATimeAxisView::mute_release (GdkEventButton*) void VCATimeAxisView::set_vca (boost::shared_ptr<VCA> v) { + StripableTimeAxisView::set_stripable (v); _vca = v; gain_meter.set_controls (boost::shared_ptr<Route>(), @@ -159,6 +167,13 @@ VCATimeAxisView::set_vca (boost::shared_ptr<VCA> v) set_height (preset_height (HeightNormal)); + if (automation_child (GainAutomation) == 0) { + create_automation_child (GainAutomation, false); + } + if (automation_child (MuteAutomation) == 0) { + create_automation_child (MuteAutomation, false); + } + update_vca_name (); set_button_names (); update_solo_display (); @@ -269,8 +284,15 @@ VCATimeAxisView::update_track_number_visibility () } bool -VCATimeAxisView::spill_release (GdkEventButton*) +VCATimeAxisView::automation_click (GdkEventButton* ev) { + if (ev->button != 1) { + return true; + } + + conditionally_add_to_selection (); + build_automation_action_menu (false); + Gtkmm2ext::anchored_menu_popup (automation_action_menu, &automation_button, "", 1, ev->time); return true; } @@ -323,3 +345,140 @@ VCATimeAxisView::set_marked_for_display (bool yn) } return false; } + +void +VCATimeAxisView::create_gain_automation_child (const Evoral::Parameter& param, bool show) +{ + boost::shared_ptr<AutomationControl> c = _vca->gain_control(); + if (!c) { + error << "VCA has no gain automation, unable to add automation track view." << endmsg; + return; + } + + gain_track.reset (new AutomationTimeAxisView (_session, + _vca, boost::shared_ptr<Automatable> (), c, param, + _editor, + *this, + false, + parent_canvas, + /*_route->amp()->describe_parameter(param)*/"Fader")); + + add_automation_child (Evoral::Parameter(GainAutomation), gain_track, show); +} + +void +VCATimeAxisView::create_mute_automation_child (const Evoral::Parameter& param, bool show) +{ + boost::shared_ptr<AutomationControl> c = _vca->mute_control(); + if (!c) { + error << "VCA has no mute automation, unable to add automation track view." << endmsg; + return; + } + + mute_track.reset (new AutomationTimeAxisView (_session, + _vca, boost::shared_ptr<Automatable> (), c, param, + _editor, + *this, + false, + parent_canvas, + /*_route->describe_parameter(param)*/ "Mute")); + + add_automation_child (Evoral::Parameter(MuteAutomation), mute_track, show); +} + +void +VCATimeAxisView::create_automation_child (const Evoral::Parameter& param, bool show) +{ + switch (param.type()) { + case GainAutomation: + create_gain_automation_child (param, show); + break; + case MuteAutomation: + create_mute_automation_child (param, show); + break; + default: + break; + } +} + +void +VCATimeAxisView::build_automation_action_menu (bool for_selection) +{ + using namespace Menu_Helpers; + _main_automation_menu_map.clear (); + delete automation_action_menu; + automation_action_menu = new Menu; + + MenuList& items = automation_action_menu->items(); + + automation_action_menu->set_name ("ArdourContextMenu"); + + items.push_back (MenuElem (_("Show All Automation"), + sigc::bind (sigc::mem_fun (*this, &VCATimeAxisView::show_all_automation), for_selection))); + + items.push_back (MenuElem (_("Show Existing Automation"), + sigc::bind (sigc::mem_fun (*this, &VCATimeAxisView::show_existing_automation), for_selection))); + + items.push_back (MenuElem (_("Hide All Automation"), + sigc::bind (sigc::mem_fun (*this, &VCATimeAxisView::hide_all_automation), for_selection))); + + if (gain_track) { + items.push_back (CheckMenuElem (_("Fader"), sigc::mem_fun (*this, &VCATimeAxisView::update_gain_track_visibility))); + gain_automation_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ()); + gain_automation_item->set_active (string_to<bool>(gain_track->gui_property ("visible"))); + + _main_automation_menu_map[Evoral::Parameter(GainAutomation)] = gain_automation_item; + } + + if (trim_track) { + items.push_back (CheckMenuElem (_("Trim"), sigc::mem_fun (*this, &VCATimeAxisView::update_trim_track_visibility))); + trim_automation_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ()); + trim_automation_item->set_active (string_to<bool>(trim_track->gui_property ("visible"))); + + _main_automation_menu_map[Evoral::Parameter(TrimAutomation)] = trim_automation_item; + } + + if (mute_track) { + items.push_back (CheckMenuElem (_("Mute"), sigc::mem_fun (*this, &VCATimeAxisView::update_mute_track_visibility))); + mute_automation_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ()); + mute_automation_item->set_active (string_to<bool>(mute_track->gui_property ("visible"))); + + _main_automation_menu_map[Evoral::Parameter(MuteAutomation)] = mute_automation_item; + } +} + +void +VCATimeAxisView::show_all_automation (bool apply_to_selection) +{ + assert (!apply_to_selection); // VCAs can't yet be selected + no_redraw = true; + + StripableTimeAxisView::show_all_automation (); + + no_redraw = false; + request_redraw (); +} + +void +VCATimeAxisView::show_existing_automation (bool apply_to_selection) +{ + assert (!apply_to_selection); // VCAs can't yet be selected + no_redraw = true; + + StripableTimeAxisView::show_existing_automation (); + + no_redraw = false; + request_redraw (); +} + +void +VCATimeAxisView::hide_all_automation (bool apply_to_selection) +{ + assert (!apply_to_selection); // VCAs can't yet be selected + no_redraw = true; + + StripableTimeAxisView::hide_all_automation (); + + no_redraw = false; + request_redraw (); +} diff --git a/gtk2_ardour/vca_time_axis.h b/gtk2_ardour/vca_time_axis.h index c40b1ab288..128c3c478a 100644 --- a/gtk2_ardour/vca_time_axis.h +++ b/gtk2_ardour/vca_time_axis.h @@ -21,7 +21,7 @@ #define __ardour_vca_time_axis_h__ #include "ardour_button.h" -#include "time_axis_view.h" +#include "stripable_time_axis.h" #include "gain_meter.h" namespace ArdourCanvas { @@ -33,7 +33,7 @@ namespace ARDOUR { class VCA; } -class VCATimeAxisView : public TimeAxisView +class VCATimeAxisView : public StripableTimeAxisView { public: VCATimeAxisView (PublicEditor&, ARDOUR::Session*, ArdourCanvas::Canvas& canvas); @@ -59,12 +59,24 @@ class VCATimeAxisView : public TimeAxisView boost::shared_ptr<ARDOUR::VCA> _vca; ArdourButton solo_button; ArdourButton mute_button; - ArdourButton spill_button; + ArdourButton automation_button; ArdourButton drop_button; ArdourButton number_label; GainMeterBase gain_meter; PBD::ScopedConnectionList vca_connections; + void create_gain_automation_child (const Evoral::Parameter &, bool); + void create_trim_automation_child (const Evoral::Parameter &, bool) {} + void create_mute_automation_child (const Evoral::Parameter &, bool); + + virtual void show_all_automation (bool apply_to_selection = false); + virtual void show_existing_automation (bool apply_to_selection = false); + virtual void hide_all_automation (bool apply_to_selection = false); + + void create_automation_child (const Evoral::Parameter& param, bool show); + virtual void build_automation_action_menu (bool); + Gtk::Menu* automation_action_menu; + void parameter_changed (std::string const& p); void vca_property_changed (PBD::PropertyChange const&); void update_vca_name (); @@ -74,9 +86,9 @@ class VCATimeAxisView : public TimeAxisView void update_track_number_visibility (); bool solo_release (GdkEventButton*); bool mute_release (GdkEventButton*); - bool spill_release (GdkEventButton*); + bool automation_click (GdkEventButton*); bool drop_release (GdkEventButton*); void self_delete (); }; -#endif /* __ardour_route_time_axis_h__ */ +#endif /* __ardour_vca_time_axis_h__ */ diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript index b925e2657b..a9d3205de1 100644 --- a/gtk2_ardour/wscript +++ b/gtk2_ardour/wscript @@ -247,6 +247,7 @@ gtk2_ardour_sources = [ 'streamview.cc', 'strip_silence_dialog.cc', 'stripable_colorpicker.cc', + 'stripable_time_axis.cc', 'sys_ex.cc', 'tape_region_view.cc', 'tempo_curve.cc', |