open un-writable sessions without complaining, and desensitize all/most actions that...
[ardour.git] / gtk2_ardour / audio_streamview.cc
index 0a74d89d353a57181255126ffb4f7c8f67f0395f..8d12fef2c230847543daf44a362a4c8b2968d989 100644 (file)
@@ -31,6 +31,7 @@
 #include <ardour/playlist_templates.h>
 #include <ardour/source.h>
 #include <ardour/region_factory.h>
+#include <ardour/profile.h>
 
 #include "audio_streamview.h"
 #include "audio_region_view.h"
@@ -46,7 +47,8 @@
 #include "rgb_macros.h"
 #include "gui_thread.h"
 #include "utils.h"
-#include "color.h"
+
+#include "i18n.h"
 
 using namespace ARDOUR;
 using namespace PBD;
@@ -56,14 +58,10 @@ AudioStreamView::AudioStreamView (AudioTimeAxisView& tv)
        : StreamView (tv)
 {
        crossfades_visible = true;
+       _waveform_scale = LinearWaveform;
+       _waveform_shape = Traditional;
 
-       if (tv.is_audio_track())
-               stream_base_color = color_map[cAudioTrackBase];
-       else
-               stream_base_color = color_map[cAudioBusBase];
-       
-       canvas_rect->property_fill_color_rgba() = stream_base_color;
-       canvas_rect->property_outline_color_rgba() = color_map[cAudioTrackOutline];
+       color_handler ();
 
        _amplitude_above_axis = 1.0;
 
@@ -126,9 +124,9 @@ AudioStreamView::set_amplitude_above_axis (gdouble app)
 }
 
 void
-AudioStreamView::add_region_view_internal (boost::shared_ptr<Region> r, bool wait_for_waves)
+AudioStreamView::add_region_view_internal (boost::shared_ptr<Region> r, bool wait_for_waves, bool recording)
 {
-       AudioRegionView *region_view;
+       AudioRegionView *region_view = 0;
 
        ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::add_region_view), r));
 
@@ -144,24 +142,70 @@ AudioStreamView::add_region_view_internal (boost::shared_ptr<Region> r, bool wai
                        /* great. we already have a AudioRegionView for this Region. use it again. */
                        
                        (*i)->set_valid (true);
+
+                       // this might not be necessary
+                       AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
+                       if (arv) {
+                               arv->set_waveform_scale (_waveform_scale);
+                               arv->set_waveform_shape (_waveform_shape);
+                       }
+                               
                        return;
                }
        }
 
        switch (_trackview.audio_track()->mode()) {
        case Normal:
-               region_view = new AudioRegionView (canvas_group, _trackview, region, 
-                                                  _samples_per_unit, region_color);
+               if (recording) {
+                       region_view = new AudioRegionView (canvas_group, _trackview, region, 
+                                                  _samples_per_unit, region_color, recording, TimeAxisViewItem::Visibility(TimeAxisViewItem::ShowFrame | TimeAxisViewItem::HideFrameRight));
+               } else {
+                       region_view = new AudioRegionView (canvas_group, _trackview, region, 
+                                                          _samples_per_unit, region_color);
+               }
                break;
        case Destructive:
                region_view = new TapeAudioRegionView (canvas_group, _trackview, region, 
                                                       _samples_per_unit, region_color);
                break;
+       default:
+               fatal << string_compose (_("programming error: %1"), "illegal track mode in ::add_region_view_internal") << endmsg;
+               /*NOTREACHED*/
+
        }
 
        region_view->init (region_color, wait_for_waves);
        region_view->set_amplitude_above_axis(_amplitude_above_axis);
        region_views.push_front (region_view);
+
+       /* if its the special single-sample length that we use for rec-regions, make it 
+          insensitive to events 
+       */
+
+       if (region->length() == 1) {
+               region_view->set_sensitive (false);
+       }
+
+       /* if this was the first one, then lets query the waveform scale and shape.
+          otherwise, we set it to the current value */
+          
+       if (region_views.size() == 1) {
+               if (region_view->waveform_logscaled()) {
+                       _waveform_scale = LogWaveform;
+               } else {
+                       _waveform_scale = LinearWaveform;
+               }
+
+               if (region_view->waveform_rectified()) {
+                       _waveform_shape = Rectified;
+               } else {
+                       _waveform_shape = Traditional;
+               }
+       }
+       else {
+               region_view->set_waveform_scale(_waveform_scale);
+               region_view->set_waveform_shape(_waveform_shape);
+       }
        
        /* follow global waveform setting */
 
