1 /*
2 * Copyright (C) 2017 Robin Gareus <robin@gareus.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 #include <gtkmm/menu.h>
20 #include <gtkmm/menuitem.h>
21
22 #include "ardour/parameter_descriptor.h"
23 #include "ardour/parameter_types.h"
24 #include "ardour/stripable.h"
25
26 #include "public_editor.h"
27 #include "stripable_time_axis.h"
28 #include "automation_line.h"
29
30 #include "pbd/i18n.h"
31
32 using namespace PBD;
33 using namespace ARDOUR;
34 using namespace Gtk;
35
StripableTimeAxisView(PublicEditor & ed,ARDOUR::Session * s,ArdourCanvas::Canvas & canvas)36 StripableTimeAxisView::StripableTimeAxisView (PublicEditor& ed, ARDOUR::Session* s, ArdourCanvas::Canvas& canvas)
37 : TimeAxisView(s, ed, (TimeAxisView*) 0, canvas)
38 , gain_automation_item(NULL)
39 , trim_automation_item(NULL)
40 , mute_automation_item(NULL)
41 , parent_canvas (canvas)
42 , no_redraw (false)
43 {
44 }
45
~StripableTimeAxisView()46 StripableTimeAxisView::~StripableTimeAxisView ()
47 {
48 }
49
50 void
set_stripable(boost::shared_ptr<ARDOUR::Stripable> s)51 StripableTimeAxisView::set_stripable (boost::shared_ptr<ARDOUR::Stripable> s)
52 {
53 _stripable = s;
54 _editor.ZoomChanged.connect (sigc::mem_fun(*this, &StripableTimeAxisView::reset_samples_per_pixel));
55 }
56
57 void
reset_samples_per_pixel()58 StripableTimeAxisView::reset_samples_per_pixel ()
59 {
60 set_samples_per_pixel (_editor.get_current_zoom());
61 }
62
63 void
set_samples_per_pixel(double fpp)64 StripableTimeAxisView::set_samples_per_pixel (double fpp)
65 {
66 TimeAxisView::set_samples_per_pixel (fpp);
67 }
68
69
70 void
add_automation_child(Evoral::Parameter param,boost::shared_ptr<AutomationTimeAxisView> track,bool show)71 StripableTimeAxisView::add_automation_child (Evoral::Parameter param, boost::shared_ptr<AutomationTimeAxisView> track, bool show)
72 {
73 using namespace Menu_Helpers;
74
75 add_child (track);
76
77 if (param.type() != PluginAutomation) {
78 /* PluginAutomation is handled by
79 * - RouteTimeAxisView::processor_automation_track_hidden
80 * - RouteTimeAxisView::processor_automation
81 */
82 track->Hiding.connect (sigc::bind (sigc::mem_fun (*this, &StripableTimeAxisView::automation_track_hidden), param));
83 _automation_tracks[param] = track;
84 }
85
86 /* existing state overrides "show" argument */
87 bool visible;
88 if (track->get_gui_property ("visible", visible)) {
89 show = visible;
90 }
91
92 /* this might or might not change the visibility status, so don't rely on it */
93 track->set_marked_for_display (show);
94
95 if (show && !no_redraw) {
96 request_redraw ();
97 }
98 }
99
100 void
update_gain_track_visibility()101 StripableTimeAxisView::update_gain_track_visibility ()
102 {
103 bool const showit = gain_automation_item->get_active();
104
105 bool visible;
106 if (gain_track->get_gui_property ("visible", visible) && visible != showit) {
107 gain_track->set_marked_for_display (showit);
108
109 /* now trigger a redisplay */
110
111 if (!no_redraw) {
112 _stripable->gui_changed (X_("visible_tracks"), (void *) 0); /* EMIT_SIGNAL */
113 }
114 }
115 }
116
117 void
update_trim_track_visibility()118 StripableTimeAxisView::update_trim_track_visibility ()
119 {
120 bool const showit = trim_automation_item->get_active();
121
122 bool visible;
123 if (trim_track->get_gui_property ("visible", visible) && visible != showit) {
124 trim_track->set_marked_for_display (showit);
125
126 /* now trigger a redisplay */
127
128 if (!no_redraw) {
129 _stripable->gui_changed (X_("visible_tracks"), (void *) 0); /* EMIT_SIGNAL */
130 }
131 }
132 }
133
134 void
update_mute_track_visibility()135 StripableTimeAxisView::update_mute_track_visibility ()
136 {
137 bool const showit = mute_automation_item->get_active();
138
139 bool visible;
140 if (mute_track->get_gui_property ("visible", visible) && visible != showit) {
141 mute_track->set_marked_for_display (showit);
142
143 /* now trigger a redisplay */
144
145 if (!no_redraw) {
146 _stripable->gui_changed (X_("visible_tracks"), (void *) 0); /* EMIT_SIGNAL */
147 }
148 }
149 }
150
151 Gtk::CheckMenuItem*
automation_child_menu_item(Evoral::Parameter param)152 StripableTimeAxisView::automation_child_menu_item (Evoral::Parameter param)
153 {
154 assert (param.type() != PluginAutomation);
155 ParameterMenuMap::iterator i = _main_automation_menu_map.find (param);
156 if (i != _main_automation_menu_map.end()) {
157 return i->second;
158 }
159
160 return 0;
161 }
162
163 void
automation_track_hidden(Evoral::Parameter param)164 StripableTimeAxisView::automation_track_hidden (Evoral::Parameter param)
165 {
166 boost::shared_ptr<AutomationTimeAxisView> track = automation_child (param);
167
168 if (!track) {
169 return;
170 }
171
172 Gtk::CheckMenuItem* menu = automation_child_menu_item (param);
173
174 if (menu && !_hidden && menu->get_active()) {
175 menu->set_active (false);
176 }
177
178 if (_stripable && !no_redraw) {
179 request_redraw ();
180 }
181 }
182
183 boost::shared_ptr<AutomationTimeAxisView>
automation_child(Evoral::Parameter param,PBD::ID)184 StripableTimeAxisView::automation_child(Evoral::Parameter param, PBD::ID)
185 {
186 assert (param.type() != PluginAutomation);
187 AutomationTracks::iterator i = _automation_tracks.find(param);
188 if (i != _automation_tracks.end()) {
189 return i->second;
190 } else {
191 return boost::shared_ptr<AutomationTimeAxisView>();
192 }
193 }
194
195 boost::shared_ptr<AutomationLine>
automation_child_by_alist_id(PBD::ID alist_id)196 StripableTimeAxisView::automation_child_by_alist_id (PBD::ID alist_id)
197 {
198 for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) {
199 boost::shared_ptr<AutomationTimeAxisView> atv (i->second);
200 std::list<boost::shared_ptr<AutomationLine> > lines = atv->lines();
201 for (std::list<boost::shared_ptr<AutomationLine> >::const_iterator li = lines.begin(); li != lines.end(); ++li) {
202 if ((*li)->the_list()->id() == alist_id) {
203 return *li;
204 }
205 }
206 }
207 return boost::shared_ptr<AutomationLine> ();
208 }
209
210 void
request_redraw()211 StripableTimeAxisView::request_redraw ()
212 {
213 if (_stripable) {
214 _stripable->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
215 }
216 }
217
218 void
show_all_automation(bool apply_to_selection)219 StripableTimeAxisView::show_all_automation (bool apply_to_selection)
220 {
221 /* this protected member should not be called directly */
222 assert (!apply_to_selection);
223 assert (no_redraw);
224
225 for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) {
226 i->second->set_marked_for_display (true);
227
228 Gtk::CheckMenuItem* menu = automation_child_menu_item (i->first);
229
230 if (menu) {
231 menu->set_active(true);
232 }
233 }
234 }
235
236 void
show_existing_automation(bool apply_to_selection)237 StripableTimeAxisView::show_existing_automation (bool apply_to_selection)
238 {
239 /* this protected member should not be called directly */
240 assert (!apply_to_selection);
241 assert (no_redraw);
242
243 for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) {
244 if (i->second->has_automation()) {
245 i->second->set_marked_for_display (true);
246
247 Gtk::CheckMenuItem* menu = automation_child_menu_item (i->first);
248 if (menu) {
249 menu->set_active(true);
250 }
251 }
252 }
253 }
254
255 void
hide_all_automation(bool apply_to_selection)256 StripableTimeAxisView::hide_all_automation (bool apply_to_selection)
257 {
258 /* this protected member should not be called directly */
259 assert (!apply_to_selection);
260 assert (no_redraw);
261
262 for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) {
263 i->second->set_marked_for_display (false);
264
265 Gtk::CheckMenuItem* menu = automation_child_menu_item (i->first);
266
267 if (menu) {
268 menu->set_active (false);
269 }
270 }
271 }
272