ardour
audio_streamview.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2001, 2006 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 <cassert>
21 #include <utility>
22 
23 #include <gtkmm.h>
24 
25 #include <gtkmm2ext/gtk_ui.h>
26 
27 #include "pbd/stacktrace.h"
28 
29 #include "ardour/audioregion.h"
30 #include "ardour/audiofilesource.h"
31 #include "ardour/audio_track.h"
32 #include "ardour/region_factory.h"
33 #include "ardour/profile.h"
35 #include "ardour/session.h"
36 
37 #include "canvas/rectangle.h"
38 
39 #include "audio_streamview.h"
40 #include "audio_region_view.h"
41 #include "tape_region_view.h"
42 #include "audio_time_axis.h"
43 #include "region_selection.h"
44 #include "selection.h"
45 #include "public_editor.h"
46 #include "ardour_ui.h"
47 #include "rgb_macros.h"
48 #include "gui_thread.h"
49 
50 #include "i18n.h"
51 
52 using namespace std;
53 using namespace ARDOUR;
54 using namespace PBD;
55 using namespace Editing;
56 
58  : StreamView (tv)
59 {
60  color_handler ();
62 }
63 
64 int
66 {
67  RegionViewList::iterator i;
68 
69  if (app < 1.0) {
70  return -1;
71  }
72 
74 
75  for (i = region_views.begin(); i != region_views.end(); ++i) {
76  AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
77  if (arv)
78  arv->set_amplitude_above_axis (app);
79  }
80 
81  return 0;
82 }
83 
85 AudioStreamView::create_region_view (boost::shared_ptr<Region> r, bool wait_for_waves, bool recording)
86 {
87  AudioRegionView *region_view = 0;
89 
90  if (region == 0) {
91  return 0;
92  }
93 
94  switch (_trackview.audio_track()->mode()) {
95 
96  case NonLayered:
97  case Normal:
98  if (recording) {
99  region_view = new AudioRegionView (_canvas_group, _trackview, region,
105  } else {
106  region_view = new AudioRegionView (_canvas_group, _trackview, region,
108  }
109  break;
110  case Destructive:
111  region_view = new TapeAudioRegionView (_canvas_group, _trackview, region,
113  break;
114  default:
115  fatal << string_compose (_("programming error: %1"), "illegal track mode in ::create_region_view()") << endmsg;
116  abort(); /*NOTREACHED*/
117 
118  }
119 
120  region_view->init (wait_for_waves);
122  region_view->set_height (child_height ());
123 
124  /* if its the special single-sample length that we use for rec-regions, make it
125  insensitive to events
126  */
127 
128  if (region->length() == 1) {
129  region_view->set_sensitive (false);
130  }
131 
132  return region_view;
133 }
134 
135 RegionView*
137 {
138  RegionView *region_view = create_region_view (r, wait_for_waves, recording);
139 
140  if (region_view == 0) {
141  return 0;
142  }
143 
144  region_views.push_front (region_view);
145 
146  /* catch region going away */
147 
148  r->DropReferences.connect (*this, invalidator (*this), boost::bind (&AudioStreamView::remove_region_view, this, boost::weak_ptr<Region> (r)), gui_context());
149 
150  RegionViewAdded (region_view);
151 
152  return region_view;
153 }
154 
155 void
157 {
158  list<RegionView *>::iterator i;
159 
160  // Flag region views as invalid and disable drawing
161  for (i = region_views.begin(); i != region_views.end(); ++i) {
162  (*i)->set_valid (false);
163  (*i)->enable_display (false);
164  }
165 
166  // Add and display views, and flag them as valid
167  if (_trackview.is_audio_track()) {
169  sigc::hide_return (sigc::mem_fun (*this, &StreamView::add_region_view))
170  );
171  }
172 
173  // Stack regions by layer, and remove invalid regions
174  layer_regions();
175 }
176 
177 void
179 {
180  //cerr << _trackview.name() << " streamview SRB region_views.size() = " << region_views.size() << endl;
181 
183 
184  // cerr << "\trolling\n";
185 
186  if (!rec_active &&
187  _trackview.session()->record_status() == Session::Recording &&
189  if (_trackview.audio_track()->mode() == Normal && ARDOUR_UI::config()->get_show_waveforms_while_recording() && rec_regions.size() == rec_rects.size()) {
190 
191  /* add a new region, but don't bother if they set show-waveforms-while-recording mid-record */
192 
193  SourceList sources;
194 
197 
198  for (uint32_t n = 0; n < tr->n_channels().n_audio(); ++n) {
200  if (src) {
201  sources.push_back (src);
203  invalidator (*this),
204  boost::bind (&AudioStreamView::rec_peak_range_ready, this, _1, _2, boost::weak_ptr<Source>(src)),
205  gui_context());
206  }
207  }
208 
209  // handle multi
210 
211  framepos_t start = 0;
212  if (rec_regions.size() > 0) {
213  start = rec_regions.back().first->start()
215  }
216 
217  PropertyList plist;
218 
219  plist.add (Properties::start, start);
220  plist.add (Properties::length, 1);
221  plist.add (Properties::name, string());
222  plist.add (Properties::layer, 0);
223 
225  boost::dynamic_pointer_cast<AudioRegion>(RegionFactory::create (sources, plist, false)));
226 
227  assert(region);
229  rec_regions.push_back (make_pair(region, (RegionView*) 0));
230  }
231 
232  /* start a new rec box */
233 
235  framepos_t const frame_pos = at->current_capture_start ();
236  double const width = ((at->mode() == Destructive) ? 2 : 0);
237 
238  create_rec_box(frame_pos, width);
239 
240  } else if (rec_active &&
241  (_trackview.session()->record_status() != Session::Recording ||
243  screen_update_connection.disconnect();
244  rec_active = false;
245  rec_updating = false;
246  }
247 
248  } else {
249 
250  // cerr << "\tNOT rolling, rec_rects = " << rec_rects.size() << " rec_regions = " << rec_regions.size() << endl;
251 
252  if (!rec_rects.empty() || !rec_regions.empty()) {
253 
254  /* disconnect rapid update */
255  screen_update_connection.disconnect();
257  rec_updating = false;
258  rec_active = false;
259 
260  /* remove temp regions */
261 
262  for (list<pair<boost::shared_ptr<Region>,RegionView*> >::iterator iter = rec_regions.begin(); iter != rec_regions.end(); ) {
263  list<pair<boost::shared_ptr<Region>,RegionView*> >::iterator tmp;
264 
265  tmp = iter;
266  ++tmp;
267 
268  (*iter).first->drop_references ();
269 
270  iter = tmp;
271  }
272 
273  rec_regions.clear();
274 
275  // cerr << "\tclear " << rec_rects.size() << " rec rects\n";
276 
277  /* transport stopped, clear boxes */
278  for (vector<RecBoxInfo>::iterator iter=rec_rects.begin(); iter != rec_rects.end(); ++iter) {
279  RecBoxInfo &rect = (*iter);
280  delete rect.rectangle;
281  }
282 
283  rec_rects.clear();
284 
285  }
286  }
287 }
288 
289 void
291 {
292  ENSURE_GUI_THREAD (*this, &AudioStreamView::rec_peak_range_ready, start, cnt, weak_src)
293 
294  boost::shared_ptr<Source> src (weak_src.lock());
295 
296  if (!src) {
297  return;
298  }
299 
300  // this is called from the peak building thread
301 
302  if (rec_data_ready_map.size() == 0 || start + cnt > last_rec_data_frame) {
303  last_rec_data_frame = start + cnt;
304  }
305 
306  rec_data_ready_map[src] = true;
307 
308  if (rec_data_ready_map.size() == _trackview.track()->n_channels().n_audio()) {
309  update_rec_regions (start, cnt);
310  rec_data_ready_map.clear();
311  }
312 }
313 
314 void
316 {
317  if (!ARDOUR_UI::config()->get_show_waveforms_while_recording ()) {
318  return;
319  }
320 
321  uint32_t n = 0;
322 
323  for (list<pair<boost::shared_ptr<Region>,RegionView*> >::iterator iter = rec_regions.begin(); iter != rec_regions.end(); n++) {
324 
325  list<pair<boost::shared_ptr<Region>,RegionView*> >::iterator tmp = iter;
326  ++tmp;
327 
328  assert (n < rec_rects.size());
329 
330  if (!rec_rects[n].rectangle->visible()) {
331  /* rect already hidden, this region is done */
332  iter = tmp;
333  continue;
334  }
335 
337 
338  if (!region) {
339  iter = tmp;
340  continue;
341  }
342 
343  framecnt_t origlen = region->length();
344 
345  if (region == rec_regions.back().first && rec_active) {
346 
347  if (last_rec_data_frame > region->start()) {
348 
349  framecnt_t nlen = last_rec_data_frame - region->start();
350 
351  if (nlen != region->length()) {
352 
353  region->suspend_property_changes ();
355  region->set_length (nlen);
356  region->resume_property_changes ();
357 
358  if (origlen == 1) {
359  /* our special initial length */
360  add_region_view_internal (region, false, true);
361  setup_new_rec_layer_time (region);
362  }
363 
364  check_record_layers (region, (region->position() - region->start() + start + cnt));
365 
366  /* also update rect */
367  ArdourCanvas::Rectangle * rect = rec_rects[n].rectangle;
368  gdouble xend = _trackview.editor().sample_to_pixel (region->position() + region->length());
369  rect->set_x1 (xend);
370  }
371 
372  } else {
373 
375 
376  if (nlen != region->length()) {
377 
378  if (region->source_length(0) >= region->start() + nlen) {
379 
380  region->suspend_property_changes ();
382  region->set_length (nlen);
383  region->resume_property_changes ();
384 
385  if (origlen == 1) {
386  /* our special initial length */
387  add_region_view_internal (region, false, true);
388  }
389 
390  /* also hide rect */
391  ArdourCanvas::Item * rect = rec_rects[n].rectangle;
392  rect->hide();
393 
394  }
395  }
396  }
397  }
398 
399  iter = tmp;
400  }
401 }
402 
403 void
405 {
406  for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
407  AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
408  if (arv) {
409  arv->set_fade_visibility (true);
410  }
411  }
412 }
413 
414 void
416 {
417  for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
418  AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
419  if (arv) {
420  arv->set_fade_visibility (false);
421  }
422  }
423 }
424 
429 pair<list<AudioRegionView*>, list<AudioRegionView*> >
431 {
432  list<AudioRegionView*> start_hidden;
433  list<AudioRegionView*> end_hidden;
434 
435  for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
436  AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
437  if (arv) {
438  switch (arv->region()->coverage (ar->position(), ar->last_frame())) {
439  case Evoral::OverlapNone:
440  break;
441  default:
442  if (arv->start_xfade_visible ()) {
443  start_hidden.push_back (arv);
444  }
445  if (arv->end_xfade_visible ()) {
446  end_hidden.push_back (arv);
447  }
448  arv->hide_xfades ();
449  break;
450  }
451  }
452  }
453 
454  return make_pair (start_hidden, end_hidden);
455 }
456 
457 void
459 {
460  //case cAudioTrackBase:
461  if (_trackview.is_track()) {
462  canvas_rect->set_fill_color (ARDOUR_UI::config()->color_mod ("audio track base", "audio track base"));
463  }
464 
465  //case cAudioBusBase:
466  if (!_trackview.is_track()) {
467  if (Profile->get_sae() && _trackview.route()->is_master()) {
468  canvas_rect->set_fill_color (ARDOUR_UI::config()->color ("audio master bus base"));
469  } else {
470  canvas_rect->set_fill_color (ARDOUR_UI::config()->color_mod ("audio bus base", "audio bus base"));
471  }
472  }
473 }
virtual void resume_property_changes()
Definition: stateful.cc:302
PBD::ScopedConnectionList rec_data_ready_connections
Definition: streamview.h:177
framepos_t get_capture_start_frame(uint32_t n=0) const
Definition: track.cc:783
bool transport_rolling() const
Definition: session.h:592
std::list< std::pair< boost::shared_ptr< ARDOUR::Region >, RegionView * > > rec_regions
Definition: streamview.h:162
LIBPBD_API Transmitter fatal
bool get_sae() const
Definition: profile.h:48
bool rec_updating
Definition: streamview.h:163
void layer_regions()
Definition: streamview.cc:224
PBD::Signal0< void > DropReferences
Definition: destructible.h:34
PublicEditor & editor() const
void setup_new_rec_layer_time(boost::shared_ptr< ARDOUR::Region >)
Definition: streamview.cc:712
void rec_peak_range_ready(framepos_t start, ARDOUR::framecnt_t cnt, boost::weak_ptr< ARDOUR::Source > src)
LIBARDOUR_API PBD::PropertyDescriptor< layer_t > layer
Definition: region.cc:67
bool is_audio_track() const
Definition: route_ui.cc:1744
sigc::signal< void, RegionView * > RegionViewAdded
Definition: streamview.h:122
double _samples_per_pixel
Definition: streamview.h:158
bool start_xfade_visible() const
ArdourCanvas::Container * _canvas_group
Definition: streamview.h:152
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r)
Definition: shared_ptr.hpp:396
framecnt_t get_captured_frames(uint32_t n=0) const
Definition: track.cc:723
framepos_t last_rec_data_frame
Definition: streamview.h:178
uint32_t n_audio() const
Definition: chan_count.h:63
Definition: Beats.hpp:239
virtual double sample_to_pixel(framepos_t frame) const =0
std::pair< std::list< AudioRegionView * >, std::list< AudioRegionView * > > hide_xfades_with(boost::shared_ptr< ARDOUR::AudioRegion > ar)
double _amplitude_above_axis
std::ostream & endmsg(std::ostream &ostr)
Definition: transmitter.h:71
void init(bool wait_for_data)
RecordState record_status() const
Definition: session.h:276
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
void set_height(double)
#define ENSURE_GUI_THREAD(obj, method,...)
Definition: gui_thread.h:34
std::vector< RecBoxInfo > rec_rects
Definition: streamview.h:161
#define invalidator(x)
Definition: gui_thread.h:40
void set_fade_visibility(bool)
#define _(Text)
Definition: i18n.h:11
std::map< boost::shared_ptr< ARDOUR::Source >, bool > rec_data_ready_map
int64_t framecnt_t
Definition: types.h:76
void set_position(framepos_t)
Definition: region.cc:579
PBD::Signal2< void, framepos_t, framepos_t > PeakRangeReady
Definition: audiosource.h:78
boost::shared_ptr< ARDOUR::Region > region() const
Definition: region_view.h:66
void check_record_layers(boost::shared_ptr< ARDOUR::Region >, ARDOUR::framepos_t)
Definition: streamview.cc:688
RegionView * create_region_view(boost::shared_ptr< ARDOUR::Region >, bool, bool)
framepos_t transport_frame() const
Definition: session.h:551
Definition: amp.h:29
boost::shared_ptr< AudioFileSource > write_source(uint32_t n=0)
Definition: audio_track.cc:641
ARDOUR::Session * session() const
Definition: axis_view.h:52
ArdourCanvas::Rectangle * rectangle
Definition: streamview.h:49
boost::shared_ptr< ARDOUR::Track > track() const
Definition: route_ui.cc:1738
#define gui_context()
Definition: gui_thread.h:36
Evoral::OverlapType coverage(framepos_t start, framepos_t end) const
Definition: region.h:195
boost::shared_ptr< Playlist > playlist()
Definition: track.cc:590
int set_amplitude_above_axis(gdouble app)
bool record_enabled() const
Definition: track.cc:215
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
void set_amplitude_above_axis(gdouble spp)
void create_rec_box(framepos_t frame_pos, double width)
Definition: streamview.cc:409
LIBARDOUR_API RuntimeProfile * Profile
Definition: globals.cc:120
RegionViewList region_views
Definition: streamview.h:156
bool is_track() const
Definition: route_ui.cc:1732
framecnt_t source_length(uint32_t n) const
Definition: region.cc:1511
framepos_t position() const
Definition: region.h:112
sigc::connection screen_update_connection
Definition: streamview.h:160
ArdourCanvas::Rectangle * canvas_rect
Definition: streamview.h:153
const char * name
bool rec_active
Definition: streamview.h:164
ChanCount n_channels()
Definition: track.cc:777
double child_height() const
Definition: streamview.cc:613
bool is_master() const
Definition: route.h:111
void set_length(framecnt_t)
Definition: region.cc:430
bool end_xfade_visible() const
static UIConfiguration * config()
Definition: ardour_ui.h:188
void add_region_view(boost::weak_ptr< ARDOUR::Region >)
Definition: streamview.cc:165
void update_rec_regions(ARDOUR::framepos_t, ARDOUR::framecnt_t)
Definition: debug.h:30
TrackMode mode() const
Definition: track.h:49
framecnt_t length() const
Definition: region.h:114
void set_sensitive(bool yn)
RegionView * add_region_view_internal(boost::shared_ptr< ARDOUR::Region >, bool wait_for_waves, bool recording=false)
framepos_t start() const
Definition: region.h:113
boost::shared_ptr< ARDOUR::AudioTrack > audio_track() const
Definition: route_ui.cc:1750
uint32_t region_color
Contained region color.
Definition: streamview.h:166
std::vector< boost::shared_ptr< Source > > SourceList
Definition: types.h:520
bool add(PropertyBase *prop)
boost::shared_ptr< ARDOUR::Route > route() const
Definition: route_ui.h:76
AudioStreamView(AudioTimeAxisView &)
framepos_t current_capture_start() const
Definition: track.cc:801
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:208
void suspend_property_changes()
Definition: region.cc:1292
framepos_t last_frame() const
Definition: region.h:142
LIBARDOUR_API PBD::PropertyDescriptor< framecnt_t > length
Definition: region.cc:64
LIBARDOUR_API PBD::PropertyDescriptor< bool > color
Definition: route_group.cc:50