@@ -193,7 +237,7 @@ AudioStreamView::remove_region_view (boost::weak_ptr<Region> weak_r)
                        ++tmp;
                        
                        boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(r);
-                       if (ar && (*i)->crossfade.involves (ar)) {
+                       if (ar && (*i)->crossfade->involves (ar)) {
                                delete *i;
                                crossfade_views.erase (i);
                        }
@@ -202,6 +246,7 @@ AudioStreamView::remove_region_view (boost::weak_ptr<Region> weak_r)
                }
        }
 
+
        StreamView::remove_region_view(r);
 }
 
@@ -232,29 +277,49 @@ AudioStreamView::playlist_modified ()
 }
 
 void
-AudioStreamView::playlist_changed (boost::shared_ptr<Diskstream> ds)
+AudioStreamView::playlist_changed (boost::weak_ptr<Diskstream> wptr)
 {
-       ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::playlist_changed), ds));
+       ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::playlist_changed), wptr));
+
+       boost::shared_ptr<Diskstream> ds  = wptr.lock();
+
+       if (!ds) {
+               return;
+       }
 
        StreamView::playlist_changed(ds);
 
-       AudioPlaylist* apl = dynamic_cast<AudioPlaylist*>(ds->playlist());
+       boost::shared_ptr<AudioPlaylist> apl = boost::dynamic_pointer_cast<AudioPlaylist>(ds->playlist());
        if (apl)
                playlist_connections.push_back (apl->NewCrossfade.connect (mem_fun (*this, &AudioStreamView::add_crossfade)));
 }
 
 void
-AudioStreamView::add_crossfade (Crossfade *crossfade)
+AudioStreamView::add_crossfade_weak (boost::weak_ptr<Crossfade> crossfade)
+{
+       boost::shared_ptr<Crossfade> sp (crossfade.lock());
+
+       if (!sp) {
+               return;
+       }
+
+       add_crossfade (sp);
+}
+
+void
+AudioStreamView::add_crossfade (boost::shared_ptr<Crossfade> crossfade)
 {
        AudioRegionView* lview = 0;
        AudioRegionView* rview = 0;
 
-       ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::add_crossfade), crossfade));
+       /* we do not allow shared_ptr<T> to be bound to slots */
+       
+       ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::add_crossfade_weak), boost::weak_ptr<Crossfade> (crossfade)));
 
        /* first see if we already have a CrossfadeView for this Crossfade */
 
        for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
