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 {
}
deletion_list.push_back (i);
-
}
while (deletion_list.size() > 0) {
} else {
_image_cache[_region->audio_source ()] = caches;
}
-
}
void
}
}
+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;
Cairo::RefPtr<Cairo::Context> outline_context = Cairo::Context::create (images.outline);
Cairo::RefPtr<Cairo::Context> clip_context = Cairo::Context::create (images.clip);
Cairo::RefPtr<Cairo::Context> zero_context = Cairo::Context::create (images.zero);
+ wave_context->set_antialias (Cairo::ANTIALIAS_NONE);
+ outline_context->set_antialias (Cairo::ANTIALIAS_NONE);
+ clip_context->set_antialias (Cairo::ANTIALIAS_NONE);
+ zero_context->set_antialias (Cairo::ANTIALIAS_NONE);
boost::scoped_array<LineTips> tips (new LineTips[n_peaks]);
tips[i].top = y_extent (p, false);
tips[i].spread = p * (_height - 1.0);
- if (fabs (_peaks[i].max) >= clip_level) {
+ if (_peaks[i].max >= clip_level) {
tips[i].clip_max = true;
}
- if (fabs (_peaks[i].min) >= clip_level) {
+ if (-(_peaks[i].min) >= clip_level) {
tips[i].clip_min = true;
}
}
- } else {for (int i = 0; i < n_peaks; ++i) {
+ } else {
+ for (int i = 0; i < n_peaks; ++i) {
tips[i].bot = height() - 1.0;
const double p = max(fabs (_peaks[i].max), fabs (_peaks[i].min));
double top = _peaks[i].max;
double bot = _peaks[i].min;
- if (_peaks[i].max > 0 && _peaks[i].min > 0) {
- if (fabs (_peaks[i].max) >= clip_level) {
+ if (_peaks[i].max >= clip_level) {
tips[i].clip_max = true;
- }
}
- else if (_peaks[i].max < 0 && _peaks[i].min < 0) {
- if (fabs (_peaks[i].min) >= clip_level) {
- tips[i].clip_min = true;
- }
- } else {
- if (fabs (_peaks[i].max) >= clip_level) {
- tips[i].clip_max = true;
- }
- if (fabs (_peaks[i].min) >= clip_level) {
- tips[i].clip_min = true;
- }
+ if (-(_peaks[i].min) >= clip_level) {
+ tips[i].clip_min = true;
}
if (top > 0.0) {
tips[i].top = y_extent (top, false);
tips[i].bot = y_extent (bot, true);
- tips[i].spread = fabs (tips[i].top - tips[i].bot);
+ tips[i].spread = tips[i].bot - tips[i].top;
}
} else {
for (int i = 0; i < n_peaks; ++i) {
- if (_peaks[i].max > 0 && _peaks[i].min > 0) {
- if (fabs (_peaks[i].max) >= clip_level) {
- tips[i].clip_max = true;
- }
+ if (_peaks[i].max >= clip_level) {
+ tips[i].clip_max = true;
}
- else if (_peaks[i].max < 0 && _peaks[i].min < 0) {
- if (fabs (_peaks[i].min) >= clip_level) {
- tips[i].clip_min = true;
- }
- } else {
- if (fabs (_peaks[i].max) >= clip_level) {
- tips[i].clip_max = true;
- }
- if (fabs (_peaks[i].min) >= clip_level) {
- tips[i].clip_min = true;
- }
+ if (-(_peaks[i].min) >= clip_level) {
+ tips[i].clip_min = true;
}
tips[i].top = y_extent (_peaks[i].max, false);
tips[i].bot = y_extent (_peaks[i].min, true);
- tips[i].spread = fabs (tips[i].top - tips[i].bot);
+ tips[i].spread = tips[i].bot - tips[i].top;
}
}
wave_context->set_line_width (1.0);
wave_context->translate (0.5, +0.5);
- outline_context->set_line_cap (Cairo::LINE_CAP_ROUND);
outline_context->set_line_width (1.0);
outline_context->translate (0.5, +0.5);
*/
const double clip_height = min (7.0, ceil (_height * 0.05));
+ bool draw_outline_as_wave = false;
/* There are 3 possible components to draw at each x-axis position: the
waveform "line", the zero line and an outline/clip indicator. We
wave_context->move_to (i, tips[i].top);
wave_context->line_to (i, tips[i].bot);
}
+ /* draw square waves and other discontiguous points clearly */
if (i > 0) {
- if (tips[i-1].top + 2 < tips[i].bot) {
+ if (tips[i-1].top + 2 < tips[i].top) {
wave_context->move_to (i-1, tips[i-1].top);
- wave_context->line_to (i, tips[i].bot);
- }
- else if (tips[i-1].bot > tips[i].top + 2) {
- wave_context->move_to (i-1, tips[i-1].bot);
+ wave_context->line_to (i-1, (tips[i].bot + tips[i-1].top)/2);
+ wave_context->move_to (i, (tips[i].bot + tips[i-1].top)/2);
wave_context->line_to (i, tips[i].top);
+ } else if (tips[i-1].bot > tips[i].bot + 2) {
+ wave_context->move_to (i-1, tips[i-1].bot);
+ wave_context->line_to (i-1, (tips[i].top + tips[i-1].bot)/2);
+ wave_context->move_to (i, (tips[i].top + tips[i-1].bot)/2);
+ wave_context->line_to (i, tips[i].bot);
}
}
}
if (tips[i].spread > 1.0) {
+ draw_outline_as_wave = false;
/* lower outline/clip indicator */
if (_global_show_waveform_clipping && tips[i].clip_min) {
clip_context->move_to (i, tips[i].bot);
const double sign = tips[i].bot > height_2 ? -1 : 1;
clip_context->rel_line_to (0, sign * min (clip_height, ceil (tips[i].spread + .5)));
} else {
- outline_context->move_to (i, tips[i].bot);
+ outline_context->move_to (i, tips[i].bot + 0.5);
/* normal lower terminal dot */
- outline_context->close_path ();
+ outline_context->rel_line_to (0, -0.5);
}
} else {
+ draw_outline_as_wave = true;
if (tips[i].clip_min) {
// make sure we draw the clip
tips[i].clip_max = true;
const double sign = tips[i].top > height_2 ? -1 : 1;
clip_context->rel_line_to (0, sign * min(clip_height, ceil(tips[i].spread + .5)));
} else {
- outline_context->move_to (i, tips[i].top);
- /* normal upper terminal dot */
- outline_context->close_path ();
+ if (draw_outline_as_wave) {
+ wave_context->move_to (i, tips[i].top + 0.5);
+ /* special case where outline only is drawn.
+ is this correct? too short by 0.5?
+ */
+ wave_context->rel_line_to (0, -0.5);
+ } else {
+ outline_context->move_to (i, tips[i].top + 0.5);
+ /* normal upper terminal dot */
+ outline_context->rel_line_to (0, -0.5);
+ }
}
}
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));