Fix 0006183 (waveview crash).
[ardour.git] / libs / canvas / wave_view.cc
index e559756e6840c1eee346b1d835e1217b8c461de8..3521ef33cd20bc610a745ceb7196cf06c7baab64 100644 (file)
@@ -211,6 +211,21 @@ WaveView::invalidate_image_cache ()
        vector <uint32_t> deletion_list;
        vector <CacheEntry> caches;
 
+       /* The source may have disappeared in the case of rec regions.*/
+       if (_region->n_channels() == 0) {
+               std::map <boost::shared_ptr<ARDOUR::AudioSource>, std::vector <CacheEntry> >::iterator i;
+               for (i = _image_cache.begin(); i != _image_cache.end(); ++i) {
+                       if (i->first.unique()) {
+                               for (uint32_t n = 0; n < (*i).second.size (); ++n) {
+                                       (*i).second[n].image.clear ();
+                               }
+                               (*i).second.clear ();
+                               _image_cache.erase(i->first);
+                       }
+               }
+               return;
+       }
+
        if (_image_cache.find (_region->audio_source ()) != _image_cache.end ()) {
                caches = _image_cache.find (_region->audio_source ())->second;
        } else {
@@ -228,7 +243,6 @@ WaveView::invalidate_image_cache ()
                }
 
                deletion_list.push_back (i);
-
        }
 
        while (deletion_list.size() > 0) {
@@ -242,7 +256,6 @@ WaveView::invalidate_image_cache ()
        } else {
                _image_cache[_region->audio_source ()] = caches;
        }
-
 }
 
 void
@@ -349,6 +362,38 @@ WaveView::y_extent (double s, bool /*round_to_lower_edge*/) const
        }
 }
 
+void
+WaveView::draw_absent_image (Cairo::RefPtr<Cairo::ImageSurface>& image, PeakData* _peaks, int n_peaks) const
+{
+       Cairo::RefPtr<Cairo::ImageSurface> stripe = Cairo::ImageSurface::create (Cairo::FORMAT_A8, n_peaks, _height);
+
+       Cairo::RefPtr<Cairo::Context> stripe_context = Cairo::Context::create (stripe);
+       stripe_context->set_antialias (Cairo::ANTIALIAS_NONE);
+
+       uint32_t stripe_separation = 150;
+       double start = - floor (_height / stripe_separation) * stripe_separation;
+       int stripe_x = 0;
+
+       while (start < n_peaks) {
+
+               stripe_context->move_to (start, 0);
+               stripe_x = start + _height;
+               stripe_context->line_to (stripe_x, _height);
+               start += stripe_separation;
+       }
+
+       stripe_context->set_source_rgba (1.0, 1.0, 1.0, 1.0);
+       stripe_context->set_line_cap (Cairo::LINE_CAP_SQUARE);
+       stripe_context->set_line_width(50);
+       stripe_context->stroke();
+
+       Cairo::RefPtr<Cairo::Context> context = Cairo::Context::create (image);
+
+       context->set_source_rgba (1.0, 1.0, 0.0, 0.3);
+       context->mask (stripe, 0, 0);
+       context->fill ();
+}
+
 struct LineTips {
        double top;
        double bot;
@@ -754,21 +799,26 @@ WaveView::get_image (Cairo::RefPtr<Cairo::ImageSurface>& image, framepos_t start
        /* we can request data from anywhere in the Source, between 0 and its length
         */
 
-       framepos_t sample_start = max ((framepos_t) _region->start(), (center - canvas_samples));
-       framepos_t sample_end = min (center + canvas_samples, _region->start() + _region->length());
+       framepos_t sample_start = max ((framepos_t) 0, (center - canvas_samples));
+       framepos_t sample_end = min (center + canvas_samples, _region->source_length (0));
 
        const int n_peaks = llrintf ((sample_end - sample_start)/ (double) _samples_per_pixel);
 
        boost::scoped_array<ARDOUR::PeakData> peaks (new PeakData[n_peaks]);
 
-       _region->read_peaks (peaks.get(), n_peaks,
+       framecnt_t peaks_read;
+       peaks_read = _region->read_peaks (peaks.get(), n_peaks,
                             sample_start, sample_end - sample_start,
                             _channel,
                             _samples_per_pixel);
 
        image = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, n_peaks, _height);
 
-       draw_image (image, peaks.get(), n_peaks);
+       if (peaks_read > 0) {
+               draw_image (image, peaks.get(), n_peaks);
+       } else {
+               draw_absent_image (image, peaks.get(), n_peaks);
+       }
 
        _image_cache[_region->audio_source ()].push_back (CacheEntry (_channel, _height, _region_amplitude, _fill_color, sample_start,  sample_end, image));