2 Copyright (C) 2000-2006 Paul Davis
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.
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.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #include <sigc++/bind.h>
30 #include "pbd/error.h"
31 #include "pbd/stl_delete.h"
32 #include "pbd/memento_command.h"
34 #include <gtkmm2ext/gtk_ui.h>
35 #include <gtkmm2ext/selector.h>
36 #include <gtkmm2ext/bindable_button.h>
37 #include <gtkmm2ext/utils.h>
39 #include "ardour/amp.h"
40 #include "ardour/audioplaylist.h"
41 #include "ardour/event_type_map.h"
42 #include "ardour/location.h"
43 #include "ardour/pannable.h"
44 #include "ardour/panner.h"
45 #include "ardour/panner_shell.h"
46 #include "ardour/playlist.h"
47 #include "ardour/processor.h"
48 #include "ardour/profile.h"
49 #include "ardour/session.h"
50 #include "ardour/session_playlist.h"
51 #include "ardour/utils.h"
53 #include "ardour_ui.h"
54 #include "audio_time_axis.h"
55 #include "automation_line.h"
56 #include "canvas_impl.h"
57 #include "crossfade_view.h"
59 #include "gui_thread.h"
60 #include "automation_time_axis.h"
62 #include "playlist_selector.h"
64 #include "public_editor.h"
65 #include "audio_region_view.h"
66 #include "simplerect.h"
67 #include "audio_streamview.h"
70 #include "ardour/audio_track.h"
75 using namespace ARDOUR
;
78 using namespace Editing
;
80 AudioTimeAxisView::AudioTimeAxisView (PublicEditor
& ed
, Session
* sess
, boost::shared_ptr
<Route
> rt
, Canvas
& canvas
)
82 , RouteTimeAxisView(ed
, sess
, rt
, canvas
)
84 // Make sure things are sane...
85 assert(!is_track() || is_audio_track());
87 subplugin_menu
.set_name ("ArdourContextMenu");
89 _view
= new AudioStreamView (*this);
91 ignore_toggle
= false;
93 mute_button
->set_active (false);
94 solo_button
->set_active (false);
96 if (is_audio_track()) {
97 controls_ebox
.set_name ("AudioTrackControlsBaseUnselected");
99 controls_ebox
.set_name ("AudioBusControlsBaseUnselected");
104 set_state (*xml_node
, Stateful::loading_state_version
);
106 /* if set_state above didn't create a gain automation child, we need to make one */
107 if (automation_child (GainAutomation
) == 0) {
108 create_automation_child (GainAutomation
, false);
111 if (_route
->panner()) {
112 _route
->panner_shell()->Changed
.connect (*this, invalidator (*this),
113 boost::bind (&AudioTimeAxisView::ensure_pan_views
, this, false), gui_context());
116 /* map current state of the route */
118 processors_changed (RouteProcessorChange ());
119 reset_processor_automation_curves ();
120 ensure_pan_views (false);
121 update_control_names ();
123 if (is_audio_track()) {
125 /* ask for notifications of any new RegionViews */
126 _view
->RegionViewAdded
.connect (sigc::mem_fun(*this, &AudioTimeAxisView::region_view_added
));
128 if (!_editor
.have_idled()) {
129 /* first idle will do what we need */
139 AudioTimeAxisView::~AudioTimeAxisView ()
144 AudioTimeAxisView::first_idle ()
151 AudioTimeAxisView::audio_view()
153 return dynamic_cast<AudioStreamView
*>(_view
);
157 AudioTimeAxisView::show_at (double y
, int& nth
, Gtk::VBox
*parent
)
160 xml_node
->add_property ("shown-editor", "yes");
162 return TimeAxisView::show_at (y
, nth
, parent
);
166 AudioTimeAxisView::hide ()
169 xml_node
->add_property ("shown-editor", "no");
171 TimeAxisView::hide ();
176 AudioTimeAxisView::append_extra_display_menu_items ()
178 using namespace Menu_Helpers
;
180 MenuList
& items
= display_menu
->items();
183 if (!Profile
->get_sae() && is_track ()) {
184 items
.push_back (MenuElem (_("Hide All Crossfades"), sigc::bind (sigc::mem_fun(*this, &AudioTimeAxisView::hide_all_xfades
), true)));
185 items
.push_back (MenuElem (_("Show All Crossfades"), sigc::bind (sigc::mem_fun(*this, &AudioTimeAxisView::show_all_xfades
), true)));
186 items
.push_back (SeparatorElem ());
191 AudioTimeAxisView::create_automation_child (const Evoral::Parameter
& param
, bool show
)
193 if (param
.type() == NullAutomation
) {
194 cerr
<< "WARNING: Attempt to create NullAutomation child, ignoring" << endl
;
198 AutomationTracks::iterator existing
= _automation_tracks
.find (param
);
200 if (existing
!= _automation_tracks
.end()) {
202 /* automation track created because we had existing data for
203 * the processor, but visibility may need to be controlled
204 * since it will have been set visible by default.
207 existing
->second
->set_visibility (show
);
210 _route
->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
216 if (param
.type() == GainAutomation
) {
218 create_gain_automation_child (param
, show
);
220 } else if (param
.type() == PanWidthAutomation
||
221 param
.type() == PanElevationAutomation
||
222 param
.type() == PanAzimuthAutomation
) {
225 ensure_pan_views (show
);
227 } else if (param
.type() == PluginAutomation
) {
229 /* handled elsewhere */
232 error
<< "AudioTimeAxisView: unknown automation child " << EventTypeMap::instance().to_symbol(param
) << endmsg
;
236 /** Ensure that we have the appropriate AutomationTimeAxisViews for the
237 * panners that we have.
239 * @param show true to show any new views that we create, otherwise false.
242 AudioTimeAxisView::ensure_pan_views (bool show
)
244 if (!_route
->panner()) {
248 set
<Evoral::Parameter
> params
= _route
->panner()->what_can_be_automated();
249 set
<Evoral::Parameter
>::iterator p
;
251 for (p
= params
.begin(); p
!= params
.end(); ++p
) {
252 boost::shared_ptr
<ARDOUR::AutomationControl
> pan_control
= _route
->pannable()->automation_control(*p
);
254 if (pan_control
->parameter().type() == NullAutomation
) {
255 error
<< "Pan control has NULL automation type!" << endmsg
;
259 if (automation_child (pan_control
->parameter ()).get () == 0) {
261 /* we don't already have an AutomationTimeAxisView for this parameter */
263 std::string
const name
= _route
->panner()->describe_parameter (pan_control
->parameter ());
265 boost::shared_ptr
<AutomationTimeAxisView
> t (
266 new AutomationTimeAxisView (_session
,
270 pan_control
->parameter (),
278 pan_tracks
.push_back (t
);
279 add_automation_child (*p
, t
, show
);
285 AudioTimeAxisView::update_gain_track_visibility ()
287 bool const showit
= gain_automation_item
->get_active();
289 if (showit
!= gain_track
->marked_for_display()) {
290 gain_track
->set_visibility (showit
);
292 /* now trigger a redisplay */
295 _route
->gui_changed (X_("visible_tracks"), (void *) 0); /* EMIT_SIGNAL */
301 AudioTimeAxisView::update_pan_track_visibility ()
303 bool const showit
= pan_automation_item
->get_active();
305 for (list
<boost::shared_ptr
<AutomationTimeAxisView
> >::iterator i
= pan_tracks
.begin(); i
!= pan_tracks
.end(); ++i
) {
307 if (showit
!= (*i
)->marked_for_display()) {
308 (*i
)->set_visibility (showit
);
309 /* now trigger a redisplay */
311 _route
->gui_changed (X_("visible_tracks"), (void *) 0); /* EMIT_SIGNAL */
318 AudioTimeAxisView::show_all_automation (bool apply_to_selection
)
320 if (apply_to_selection
) {
321 _editor
.get_selection().tracks
.foreach_audio_time_axis (boost::bind (&AudioTimeAxisView::show_all_automation
, _1
, false));
326 RouteTimeAxisView::show_all_automation ();
330 _route
->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
335 AudioTimeAxisView::show_existing_automation (bool apply_to_selection
)
337 if (apply_to_selection
) {
338 _editor
.get_selection().tracks
.foreach_audio_time_axis (boost::bind (&AudioTimeAxisView::show_existing_automation
, _1
, false));
342 RouteTimeAxisView::show_existing_automation ();
346 _route
->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
351 AudioTimeAxisView::hide_all_automation (bool apply_to_selection
)
353 if (apply_to_selection
) {
354 _editor
.get_selection().tracks
.foreach_audio_time_axis (boost::bind (&AudioTimeAxisView::hide_all_automation
, _1
, false));
358 RouteTimeAxisView::hide_all_automation();
361 _route
->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
366 AudioTimeAxisView::show_all_xfades (bool apply_to_selection
)
368 if (apply_to_selection
) {
369 _editor
.get_selection().tracks
.foreach_audio_time_axis (boost::bind (&AudioTimeAxisView::show_all_xfades
, _1
, false));
371 AudioStreamView
* asv
= audio_view ();
373 asv
->show_all_xfades ();
379 AudioTimeAxisView::hide_all_xfades (bool apply_to_selection
)
381 if (apply_to_selection
) {
382 _editor
.get_selection().tracks
.foreach_audio_time_axis (boost::bind (&AudioTimeAxisView::hide_all_xfades
, _1
, false));
384 AudioStreamView
* asv
= audio_view ();
386 asv
->hide_all_xfades ();
392 AudioTimeAxisView::hide_dependent_views (TimeAxisViewItem
& tavi
)
394 AudioStreamView
* asv
= audio_view();
397 if (asv
&& (rv
= dynamic_cast<AudioRegionView
*>(&tavi
)) != 0) {
398 asv
->hide_xfades_involving (*rv
);
403 AudioTimeAxisView::reveal_dependent_views (TimeAxisViewItem
& tavi
)
405 AudioStreamView
* asv
= audio_view();
408 if (asv
&& (rv
= dynamic_cast<AudioRegionView
*>(&tavi
)) != 0) {
409 asv
->reveal_xfades_involving (*rv
);
414 AudioTimeAxisView::route_active_changed ()
416 update_control_names ();
421 * Set up the names of the controls so that they are coloured
422 * correctly depending on whether this route is inactive or
427 AudioTimeAxisView::update_control_names ()
429 if (is_audio_track()) {
430 if (_route
->active()) {
431 controls_base_selected_name
= "AudioTrackControlsBaseSelected";
432 controls_base_unselected_name
= "AudioTrackControlsBaseUnselected";
434 controls_base_selected_name
= "AudioTrackControlsBaseInactiveSelected";
435 controls_base_unselected_name
= "AudioTrackControlsBaseInactiveUnselected";
438 if (_route
->active()) {
439 controls_base_selected_name
= "BusControlsBaseSelected";
440 controls_base_unselected_name
= "BusControlsBaseUnselected";
442 controls_base_selected_name
= "BusControlsBaseInactiveSelected";
443 controls_base_unselected_name
= "BusControlsBaseInactiveUnselected";
447 if (get_selected()) {
448 controls_ebox
.set_name (controls_base_selected_name
);
450 controls_ebox
.set_name (controls_base_unselected_name
);
455 AudioTimeAxisView::build_automation_action_menu (bool for_selection
)
457 using namespace Menu_Helpers
;
459 RouteTimeAxisView::build_automation_action_menu (for_selection
);
461 MenuList
& automation_items
= automation_action_menu
->items ();
463 automation_items
.push_back (CheckMenuElem (_("Fader"), sigc::mem_fun (*this, &AudioTimeAxisView::update_gain_track_visibility
)));
464 gain_automation_item
= dynamic_cast<CheckMenuItem
*> (&automation_items
.back ());
465 gain_automation_item
->set_active (gain_track
->marked_for_display () && (!for_selection
|| _editor
.get_selection().tracks
.size() == 1));
467 _main_automation_menu_map
[Evoral::Parameter(GainAutomation
)] = gain_automation_item
;
469 automation_items
.push_back (CheckMenuElem (_("Pan"), sigc::mem_fun (*this, &AudioTimeAxisView::update_pan_track_visibility
)));
470 pan_automation_item
= dynamic_cast<CheckMenuItem
*> (&automation_items
.back ());
471 pan_automation_item
->set_active (pan_tracks
.front()->marked_for_display () && (!for_selection
|| _editor
.get_selection().tracks
.size() == 1));
473 set
<Evoral::Parameter
> const & params
= _route
->pannable()->what_can_be_automated ();
474 for (set
<Evoral::Parameter
>::iterator p
= params
.begin(); p
!= params
.end(); ++p
) {
475 _main_automation_menu_map
[*p
] = pan_automation_item
;
480 AudioTimeAxisView::enter_internal_edit_mode ()
483 audio_view()->enter_internal_edit_mode ();
488 AudioTimeAxisView::leave_internal_edit_mode ()
491 audio_view()->leave_internal_edit_mode ();