ardour
automation_streamview.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2001-2007 Paul Davis
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
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18 
19 #include <cmath>
20 #include <list>
21 #include <utility>
22 
23 #include <gtkmm.h>
24 
25 #include "gtkmm2ext/gtk_ui.h"
26 
27 #include "pbd/compose.h"
28 #include "canvas/debug.h"
29 
30 #include "ardour/midi_region.h"
31 #include "ardour/midi_source.h"
32 
33 #include "ardour_ui.h"
34 #include "automation_region_view.h"
35 #include "automation_streamview.h"
36 #include "automation_time_axis.h"
37 #include "global_signals.h"
38 #include "gui_thread.h"
39 #include "public_editor.h"
40 #include "region_selection.h"
41 #include "region_view.h"
42 #include "rgb_macros.h"
43 #include "selection.h"
44 
45 #include "i18n.h"
46 
47 using namespace std;
48 using namespace ARDOUR;
49 using namespace ARDOUR_UI_UTILS;
50 using namespace PBD;
51 using namespace Editing;
52 
54  : StreamView (*dynamic_cast<RouteTimeAxisView*>(tv.get_parent()),
55  tv.canvas_display())
56  , _automation_view(tv)
57  , _pending_automation_state (Off)
58 {
59  CANVAS_DEBUG_NAME (_canvas_group, string_compose ("SV canvas group auto %1", tv.name()));
60  CANVAS_DEBUG_NAME (canvas_rect, string_compose ("SV canvas rectangle auto %1", tv.name()));
61 
62  color_handler ();
63 
64  ColorsChanged.connect(sigc::mem_fun(*this, &AutomationStreamView::color_handler));
65 }
66 
68 {
69 }
70 
71 
73 AutomationStreamView::add_region_view_internal (boost::shared_ptr<Region> region, bool wait_for_data, bool /*recording*/)
74 {
75  if (!region) {
76  return 0;
77  }
78 
79  if (wait_for_data) {
81  if (mr) {
82  Source::Lock lock(mr->midi_source()->mutex());
83  mr->midi_source()->load_model(lock);
84  }
85  }
86 
88  region->control (_automation_view.parameter(), true)
89  );
90 
92  if (control) {
94  if (control->list() && !list) {
95  error << _("unable to display automation region for control without list") << endmsg;
96  return 0;
97  }
98  }
99 
100  AutomationRegionView *region_view;
101  std::list<RegionView *>::iterator i;
102 
103  for (i = region_views.begin(); i != region_views.end(); ++i) {
104  if ((*i)->region() == region) {
105 
106  /* great. we already have an AutomationRegionView for this Region. use it again. */
107  AutomationRegionView* arv = dynamic_cast<AutomationRegionView*>(*i);;
108 
109  if (arv->line()) {
110  arv->line()->set_list (list);
111  }
112  (*i)->set_valid (true);
113  (*i)->enable_display (wait_for_data);
114  display_region(arv);
115 
116  return 0;
117  }
118  }
119 
120  region_view = new AutomationRegionView (
122  _automation_view.parameter (), list,
124  );
125 
126  region_view->init (false);
127  region_views.push_front (region_view);
128 
129  /* follow global waveform setting */
130 
131  if (wait_for_data) {
132  region_view->enable_display(true);
133  // region_view->midi_region()->midi_source(0)->load_model();
134  }
135 
136  display_region (region_view);
137 
138  /* catch regionview going away */
139  region->DropReferences.connect (*this, invalidator (*this), boost::bind (&AutomationStreamView::remove_region_view, this, boost::weak_ptr<Region>(region)), gui_context());
140 
141  /* setup automation state for this region */
142  boost::shared_ptr<AutomationLine> line = region_view->line ();
143  if (line && line->the_list()) {
145  }
146 
147  RegionViewAdded (region_view);
148 
149  return region_view;
150 }
151 
152 void
154 {
155  region_view->line().reset();
156 }
157 
158 void
160 {
161  /* Setting the automation state for this view sets the state of all regions' lists to the same thing */
162 
163  if (region_views.empty()) {
165  } else {
166  list<boost::shared_ptr<AutomationLine> > lines = get_lines ();
167 
168  for (list<boost::shared_ptr<AutomationLine> >::iterator i = lines.begin(); i != lines.end(); ++i) {
169  if ((*i)->the_list()) {
170  (*i)->the_list()->set_automation_state (state);
171  }
172  }
173  }
174 }
175 
176 void
178 {
179  // Flag region views as invalid and disable drawing
180  for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
181  (*i)->set_valid (false);
182  (*i)->enable_display(false);
183  }
184 
185  // Add and display region views, and flag them as valid
186  if (_trackview.is_track()) {
188  sigc::hide_return (sigc::mem_fun (*this, &StreamView::add_region_view))
189  );
190  }
191 
192  // Stack regions by layer, and remove invalid regions
193  layer_regions();
194 }
195 
196 
197 void
199 {
200 }
201 
202 void
204 {
205  if (_trackview.is_midi_track()) {
206  canvas_rect->set_fill_color (ARDOUR_UI::config()->color_mod ("midi track base", "midi track base"));
207  } else {
208  canvas_rect->set_fill_color (ARDOUR_UI::config()->color ("midi bus base"));
209  }
210 }
211 
212 AutoState
214 {
215  if (region_views.empty()) {
217  }
218 
220  if (!line || !line->the_list()) {
221  return Off;
222  }
223 
224  return line->the_list()->automation_state ();
225 }
226 
227 bool
229 {
230  list<boost::shared_ptr<AutomationLine> > lines = get_lines ();
231 
232  for (list<boost::shared_ptr<AutomationLine> >::iterator i = lines.begin(); i != lines.end(); ++i) {
233  if ((*i)->npoints() > 0) {
234  return true;
235  }
236  }
237 
238  return false;
239 }
240 
244 void
245 AutomationStreamView::set_interpolation (AutomationList::InterpolationStyle s)
246 {
247  list<boost::shared_ptr<AutomationLine> > lines = get_lines ();
248 
249  for (list<boost::shared_ptr<AutomationLine> >::iterator i = lines.begin(); i != lines.end(); ++i) {
250  (*i)->the_list()->set_interpolation (s);
251  }
252 }
253 
254 AutomationList::InterpolationStyle
256 {
257  if (region_views.empty()) {
258  return AutomationList::Linear;
259  }
260 
261  AutomationRegionView* v = dynamic_cast<AutomationRegionView*> (region_views.front());
262  if (v) {
263  return v->line()->the_list()->interpolation ();
264  }
265  return AutomationList::Linear;
266 }
267 
269 void
271 {
272  list<boost::shared_ptr<AutomationLine> > lines = get_lines ();
273 
274  for (list<boost::shared_ptr<AutomationLine> >::iterator i = lines.begin(); i != lines.end(); ++i) {
275  (*i)->clear ();
276  }
277 }
278 
286 void
287 AutomationStreamView::get_selectables (framepos_t start, framepos_t end, double botfrac, double topfrac, list<Selectable*>& results, bool /*within*/)
288 {
289  for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
290  AutomationRegionView* arv = dynamic_cast<AutomationRegionView*> (*i);
291  if (arv) {
292  arv->line()->get_selectables (start, end, botfrac, topfrac, results);
293  }
294  }
295 }
296 
297 void
299 {
300  list<boost::shared_ptr<AutomationLine> > lines = get_lines ();
301 
302  for (list<boost::shared_ptr<AutomationLine> >::iterator i = lines.begin(); i != lines.end(); ++i) {
303  (*i)->set_selected_points (ps);
304  }
305 }
306 
307 list<boost::shared_ptr<AutomationLine> >
309 {
310  list<boost::shared_ptr<AutomationLine> > lines;
311 
312  for (list<RegionView*>::const_iterator i = region_views.begin(); i != region_views.end(); ++i) {
313  AutomationRegionView* arv = dynamic_cast<AutomationRegionView*> (*i);
314  if (arv) {
315  lines.push_back (arv->line());
316  }
317  }
318 
319  return lines;
320 }
321 
322 bool
324  unsigned paste_count,
325  float times,
327 {
328  /* XXX: not sure how best to pick this; for now, just use the last region which starts before pos */
329 
330  if (region_views.empty()) {
331  return false;
332  }
333 
335 
336  list<RegionView*>::const_iterator prev = region_views.begin ();
337 
338  for (list<RegionView*>::const_iterator i = region_views.begin(); i != region_views.end(); ++i) {
339  if ((*i)->region()->position() > pos) {
340  break;
341  }
342  prev = i;
343  }
344 
345  boost::shared_ptr<Region> r = (*prev)->region ();
346 
347  /* If *prev doesn't cover pos, it's no good */
348  if (r->position() > pos || ((r->position() + r->length()) < pos)) {
349  return false;
350  }
351 
352  AutomationRegionView* arv = dynamic_cast<AutomationRegionView*> (*prev);
353  return arv ? arv->paste(pos, paste_count, times, alist) : false;
354 }
void set_automation_state(AutoState)
void set_selected_points(PointSelection &)
void layer_regions()
Definition: streamview.cc:224
PBD::Signal0< void > DropReferences
Definition: destructible.h:34
bool is_midi_track() const
Definition: route_ui.cc:1756
Glib::Threads::Mutex::Lock Lock
Definition: source.h:54
bool paste(framepos_t pos, unsigned paste_count, float times, boost::shared_ptr< const ARDOUR::AutomationList > slist)
sigc::signal< void, RegionView * > RegionViewAdded
Definition: streamview.h:122
double _samples_per_pixel
Definition: streamview.h:158
ArdourCanvas::Container * _canvas_group
Definition: streamview.h:152
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r)
Definition: shared_ptr.hpp:396
boost::shared_ptr< ARDOUR::AutomationList > the_list() const
AutomationTimeAxisView & _automation_view
Definition: Beats.hpp:239
LIBPBD_API Transmitter error
std::string name() const
std::ostream & endmsg(std::ostream &ostr)
Definition: transmitter.h:71
virtual void remove_region_view(boost::weak_ptr< ARDOUR::Region >)
Definition: streamview.cc:180
LIBARDOUR_API PBD::PropertyDescriptor< framepos_t > start
Definition: region.cc:63
#define invalidator(x)
Definition: gui_thread.h:40
boost::shared_ptr< AutomationLine > line()
ARDOUR::AutoState automation_state() const
#define _(Text)
Definition: i18n.h:11
virtual void enable_display(bool yn)
Definition: region_view.h:97
bool paste(framepos_t pos, unsigned paste_count, float times, boost::shared_ptr< ARDOUR::AutomationList > list)
Evoral::Parameter parameter() const
AutoState automation_state() const
Definition: amp.h:29
RegionView * add_region_view_internal(boost::shared_ptr< ARDOUR::Region >, bool wait_for_data, bool recording=false)
void get_selectables(ARDOUR::framepos_t, ARDOUR::framepos_t, double, double, std::list< Selectable * > &, bool within=false)
boost::shared_ptr< ARDOUR::Track > track() const
Definition: route_ui.cc:1738
AutomationStreamView(AutomationTimeAxisView &tv)
#define gui_context()
Definition: gui_thread.h:36
ARDOUR::AutoState _pending_automation_state
boost::shared_ptr< Playlist > playlist()
Definition: track.cc:590
virtual boost::shared_ptr< Evoral::Control > control(const Evoral::Parameter &id, bool create=false)=0
int64_t framepos_t
Definition: types.h:66
void foreach_region(boost::function< void(boost::shared_ptr< Region >)>)
Definition: playlist.cc:2833
RouteTimeAxisView & _trackview
Definition: streamview.h:151
RegionViewList region_views
Definition: streamview.h:156
bool is_track() const
Definition: route_ui.cc:1732
framepos_t position() const
Definition: region.h:112
ArdourCanvas::Rectangle * canvas_rect
Definition: streamview.h:153
void set_interpolation(ARDOUR::AutomationList::InterpolationStyle)
std::list< boost::shared_ptr< AutomationLine > > get_lines() const
InterpolationStyle interpolation() const
void get_selectables(ARDOUR::framepos_t, ARDOUR::framepos_t, double, double, std::list< Selectable * > &)
void display_region(AutomationRegionView *region_view)
ARDOUR::AutomationList::InterpolationStyle interpolation() const
boost::shared_ptr< ControlList > list()
Definition: Control.hpp:66
static UIConfiguration * config()
Definition: ardour_ui.h:188
void add_region_view(boost::weak_ptr< ARDOUR::Region >)
Definition: streamview.cc:165
sigc::signal< void > ColorsChanged
Definition: debug.h:30
framecnt_t length() const
Definition: region.h:114
boost::shared_ptr< MidiSource > midi_source(uint32_t n=0) const
Definition: midi_region.cc:390
Off
Definition: widget_state.h:13
void set_list(boost::shared_ptr< ARDOUR::AutomationList > list)
void set_automation_state(ARDOUR::AutoState state)
uint32_t region_color
Contained region color.
Definition: streamview.h:166
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:208
AutoState
Definition: types.h:145
LIBARDOUR_API PBD::PropertyDescriptor< bool > color
Definition: route_group.cc:50