-               if (&(*i)->crossfade == crossfade) {
+               if ((*i)->crossfade == crossfade) {
                        if (!crossfades_visible) {
                                (*i)->hide();
                        } else {
@@ -280,7 +345,7 @@ AudioStreamView::add_crossfade (Crossfade *crossfade)
 
        CrossfadeView *cv = new CrossfadeView (_trackview.canvas_display,
                                               _trackview,
-                                              *crossfade,
+                                               crossfade,
                                               _samples_per_unit,
                                               region_color,
                                               *lview, *rview);
@@ -288,18 +353,18 @@ AudioStreamView::add_crossfade (Crossfade *crossfade)
        crossfade->Invalidated.connect (mem_fun (*this, &AudioStreamView::remove_crossfade));
        crossfade_views.push_back (cv);
 
-       if (!crossfades_visible) {
+       if (!Config->get_xfades_visible() || !crossfades_visible) {
                cv->hide ();
        }
 }
 
 void
-AudioStreamView::remove_crossfade (Crossfade *xfade)
+AudioStreamView::remove_crossfade (boost::shared_ptr<Crossfade> xfade)
 {
        ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::remove_crossfade), xfade));
 
        for (list<CrossfadeView*>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
-               if (&(*i)->crossfade == xfade) {
+               if ((*i)->crossfade == xfade) {
                        delete *i;
                        crossfade_views.erase (i);
                        break;
@@ -313,7 +378,6 @@ AudioStreamView::redisplay_diskstream ()
        list<RegionView *>::iterator i, tmp;
        list<CrossfadeView*>::iterator xi, tmpx;
 
-       
        for (i = region_views.begin(); i != region_views.end(); ++i) {
                (*i)->set_valid (false);
        }
@@ -327,7 +391,8 @@ AudioStreamView::redisplay_diskstream ()
 
        if (_trackview.is_audio_track()) {
                _trackview.get_diskstream()->playlist()->foreach_region (static_cast<StreamView*>(this), &StreamView::add_region_view);
-               AudioPlaylist* apl = dynamic_cast<AudioPlaylist*>(_trackview.get_diskstream()->playlist());
+
+               boost::shared_ptr<AudioPlaylist> apl = boost::dynamic_pointer_cast<AudioPlaylist>(_trackview.get_diskstream()->playlist());
                if (apl)
                        apl->foreach_crossfade (this, &AudioStreamView::add_crossfade);
        }
@@ -358,7 +423,9 @@ AudioStreamView::redisplay_diskstream ()
 
        /* now fix layering */
 
-       playlist_modified ();
+       for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+               region_layered (*i);
+       }
 }
 
 void
@@ -366,8 +433,9 @@ AudioStreamView::set_show_waveforms (bool yn)
 {
        for (list<RegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
                AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
-               if (arv)
+               if (arv) {
                        arv->set_waveform_visible (yn);
+               }
        }
 }
 
@@ -379,12 +447,24 @@ AudioStreamView::set_waveform_shape (WaveformShape shape)
                if (arv)
                        arv->set_waveform_shape (shape);
        }
+       _waveform_shape = shape;
 }              
