add toggles for region fade in/out/both active, plus toggle for region fades visibility
[ardour.git] / gtk2_ardour / audio_streamview.cc
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 <ardour/audioplaylist.h>
28 #include <ardour/audioregion.h>
29 #include <ardour/audiofilesource.h>
30 #include <ardour/audio_diskstream.h>
31 #include <ardour/audio_track.h>
32 #include <ardour/playlist_templates.h>
33 #include <ardour/source.h>
34 #include <ardour/region_factory.h>
35
36 #include "audio_streamview.h"
37 #include "audio_region_view.h"
38 #include "tape_region_view.h"
39 #include "audio_time_axis.h"
40 #include "canvas-waveview.h"
41 #include "canvas-simplerect.h"
42 #include "region_selection.h"
43 #include "selection.h"
44 #include "public_editor.h"
45 #include "ardour_ui.h"
46 #include "crossfade_view.h"
47 #include "rgb_macros.h"
48 #include "gui_thread.h"
49 #include "utils.h"
50
51 #include "i18n.h"
52
53 using namespace std;
54 using namespace ARDOUR;
55 using namespace PBD;
56 using namespace Editing;
57
58 AudioStreamView::AudioStreamView (AudioTimeAxisView& tv)
59         : StreamView (tv)
60 {
61         crossfades_visible = true;
62         _waveform_scale = LinearWaveform;
63         _waveform_shape = Traditional;
64         color_handler ();
65         _amplitude_above_axis = 1.0;
66
67         use_rec_regions = tv.editor.show_waveforms_recording ();
68 }
69
70 AudioStreamView::~AudioStreamView ()
71 {
72 }
73
74 int 
75 AudioStreamView::set_samples_per_unit (gdouble spp)
76 {
77         StreamView::set_samples_per_unit(spp);
78
79         for (CrossfadeViewList::iterator xi = crossfade_views.begin(); xi != crossfade_views.end(); ++xi) {
80                 (*xi)->set_samples_per_unit (spp);
81         }
82
83         return 0;
84 }
85
86 int 
87 AudioStreamView::set_amplitude_above_axis (gdouble app)
88 {
89         RegionViewList::iterator i;
90
91         if (app < 1.0) {
92                 return -1;
93         }
94
95         _amplitude_above_axis = app;
96
97         for (i = region_views.begin(); i != region_views.end(); ++i) {
98                 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
99                 if (arv)
100                         arv->set_amplitude_above_axis (app);
101         }
102
103         return 0;
104 }
105
106 RegionView*
107 AudioStreamView::add_region_view_internal (boost::shared_ptr<Region> r, bool wait_for_waves, bool recording)
108 {
109         AudioRegionView *region_view = 0;
110
111         boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (r);
112
113         if (region == 0) {
114                 return NULL;
115         }
116
117         for (list<RegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
118                 if ((*i)->region() == r) {
119                         
120                         /* great. we already have a AudioRegionView for this Region. use it again. */
121                         
122                         (*i)->set_valid (true);
123
124                         // this might not be necessary
125                         AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
126                         if (arv) {
127                                 arv->set_waveform_scale (_waveform_scale);
128                                 arv->set_waveform_shape (_waveform_shape);
129                         }
130                                 
131                         return NULL;
132                 }
133         }
134
135         switch (_trackview.audio_track()->mode()) {
136         case Normal:
137                 if (recording) {
138                         region_view = new AudioRegionView (canvas_group, _trackview, region, 
139                                                    _samples_per_unit, region_color, recording, TimeAxisViewItem::Visibility(TimeAxisViewItem::ShowFrame | TimeAxisViewItem::HideFrameRight));
140                 } else {
141                         region_view = new AudioRegionView (canvas_group, _trackview, region, 
142                                                    _samples_per_unit, region_color);
143                 }
144                 break;
145         case Destructive:
146                 region_view = new TapeAudioRegionView (canvas_group, _trackview, region, 
147                                                        _samples_per_unit, region_color);
148                 break;
149         default:
150                 fatal << string_compose (_("programming error: %1"), "illegal track mode in ::add_region_view_internal") << endmsg;
151                 /*NOTREACHED*/
152
153         }
154
155         region_view->init (region_color, wait_for_waves);
156         region_view->set_amplitude_above_axis(_amplitude_above_axis);
157         region_views.push_front (region_view);
158
159         /* if its the special single-sample length that we use for rec-regions, make it 
160            insensitive to events 
161         */
162
163         if (region->length() == 1) {
164                 region_view->set_sensitive (false);
165         }
166
167         /* if this was the first one, then lets query the waveform scale and shape.
168            otherwise, we set it to the current value */
169            
170         if (region_views.size() == 1) {
171                 if (region_view->waveform_logscaled()) {
172                         _waveform_scale = LogWaveform;
173                 } else {
174                         _waveform_scale = LinearWaveform;
175                 }
176
177                 if (region_view->waveform_rectified()) {
178                         _waveform_shape = Rectified;
179                 } else {
180                         _waveform_shape = Traditional;
181                 }
182         }
183         else {
184                 region_view->set_waveform_scale(_waveform_scale);
185                 region_view->set_waveform_shape(_waveform_shape);
186         }
187         
188         /* follow global waveform setting */
189
190         region_view->set_waveform_visible(_trackview.editor.show_waveforms());
191
192         /* catch regionview going away */
193         region->GoingAway.connect (bind (mem_fun (*this, &AudioStreamView::remove_region_view), boost::weak_ptr<Region> (r)));
194
195         RegionViewAdded (region_view);
196
197         return region_view;
198 }
199
200 void
201 AudioStreamView::remove_region_view (boost::weak_ptr<Region> weak_r)
202 {
203         ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::remove_region_view), weak_r));
204
205         boost::shared_ptr<Region> r (weak_r.lock());
206
207         if (!r) {
208                 return;
209         }
210
211         if (!_trackview.session().deletion_in_progress()) {
212
213                 for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end();) {
214                         list<CrossfadeView*>::iterator tmp;
215                         
216                         tmp = i;
217                         ++tmp;
218                         
219                         boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(r);
220                         if (ar && (*i)->crossfade->involves (ar)) {
221                                 delete *i;
222                                 crossfade_views.erase (i);
223                         }
224                         
225                         i = tmp;
226                 }
227         }
228
229         StreamView::remove_region_view(r);
230 }
231
232 void
233 AudioStreamView::undisplay_diskstream ()
234 {
235         StreamView::undisplay_diskstream();
236
237         for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
238                 delete *i;
239         }
240
241         crossfade_views.clear ();
242 }
243
244 void
245 AudioStreamView::playlist_modified_weak (boost::weak_ptr<Diskstream> ds)
246 {
247         boost::shared_ptr<Diskstream> sp (ds.lock());
248         if (!sp) {
249                 return;
250         }
251
252         playlist_modified (sp);
253 }
254
255 void
256 AudioStreamView::playlist_modified (boost::shared_ptr<Diskstream> ds)
257 {
258         /* we do not allow shared_ptr<T> to be bound to slots */
259         ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::playlist_modified_weak), ds));
260
261         StreamView::playlist_modified (ds);
262         
263         /* make sure xfades are on top and all the regionviews are stacked correctly. */
264
265         for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
266                 (*i)->get_canvas_group()->raise_to_top();
267         }
268 }
269
270 void
271 AudioStreamView::playlist_changed (boost::shared_ptr<Diskstream> ds)
272 {
273         ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::playlist_changed), ds));
274
275         StreamView::playlist_changed(ds);
276
277         boost::shared_ptr<AudioPlaylist> apl = boost::dynamic_pointer_cast<AudioPlaylist>(ds->playlist());
278         if (apl)
279                 playlist_connections.push_back (apl->NewCrossfade.connect (mem_fun (*this, &AudioStreamView::add_crossfade)));
280 }
281
282 void
283 AudioStreamView::add_crossfade_weak (boost::weak_ptr<Crossfade> crossfade)
284 {
285         boost::shared_ptr<Crossfade> sp (crossfade.lock());
286
287         if (!sp) {
288                 return;
289         }
290
291         add_crossfade (sp);
292 }
293
294 void
295 AudioStreamView::add_crossfade (boost::shared_ptr<Crossfade> crossfade)
296 {
297         AudioRegionView* lview = 0;
298         AudioRegionView* rview = 0;
299
300         /* we do not allow shared_ptr<T> to be bound to slots */
301         
302         ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::add_crossfade_weak), boost::weak_ptr<Crossfade> (crossfade)));
303
304         /* first see if we already have a CrossfadeView for this Crossfade */
305
306         for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
307                 if ((*i)->crossfade == crossfade) {
308
309                         if (!crossfades_visible || layer_display == Stacked) {
310                                 (*i)->hide();
311                         } else {
312                                 (*i)->show ();
313                         }
314                         (*i)->set_valid (true);
315                         return;
316                 }
317         }
318
319         /* create a new one */
320
321         for (list<RegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
322                 AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*i);
323
324                 if (!lview && arv && (arv->region() == crossfade->out())) {
325                         lview = arv;
326                 }
327                 if (!rview && arv && (arv->region() == crossfade->in())) {
328                         rview = arv;
329                 }
330         }
331
332         CrossfadeView *cv = new CrossfadeView (_trackview.canvas_display,
333                                                _trackview,
334                                                 crossfade,
335                                                _samples_per_unit,
336                                                region_color,
337                                                *lview, *rview);
338         cv->set_valid (true);
339         crossfade->Invalidated.connect (mem_fun (*this, &AudioStreamView::remove_crossfade));
340         crossfade_views.push_back (cv);
341         if (!Config->get_xfades_visible() || !crossfades_visible || layer_display == Stacked) {
342                 cv->hide ();
343         }
344 }
345
346 void
347 AudioStreamView::remove_crossfade (boost::shared_ptr<Region> r)
348 {
349         ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::remove_crossfade), r));
350
351         boost::shared_ptr<Crossfade> xfade = boost::dynamic_pointer_cast<Crossfade> (r);
352
353         for (list<CrossfadeView*>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
354                 if ((*i)->crossfade == xfade) {
355                         delete *i;
356                         crossfade_views.erase (i);
357                         break;
358                 }
359         }
360 }
361
362 void
363 AudioStreamView::redisplay_diskstream ()
364 {
365         list<RegionView *>::iterator i, tmp;
366         list<CrossfadeView*>::iterator xi, tmpx;
367
368         for (i = region_views.begin(); i != region_views.end(); ++i) {
369                 (*i)->set_valid (false);
370         }
371
372         for (xi = crossfade_views.begin(); xi != crossfade_views.end(); ++xi) {
373                 (*xi)->set_valid (false);
374                 if ((*xi)->visible() && layer_display != Stacked) {
375                         (*xi)->show ();
376                 }
377         }
378
379         if (_trackview.is_audio_track()) {
380                 _trackview.get_diskstream()->playlist()->foreach_region (static_cast<StreamView*>(this), &StreamView::add_region_view);
381
382                 boost::shared_ptr<AudioPlaylist> apl = boost::dynamic_pointer_cast<AudioPlaylist>(_trackview.get_diskstream()->playlist());
383                 if (apl)
384                         apl->foreach_crossfade (this, &AudioStreamView::add_crossfade);
385         }
386
387         RegionViewList copy;
388
389         /* Place regions */
390         for (i = region_views.begin(); i != region_views.end(); ) {
391                 tmp = i;
392                 tmp++;
393
394                 if (!(*i)->is_valid()) {
395                         delete *i;
396                         region_views.erase (i);
397                         i = tmp;
398                         continue;
399                 } else {
400                         (*i)->enable_display(true);
401                 }
402
403                 /* Sort regionviews by layer so that when we call region_layered ()
404                    the canvas layering works out (in non-stacked mode). */
405
406                 if (copy.size() == 0) {
407                         copy.push_front((*i));
408                         i = tmp;
409                         continue;
410                 }
411
412                 RegionViewList::iterator k = copy.begin();
413                 RegionViewList::iterator l = copy.end();
414                 l--;
415
416                 if ((*i)->region()->layer() <= (*k)->region()->layer()) {
417                         copy.push_front((*i));
418                         i = tmp;
419                         continue;
420                 } else if ((*i)->region()->layer() >= (*l)->region()->layer()) {
421                         copy.push_back((*i));
422                         i = tmp;
423                         continue;
424                 }
425
426                 for (RegionViewList::iterator j = copy.begin(); j != copy.end(); ++j) {
427                         if ((*j)->region()->layer() >= (*i)->region()->layer()) {
428                                 copy.insert(j, (*i));
429                                 break;
430                         }
431                 }
432
433                 i = tmp;
434         }
435
436         for (xi = crossfade_views.begin(); xi != crossfade_views.end();) {
437                 tmpx = xi;
438                 tmpx++;
439
440                 if (!(*xi)->valid()) {
441                         delete *xi;
442                         crossfade_views.erase (xi);
443                 }
444
445                 xi = tmpx;
446         }
447         
448         /* now fix layering */
449
450         for (RegionViewList::iterator i = copy.begin(); i != copy.end(); ++i) {
451                 region_layered (*i);
452         }
453 }
454
455 void
456 AudioStreamView::set_show_waveforms (bool yn)
457 {
458         for (list<RegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
459                 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
460                 if (arv) {
461                         arv->set_waveform_visible (yn);
462                 }
463         }
464 }
465
466 void
467 AudioStreamView::set_waveform_shape (WaveformShape shape)
468 {
469         for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
470                 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
471                 if (arv)
472                         arv->set_waveform_shape (shape);
473         }
474         _waveform_shape = shape;
475 }               
476
477 void
478 AudioStreamView::set_waveform_scale (WaveformScale scale)
479 {
480         for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
481                 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
482                 if (arv) 
483                         arv->set_waveform_scale (scale);
484         }
485         _waveform_scale = scale;
486 }               
487
488 void
489 AudioStreamView::setup_rec_box ()
490 {
491         //cerr << _trackview.name() << " streamview SRB region_views.size() = " << region_views.size() << endl;
492
493         if (_trackview.session().transport_rolling()) {
494
495                 // cerr << "\trolling\n";
496
497                 if (!rec_active && 
498                     _trackview.session().record_status() == Session::Recording && 
499                     _trackview.get_diskstream()->record_enabled()) {
500                         if (_trackview.audio_track()->mode() == Normal && use_rec_regions && rec_regions.size() == rec_rects.size()) {
501
502                                 /* add a new region, but don't bother if they set use_rec_regions mid-record */
503
504                                 SourceList sources;
505
506                                 for (list<sigc::connection>::iterator prc = rec_data_ready_connections.begin(); prc != rec_data_ready_connections.end(); ++prc) {
507                                         (*prc).disconnect();
508                                 }
509                                 rec_data_ready_connections.clear();
510                                         
511                                 // FIXME
512                                 boost::shared_ptr<AudioDiskstream> ads = boost::dynamic_pointer_cast<AudioDiskstream>(_trackview.get_diskstream());
513                                 assert(ads);
514
515                                 for (uint32_t n=0; n < ads->n_channels().n_audio(); ++n) {
516                                         boost::shared_ptr<AudioFileSource> src = boost::static_pointer_cast<AudioFileSource> (ads->write_source (n));
517                                         if (src) {
518                                                 sources.push_back (src);
519                                                 
520                                                 rec_data_ready_connections.push_back (src->PeakRangeReady.connect (bind
521                                                         (mem_fun (*this, &AudioStreamView::rec_peak_range_ready), boost::weak_ptr<Source>(src)))); 
522                                         }
523                                 }
524
525                                 // handle multi
526                                 
527                                 nframes_t start = 0;
528                                 if (rec_regions.size() > 0) {
529                                         start = rec_regions.back().first->start() + _trackview.get_diskstream()->get_captured_frames(rec_regions.size()-1);
530                                 }
531                                 
532                                 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion>
533                                                                        (RegionFactory::create (sources, start, 1 , "", 0, (Region::Flag)(Region::DefaultFlags | Region::DoNotSaveState), false)));
534                                 assert(region);
535                                 region->set_position (_trackview.session().transport_frame(), this);
536
537                                 rec_regions.push_back (make_pair(region, (RegionView*)0));
538                         }
539                         
540                         /* start a new rec box */
541
542                         boost::shared_ptr<AudioTrack> at;
543
544                         at = _trackview.audio_track(); /* we know what it is already */
545                         boost::shared_ptr<AudioDiskstream> ds = at->audio_diskstream();
546                         nframes_t frame_pos = ds->current_capture_start ();
547                         gdouble xstart = _trackview.editor.frame_to_pixel (frame_pos);
548                         gdouble xend;
549                         uint32_t fill_color;
550
551                         switch (_trackview.audio_track()->mode()) {
552                         case Normal:
553                                 xend = xstart;
554                                 fill_color = ARDOUR_UI::config()->canvasvar_RecordingRect.get();
555                                 break;
556
557                         case Destructive:
558                                 xend = xstart + 2;
559                                 fill_color = ARDOUR_UI::config()->canvasvar_RecordingRect.get();
560                                 /* make the recording rect translucent to allow
561                                    the user to see the peak data coming in, etc.
562                                 */
563                                 fill_color = UINT_RGBA_CHANGE_A (fill_color, 120);
564                                 break;
565                         }
566                         
567                         ArdourCanvas::SimpleRect * rec_rect = new Gnome::Canvas::SimpleRect (*canvas_group);
568                         rec_rect->property_x1() = xstart;
569                         rec_rect->property_y1() = 1.0;
570                         rec_rect->property_x2() = xend;
571                         rec_rect->property_y2() = (double) _trackview.current_height() - 1;
572                         rec_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_TimeAxisFrame.get();
573                         rec_rect->property_outline_what() = 0x1 | 0x2 | 0x4 | 0x8;
574                         rec_rect->property_fill_color_rgba() = fill_color;
575                         rec_rect->lower_to_bottom();
576                         
577                         RecBoxInfo recbox;
578                         recbox.rectangle = rec_rect;
579                         recbox.start = _trackview.session().transport_frame();
580                         recbox.length = 0;
581                         
582                         rec_rects.push_back (recbox);
583                         
584                         screen_update_connection.disconnect();
585                         screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun (*this, &AudioStreamView::update_rec_box));   
586                         rec_updating = true;
587                         rec_active = true;
588
589                 } else if (rec_active &&
590                            (_trackview.session().record_status() != Session::Recording ||
591                             !_trackview.get_diskstream()->record_enabled())) {
592                         screen_update_connection.disconnect();
593                         rec_active = false;
594                         rec_updating = false;
595                 }
596                 
597         } else {
598
599                 // cerr << "\tNOT rolling, rec_rects = " << rec_rects.size() << " rec_regions = " << rec_regions.size() << endl;
600
601                 if (!rec_rects.empty() || !rec_regions.empty()) {
602
603                         /* disconnect rapid update */
604                         screen_update_connection.disconnect();
605
606                         for (list<sigc::connection>::iterator prc = rec_data_ready_connections.begin(); prc != rec_data_ready_connections.end(); ++prc) {
607                                 (*prc).disconnect();
608                         }
609                         rec_data_ready_connections.clear();
610
611                         rec_updating = false;
612                         rec_active = false;
613                         
614                         /* remove temp regions */
615
616                         for (list<pair<boost::shared_ptr<Region>,RegionView*> >::iterator iter = rec_regions.begin(); iter != rec_regions.end(); ) {
617                                 list<pair<boost::shared_ptr<Region>,RegionView*> >::iterator tmp;
618
619                                 tmp = iter;
620                                 ++tmp;
621
622                                 (*iter).first->drop_references ();
623
624                                 iter = tmp;
625                         }
626                                 
627                         rec_regions.clear();
628
629                         // cerr << "\tclear " << rec_rects.size() << " rec rects\n";
630
631                         /* transport stopped, clear boxes */
632                         for (vector<RecBoxInfo>::iterator iter=rec_rects.begin(); iter != rec_rects.end(); ++iter) {
633                                 RecBoxInfo &rect = (*iter);
634                                 delete rect.rectangle;
635                         }
636                         
637                         rec_rects.clear();
638                         
639                 }
640         }
641 }
642
643 void
644 AudioStreamView::foreach_crossfadeview (void (CrossfadeView::*pmf)(void))
645 {
646         for (list<CrossfadeView*>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
647                 ((*i)->*pmf) ();
648         }
649 }
650
651 void
652 AudioStreamView::rec_peak_range_ready (nframes_t start, nframes_t cnt, boost::weak_ptr<Source> weak_src)
653 {
654         ENSURE_GUI_THREAD(bind (mem_fun (*this, &AudioStreamView::rec_peak_range_ready), start, cnt, weak_src));
655         
656         boost::shared_ptr<Source> src (weak_src.lock());
657
658         if (!src) {
659                 return; 
660         }
661
662         // this is called from the peak building thread
663         
664         if (rec_data_ready_map.size() == 0 || start+cnt > last_rec_data_frame) {
665                 last_rec_data_frame = start + cnt;
666         }
667         
668         rec_data_ready_map[src] = true;
669         
670         if (rec_data_ready_map.size() == _trackview.get_diskstream()->n_channels().n_audio()) {
671                 this->update_rec_regions ();
672                 rec_data_ready_map.clear();
673         }
674 }
675
676 void
677 AudioStreamView::update_rec_regions ()
678 {
679         if (use_rec_regions) {
680                 uint32_t n = 0;
681
682                 for (list<pair<boost::shared_ptr<Region>,RegionView*> >::iterator iter = rec_regions.begin(); iter != rec_regions.end(); n++) {
683
684                         list<pair<boost::shared_ptr<Region>,RegionView*> >::iterator tmp;
685
686                         tmp = iter;
687                         ++tmp;
688
689                         if (!canvas_item_visible (rec_rects[n].rectangle)) {
690                                 /* rect already hidden, this region is done */
691                                 iter = tmp;
692                                 continue;
693                         }
694                         
695                         boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion>(iter->first);
696                         if (!region) {
697                                 continue;
698                         }
699
700                         nframes_t origlen = region->length();
701
702                         if (region == rec_regions.back().first && rec_active) {
703
704                                 if (last_rec_data_frame > region->start()) {
705
706                                         nframes_t nlen = last_rec_data_frame - region->start();
707
708                                         if (nlen != region->length()) {
709
710                                                 region->freeze ();
711                                                 region->set_position (_trackview.get_diskstream()->get_capture_start_frame(n), this);
712                                                 region->set_length (nlen, this);
713                                                 region->thaw ("updated");
714
715                                                 if (origlen == 1) {
716                                                         /* our special initial length */
717                                                         add_region_view_internal (region, false, true);
718                                                 }
719
720                                                 /* also update rect */
721                                                 ArdourCanvas::SimpleRect * rect = rec_rects[n].rectangle;
722                                                 gdouble xend = _trackview.editor.frame_to_pixel (region->position() + region->length());
723                                                 rect->property_x2() = xend;
724                                         }
725                                 }
726
727                         } else {
728
729                                 nframes_t nlen = _trackview.get_diskstream()->get_captured_frames(n);
730
731                                 if (nlen != region->length()) {
732
733                                         if (region->source(0)->length() >= region->start() + nlen) {
734
735                                                 region->freeze ();
736                                                 region->set_position (_trackview.get_diskstream()->get_capture_start_frame(n), this);
737                                                 region->set_length (nlen, this);
738                                                 region->thaw ("updated");
739                                                 
740                                                 if (origlen == 1) {
741                                                         /* our special initial length */
742                                                         add_region_view_internal (region, false, true);
743                                                 }
744                                                 
745                                                 /* also hide rect */
746                                                 ArdourCanvas::Item * rect = rec_rects[n].rectangle;
747                                                 rect->hide();
748
749                                         }
750                                 }
751                         }
752
753                         iter = tmp;
754                 }
755         }
756 }
757
758 void
759 AudioStreamView::show_all_fades ()
760 {
761         for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
762                 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
763                 if (arv) {
764                         arv->set_fade_visibility (true);
765                 }
766         }
767 }
768
769 void
770 AudioStreamView::hide_all_fades ()
771 {
772         for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
773                 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
774                 if (arv) {
775                         arv->set_fade_visibility (false);
776                 }
777         }
778 }
779
780 void
781 AudioStreamView::show_all_xfades ()
782 {
783         foreach_crossfadeview (&CrossfadeView::show);
784         crossfades_visible = true;
785 }
786
787 void
788 AudioStreamView::hide_all_xfades ()
789 {
790         foreach_crossfadeview (&CrossfadeView::hide);
791         crossfades_visible = false;
792 }
793
794 void
795 AudioStreamView::hide_xfades_involving (AudioRegionView& rv)
796 {
797         for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
798                 if ((*i)->crossfade->involves (rv.audio_region())) {
799                         (*i)->fake_hide ();
800                 }
801         }
802 }
803
804 void
805 AudioStreamView::reveal_xfades_involving (AudioRegionView& rv)
806 {
807         for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
808                 if ((*i)->crossfade->involves (rv.audio_region()) && (*i)->visible() && layer_display != Stacked) {
809                         (*i)->show ();
810                 }
811         }
812 }
813
814 void
815 AudioStreamView::color_handler ()
816 {
817         //case cAudioTrackBase:
818         if (_trackview.is_track()) {
819                 canvas_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_AudioTrackBase.get();
820         } 
821
822         //case cAudioBusBase:
823         if (!_trackview.is_track()) {
824                 canvas_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_AudioBusBase.get();
825         }
826
827 }
828
829 void
830 AudioStreamView::update_contents_height ()
831 {
832         StreamView::update_contents_height ();
833         
834         for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
835                 if (layer_display == Overlaid) {
836                         (*i)->show ();
837                         (*i)->set_height (height);
838                 } else {
839                         (*i)->hide ();
840                 }
841         }
842 }