2 Copyright (C) 2001-2007 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.
25 #include <gtkmm2ext/gtk_ui.h>
27 #include "ardour/midi_playlist.h"
28 #include "ardour/midi_region.h"
29 #include "ardour/midi_source.h"
30 #include "ardour/midi_diskstream.h"
31 #include "ardour/midi_track.h"
32 #include "ardour/smf_source.h"
33 #include "ardour/region_factory.h"
35 #include "automation_streamview.h"
36 #include "region_view.h"
37 #include "automation_region_view.h"
38 #include "automation_time_axis.h"
39 #include "canvas-simplerect.h"
40 #include "region_selection.h"
41 #include "selection.h"
42 #include "public_editor.h"
43 #include "ardour_ui.h"
44 #include "rgb_macros.h"
45 #include "gui_thread.h"
47 #include "simplerect.h"
48 #include "simpleline.h"
51 using namespace ARDOUR
;
53 using namespace Editing
;
55 AutomationStreamView::AutomationStreamView (AutomationTimeAxisView
& tv
)
56 : StreamView (*dynamic_cast<RouteTimeAxisView
*>(tv
.get_parent()),
57 new ArdourCanvas::Group(*tv
.canvas_background()),
58 new ArdourCanvas::Group(*tv
.canvas_display()))
59 , _controller(tv
.controller())
60 , _automation_view(tv
)
61 , _pending_automation_state (Off
)
63 //canvas_rect->property_fill_color_rgba() = stream_base_color;
64 canvas_rect
->property_outline_color_rgba() = RGBA_BLACK
;
67 AutomationStreamView::~AutomationStreamView ()
73 AutomationStreamView::add_region_view_internal (boost::shared_ptr
<Region
> region
, bool wfd
, bool /*recording*/)
76 cerr
<< "No region" << endl
;
81 boost::shared_ptr
<MidiRegion
> mr
= boost::dynamic_pointer_cast
<MidiRegion
>(region
);
83 mr
->midi_source()->load_model();
86 const boost::shared_ptr
<AutomationControl
> control
= boost::dynamic_pointer_cast
<AutomationControl
> (
87 region
->control (_controller
->controllable()->parameter(), true)
90 boost::shared_ptr
<AutomationList
> list
;
92 list
= boost::dynamic_pointer_cast
<AutomationList
>(control
->list());
93 assert(!control
->list() || list
);
96 AutomationRegionView
*region_view
;
97 std::list
<RegionView
*>::iterator i
;
99 for (i
= region_views
.begin(); i
!= region_views
.end(); ++i
) {
100 if ((*i
)->region() == region
) {
102 /* great. we already have an AutomationRegionView for this Region. use it again. */
103 AutomationRegionView
* arv
= dynamic_cast<AutomationRegionView
*>(*i
);;
106 arv
->line()->set_list (list
);
107 (*i
)->set_valid (true);
108 (*i
)->enable_display(wfd
);
115 region_view
= new AutomationRegionView (_canvas_group
, _automation_view
, region
,
116 _controller
->controllable()->parameter(), list
,
117 _samples_per_unit
, region_color
);
119 region_view
->init (region_color
, false);
120 region_views
.push_front (region_view
);
122 /* follow global waveform setting */
125 region_view
->enable_display(true);
126 //region_view->midi_region()->midi_source(0)->load_model();
129 display_region(region_view
);
131 /* catch regionview going away */
132 region
->DropReferences
.connect (*this, invalidator (*this), boost::bind (&AutomationStreamView::remove_region_view
, this, boost::weak_ptr
<Region
>(region
)), gui_context());
134 /* setup automation state for this region */
135 boost::shared_ptr
<AutomationLine
> line
= region_view
->line ();
136 if (line
&& line
->the_list()) {
137 line
->the_list()->set_automation_state (automation_state ());
140 RegionViewAdded (region_view
);
146 AutomationStreamView::display_region(AutomationRegionView
* region_view
)
148 region_view
->line().reset();
152 AutomationStreamView::set_automation_state (AutoState state
)
154 /* XXX: not sure if this is right, but for now the automation state is basically held by
155 the regions' AutomationLists. Each region is always set to have the same AutoState.
158 if (region_views
.empty()) {
159 _pending_automation_state
= state
;
161 for (std::list
<RegionView
*>::iterator i
= region_views
.begin(); i
!= region_views
.end(); ++i
) {
162 boost::shared_ptr
<AutomationLine
> line
= dynamic_cast<AutomationRegionView
*>(*i
)->line();
163 if (line
&& line
->the_list()) {
164 line
->the_list()->set_automation_state (state
);
171 AutomationStreamView::redisplay_track ()
173 list
<RegionView
*>::iterator i
, tmp
;
175 // Flag region views as invalid and disable drawing
176 for (i
= region_views
.begin(); i
!= region_views
.end(); ++i
) {
177 (*i
)->set_valid (false);
178 (*i
)->enable_display(false);
181 // Add and display region views, and flag them as valid
182 if (_trackview
.is_track()) {
183 _trackview
.track()->playlist()->foreach_region (
184 sigc::hide_return (sigc::mem_fun (*this, &StreamView::add_region_view
))
188 // Stack regions by layer, and remove invalid regions
194 AutomationStreamView::setup_rec_box ()
199 AutomationStreamView::color_handler ()
201 /*if (_trackview.is_midi_track()) {
202 canvas_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_MidiTrackBase.get();
205 if (!_trackview.is_midi_track()) {
206 canvas_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_MidiBusBase.get();;
211 AutomationStreamView::automation_state () const
213 if (region_views
.empty()) {
214 return _pending_automation_state
;
217 boost::shared_ptr
<AutomationLine
> line
= ((AutomationRegionView
*) region_views
.front())->line ();
218 if (!line
|| !line
->the_list()) {
222 return line
->the_list()->automation_state ();
226 AutomationStreamView::has_automation () const
228 list
<RegionView
*>::const_iterator i
= region_views
.begin ();
229 while (i
!= region_views
.end()) {
230 AutomationRegionView
* rv
= static_cast<AutomationRegionView
*> (*i
);
231 if (rv
->line() && rv
->line()->npoints() > 0) {
240 /** Our parent AutomationTimeAxisView calls this when the user requests a particular
241 * InterpolationStyle; tell the AutomationLists in our regions.
244 AutomationStreamView::set_interpolation (AutomationList::InterpolationStyle s
)
246 for (list
<RegionView
*>::const_iterator i
= region_views
.begin(); i
!= region_views
.end(); ++i
) {
247 AutomationRegionView
* arv
= dynamic_cast<AutomationRegionView
*> (*i
);
249 arv
->line()->the_list()->set_interpolation (s
);
253 AutomationList::InterpolationStyle
254 AutomationStreamView::interpolation () const
256 if (region_views
.empty()) {
257 return AutomationList::Linear
;
260 AutomationRegionView
* v
= dynamic_cast<AutomationRegionView
*> (region_views
.front());
263 return v
->line()->the_list()->interpolation ();