-               
+
+void
+AudioStreamView::set_waveform_scale (WaveformScale scale)
+{
+       for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+               AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
+               if (arv) 
+                       arv->set_waveform_scale (scale);
+       }
+       _waveform_scale = scale;
+}              
+
 void
 AudioStreamView::setup_rec_box ()
 {
-       // cerr << _trackview.name() << " streamview SRB\n";
+       //cerr << _trackview.name() << " streamview SRB region_views.size() = " << region_views.size() << endl;
 
        if (_trackview.session().transport_rolling()) {
 
@@ -393,7 +473,6 @@ AudioStreamView::setup_rec_box ()
                if (!rec_active && 
                    _trackview.session().record_status() == Session::Recording && 
                    _trackview.get_diskstream()->record_enabled()) {
-
                        if (_trackview.audio_track()->mode() == Normal && use_rec_regions && rec_regions.size() == rec_rects.size()) {
 
                                /* add a new region, but don't bother if they set use_rec_regions mid-record */
@@ -433,24 +512,22 @@ AudioStreamView::setup_rec_box ()
                        
                        /* start a new rec box */
 
-                       AudioTrack* at;
-
-                       at = _trackview.audio_track(); /* we know what it is already */
+                       boost::shared_ptr<AudioTrack> at = _trackview.audio_track ();
                        boost::shared_ptr<AudioDiskstream> ds = at->audio_diskstream();
                        nframes_t frame_pos = ds->current_capture_start ();
                        gdouble xstart = _trackview.editor.frame_to_pixel (frame_pos);
                        gdouble xend;
                        uint32_t fill_color;
 
-                       switch (_trackview.audio_track()->mode()) {
+                       switch (at->mode()) {
                        case Normal:
                                xend = xstart;
-                               fill_color = color_map[cRecordingRectFill];
+                               fill_color = ARDOUR_UI::config()->canvasvar_RecordingRect.get();
                                break;
 
                        case Destructive:
                                xend = xstart + 2;
-                               fill_color = color_map[cRecordingRectFill];
+                               fill_color = ARDOUR_UI::config()->canvasvar_RecordingRect.get();
                                /* make the recording rect translucent to allow
                                   the user to see the peak data coming in, etc.
                                */
@@ -462,8 +539,9 @@ AudioStreamView::setup_rec_box ()
                        rec_rect->property_x1() = xstart;
                        rec_rect->property_y1() = 1.0;
                        rec_rect->property_x2() = xend;
-                       rec_rect->property_y2() = (double) _trackview.height - 1;
-                       rec_rect->property_outline_color_rgba() = color_map[cRecordingRectOutline];
+                       rec_rect->property_y2() = (double) _trackview.current_height() - 1;
+                       rec_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_TimeAxisFrame.get();
+                       rec_rect->property_outline_what() = 0x1 | 0x2 | 0x4 | 0x8;
                        rec_rect->property_fill_color_rgba() = fill_color;
                        
                        RecBoxInfo recbox;
@@ -481,11 +559,9 @@ AudioStreamView::setup_rec_box ()
                } else if (rec_active &&
                           (_trackview.session().record_status() != Session::Recording ||
                            !_trackview.get_diskstream()->record_enabled())) {
-
                        screen_update_connection.disconnect();
                        rec_active = false;
                        rec_updating = false;
-
                }
                
        } else {
@@ -572,7 +648,6 @@ void
 AudioStreamView::update_rec_regions ()
 {
        if (use_rec_regions) {
-
                uint32_t n = 0;
 
                for (list<boost::shared_ptr<Region> >::iterator iter = rec_regions.begin(); iter != rec_regions.end(); n++) {
@@ -610,7 +685,7 @@ AudioStreamView::update_rec_regions ()
 
                                                if (origlen == 1) {
                                                        /* our special initial length */
-                                                       add_region_view_internal (region, false);
+                                                       add_region_view_internal (region, false, true);
                                                }
 
                                                /* also update rect */
@@ -635,7 +710,7 @@ AudioStreamView::update_rec_regions ()
                                                
                                                if (origlen == 1) {
                                                        /* our special initial length */
-                                                       add_region_view_internal (region, false);
+                                                       add_region_view_internal (region, false, true);
                                                }
                                                
                                                /* also hide rect */
@@ -651,6 +726,28 @@ AudioStreamView::update_rec_regions ()
        }
 }
 
+void
+AudioStreamView::show_all_fades ()
+{
+       for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+               AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
+               if (arv) {
+                       arv->set_fade_visibility (true);
+               }
+       }
+}
+
+void
+AudioStreamView::hide_all_fades ()
+{
+       for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+               AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
+               if (arv) {
+                       arv->set_fade_visibility (false);
+               }
+       }
+}
+
 void
 AudioStreamView::show_all_xfades ()
 {
@@ -669,7 +766,7 @@ void
 AudioStreamView::hide_xfades_involving (AudioRegionView& rv)
 {
        for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
-               if ((*i)->crossfade.involves (rv.audio_region())) {
+               if ((*i)->crossfade->involves (rv.audio_region())) {
                        (*i)->fake_hide ();
                }
        }
@@ -679,32 +776,25 @@ void
 AudioStreamView::reveal_xfades_involving (AudioRegionView& rv)
 {
        for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
-               if ((*i)->crossfade.involves (rv.audio_region()) && (*i)->visible()) {
+               if ((*i)->crossfade->involves (rv.audio_region()) && (*i)->visible()) {
                        (*i)->show ();
                }
        }
 }
 
 void
-AudioStreamView::color_handler (ColorID id, uint32_t val)
+AudioStreamView::color_handler ()
 {
-       switch (id) {
-       case cAudioTrackBase:
-               if (_trackview.is_track()) {
-                       canvas_rect->property_fill_color_rgba() = val;
-               } 
-               break;
-       case cAudioBusBase:
-               if (!_trackview.is_track()) {
-                       canvas_rect->property_fill_color_rgba() = val;
-               }
-               break;
-       case cAudioTrackOutline:
-               canvas_rect->property_outline_color_rgba() = val;
-               break;
+       if (_trackview.is_track()) {
+               canvas_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_AudioTrackBase.get();
+       }
 
-       default:
-               break;
+       if (!_trackview.is_track()) {
+               if (Profile->get_sae() && _trackview.route()->master()) {
+                       canvas_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_AudioMasterBusBase.get();
+               } else {
+                       canvas_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_AudioBusBase.get();
+               }
        }
 }