pub fn render(&mut self, audio_buffer: &AudioBuffer, lower: usize, upper: usize) {
        #[cfg(feature = "profile-waveform-image")]
        let start = Utc::now();

        // Align requested lower and upper sample bounds in order to keep
        // a steady offset between redraws. This allows using the same samples
        // for a given req_step_duration and avoiding flickering
        // between redraws.
        let mut lower = lower / self.sample_step * self.sample_step;
        let upper = upper / self.sample_step * self.sample_step;
        if audio_buffer.eos && upper == audio_buffer.upper
            || self.contains_eos
                && (upper == self.upper || (!self.force_redraw && lower >= self.lower))
        {
            // reached eos or image already contains eos and won't change
            if !self.contains_eos {
                debug!(
                    concat!(
                        "{}_render setting contains_eos. ",
                        "Requested [{}, {}], current [{}, {}], force_redraw: {}",
                    ),
                    self.id,
                    lower,
                    upper,
                    self.lower,
                    self.upper,
                    self.force_redraw,
                );

                self.contains_eos = true;
            }
        } else if self.contains_eos {
            self.contains_eos = false;

            debug!(
                concat!(
                    "{}_render clearing contains_eos. ",
                    "Requested [{}, {}], current [{}, {}], force_redraw {} ",
                    "audio_buffer.eos {}",
                ),
                self.id,
                lower,
                upper,
                self.lower,
                self.upper,
                self.force_redraw,
                audio_buffer.eos,
            );
        }

        if lower < audio_buffer.lower {
            // first sample might be smaller than audio_buffer.lower
            // due to alignement on sample_step
            debug!(
                "{}_render lower {} is less than buffer.lower {}",
                self.id, lower, audio_buffer.lower,
            );
            lower += self.sample_step;
        }

        if lower >= upper {
            // can't draw current range
            // reset WaveformImage state
            debug!(
                "{}_render lower {} greater or equal upper {}",
                self.id, lower, upper
            );

            self.lower = 0;
            self.upper = 0;
            self.first = None;
            self.last = None;
            self.contains_eos = false;
            self.is_ready = false;
            return;
        }

        if upper < lower + 2 * self.sample_step {
            debug!(
                "{}_render range [{}, {}] too small for sample_step: {}",
                self.id, lower, upper, self.sample_step,
            );
            return;
        }

        self.force_redraw |= !self.is_ready;

        if !self.force_redraw && lower >= self.lower && upper <= self.upper {
            // target extraction fits in previous extraction
            return;
        } else if upper < self.lower || lower > self.upper {
            // current samples extraction doesn't overlap with samples in previous image
            self.force_redraw = true;

            debug!(
                concat!(
                    "{}_render no overlap self.lower {}, ",
                    "self.upper {}, lower {}, upper {}",
                ),
                self.id,
                self.lower,
                self.upper,
                lower,
                upper,
            );
        }

        let (exposed_image, secondary_image) = {
            let target_width = if self.image_width > 0 {
                self.image_width
                    .max(((upper - lower) * self.x_step / self.sample_step) as i32)
            } else {
                INIT_WIDTH.max(((upper - lower) * self.x_step / self.sample_step) as i32)
            };
            if (target_width == self.image_width && self.req_height == self.image_height)
                || (self.force_redraw && target_width <= self.image_width
                    && self.req_height == self.image_height)
            {
                // expected dimensions fit in current image => reuse it
                (
                    self.exposed_image.take().unwrap(),
                    self.secondary_image.take().unwrap(),
                )
            } else {
                // can't reuse => create new images and force redraw
                self.force_redraw = true;
                self.image_width = target_width;
                self.image_width_f = f64::from(target_width);
                self.image_height = self.req_height;
                self.half_range = f64::from(self.req_height / 2);
                self.full_range = f64::from(self.req_height);

                debug!(
                    "{}_render new images w {}, h {}",
                    self.id, target_width, self.req_height
                );

                (
                    cairo::ImageSurface::create(
                        // exposed_image
                        cairo::Format::Rgb24,
                        target_width,
                        self.req_height,
                    ).expect(&format!(
                        "WaveformBuffer.render: couldn't create image surface with width {}",
                        target_width,
                    )),
                    cairo::ImageSurface::create(
                        // will be used as secondary_image
                        cairo::Format::Rgb24,
                        target_width,
                        self.req_height,
                    ).unwrap(), // exposed_image could be created with same dimensions
                )
            }
        };

        if self.force_redraw {
            // Initialization or resolution has changed or seek requested
            // redraw the whole range from the audio buffer

            self.redraw(exposed_image, secondary_image, audio_buffer, lower, upper);
        } else if lower < self.lower {
            // can append samples before previous first sample
            if self.first.is_some() {
                // first sample position is known
                // shift previous image to the right
                // and append samples to the left
                self.append_left(exposed_image, secondary_image, audio_buffer, lower);
            } else {
                // first sample position is unknown
                // => force redraw
                warn!("{}_append left first sample unknown => redrawing", self.id);
                let sample_step = self.sample_step;
                self.redraw(
                    exposed_image,
                    secondary_image,
                    audio_buffer,
                    lower,
                    upper.min(audio_buffer.upper / sample_step * sample_step),
                );
            }
        } else if upper > self.upper {
            // can append samples after previous last sample
            if self.last.is_some() {
                // last sample position is known
                // shift previous image to the left (if necessary)
                // and append missing samples to the right

                // update lower in case a call to append_left
                // ends up adding nothing
                let lower = lower.max(self.lower);

                self.append_right(exposed_image, secondary_image, audio_buffer, lower, upper);
            } else {
                // last sample position is unknown
                // => force redraw
                warn!("{}_append right last sample unknown => redrawing", self.id);
                let sample_step = self.sample_step;
                self.redraw(
                    exposed_image,
                    secondary_image,
                    audio_buffer,
                    lower,
                    upper.min(audio_buffer.upper / sample_step * sample_step),
                );
            }
        }

        #[cfg(feature = "dump-waveform")]
        {
            let mut output_file = File::create(format!(
                "{}/waveform_{}_{}.png",
                WAVEFORM_DUMP_DIR,
                Utc::now().format("%H:%M:%S%.6f"),
                self.id,
            )).unwrap();
            self.exposed_image
                .as_ref()
                .unwrap()
                .write_to_png(&mut output_file)
                .unwrap();
        }

        self.is_ready = true;
    }
// Render the waveform within the provided limits.
// This function is called from a working buffer
// which means that self.exposed_image is the image
// that was previously exposed to the UI.
// This also means that we can safely deal with both
// images since none of them is exposed at this very moment.
// The rendering process reuses the previously rendered image
// whenever possible.
Render the waveform within the provided limits.
This function is called from a working buffer
which means that self.exposed_image is the image
that was previously exposed to the UI.
This also means that we can safely deal with both
images since none of them is exposed at this very moment.
The rendering process reuses the previously rendered image
whenever possible.
Render the waveform within the provided limits . This function is called from a working buffer which means that self . exposed_image is the image that was previously exposed to the UI . This also means that we can safely deal with both images since none of them is exposed at this very moment . The rendering process reuses the previously rendered image whenever possible .
pub fn render(&mut self, audio_buffer: &AudioBuffer, lower: usize, upper: usize) {
        #[cfg(feature = "profile-waveform-image")]
        let start = Utc::now();
        // Align requested lower and upper sample bounds in order to keep
        // a steady offset between redraws. This allows using the same samples
        // for a given req_step_duration and avoiding flickering
        // between redraws.
        let mut lower = lower / self.sample_step * self.sample_step;
        let upper = upper / self.sample_step * self.sample_step;
        if audio_buffer.eos && upper == audio_buffer.upper
            || self.contains_eos
                && (upper == self.upper || (!self.force_redraw && lower >= self.lower))
        {
            // reached eos or image already contains eos and won't change
            if !self.contains_eos {
                debug!(
                    concat!(
                        "{}_render setting contains_eos. ",
                        "Requested [{}, {}], current [{}, {}], force_redraw: {}",
                    ),
                    self.id,
                    lower,
                    upper,
                    self.lower,
                    self.upper,
                    self.force_redraw,
                );
                self.contains_eos = true;
            }
        } else if self.contains_eos {
            self.contains_eos = false;
            debug!(
                concat!(
                    "{}_render clearing contains_eos. ",
                    "Requested [{}, {}], current [{}, {}], force_redraw {} ",
                    "audio_buffer.eos {}",
                ),
                self.id,
                lower,
                upper,
                self.lower,
                self.upper,
                self.force_redraw,
                audio_buffer.eos,
            );
        }
        if lower < audio_buffer.lower {
            // first sample might be smaller than audio_buffer.lower
            // due to alignement on sample_step
            debug!(
                "{}_render lower {} is less than buffer.lower {}",
                self.id, lower, audio_buffer.lower,
            );
            lower += self.sample_step;
        }
        if lower >= upper {
            // can't draw current range
            // reset WaveformImage state
            debug!(
                "{}_render lower {} greater or equal upper {}",
                self.id, lower, upper
            );
            self.lower = 0;
            self.upper = 0;
            self.first = None;
            self.last = None;
            self.contains_eos = false;
            self.is_ready = false;
            return;
        }
        if upper < lower + 2 * self.sample_step {
            debug!(
                "{}_render range [{}, {}] too small for sample_step: {}",
                self.id, lower, upper, self.sample_step,
            );
            return;
        }
        self.force_redraw |= !self.is_ready;
        if !self.force_redraw && lower >= self.lower && upper <= self.upper {
            // target extraction fits in previous extraction
            return;
        } else if upper < self.lower || lower > self.upper {
            // current samples extraction doesn't overlap with samples in previous image
            self.force_redraw = true;
            debug!(
                concat!(
                    "{}_render no overlap self.lower {}, ",
                    "self.upper {}, lower {}, upper {}",
                ),
                self.id,
                self.lower,
                self.upper,
                lower,
                upper,
            );
        }
        let (exposed_image, secondary_image) = {
            let target_width = if self.image_width > 0 {
                self.image_width
                    .max(((upper - lower) * self.x_step / self.sample_step) as i32)
            } else {
                INIT_WIDTH.max(((upper - lower) * self.x_step / self.sample_step) as i32)
            };
            if (target_width == self.image_width && self.req_height == self.image_height)
                || (self.force_redraw && target_width <= self.image_width
                    && self.req_height == self.image_height)
            {
                // expected dimensions fit in current image => reuse it
                (
                    self.exposed_image.take().unwrap(),
                    self.secondary_image.take().unwrap(),
                )
            } else {
                // can't reuse => create new images and force redraw
                self.force_redraw = true;
                self.image_width = target_width;
                self.image_width_f = f64::from(target_width);
                self.image_height = self.req_height;
                self.half_range = f64::from(self.req_height / 2);
                self.full_range = f64::from(self.req_height);
                debug!(
                    "{}_render new images w {}, h {}",
                    self.id, target_width, self.req_height
                );
                (
                    cairo::ImageSurface::create(
                        // exposed_image
                        cairo::Format::Rgb24,
                        target_width,
                        self.req_height,
                    ).expect(&format!(
                        "WaveformBuffer.render: couldn't create image surface with width {}",
                        target_width,
                    )),
                    cairo::ImageSurface::create(
                        // will be used as secondary_image
                        cairo::Format::Rgb24,
                        target_width,
                        self.req_height,
                    ).unwrap(), // exposed_image could be created with same dimensions
                )
            }
        };
        if self.force_redraw {
            // Initialization or resolution has changed or seek requested
            // redraw the whole range from the audio buffer
            self.redraw(exposed_image, secondary_image, audio_buffer, lower, upper);
        } else if lower < self.lower {
            // can append samples before previous first sample
            if self.first.is_some() {
                // first sample position is known
                // shift previous image to the right
                // and append samples to the left
                self.append_left(exposed_image, secondary_image, audio_buffer, lower);
            } else {
                // first sample position is unknown
                // => force redraw
                warn!("{}_append left first sample unknown => redrawing", self.id);
                let sample_step = self.sample_step;
                self.redraw(
                    exposed_image,
                    secondary_image,
                    audio_buffer,
                    lower,
                    upper.min(audio_buffer.upper / sample_step * sample_step),
                );
            }
        } else if upper > self.upper {
            // can append samples after previous last sample
            if self.last.is_some() {
                // last sample position is known
                // shift previous image to the left (if necessary)
                // and append missing samples to the right
                // update lower in case a call to append_left
                // ends up adding nothing
                let lower = lower.max(self.lower);
                self.append_right(exposed_image, secondary_image, audio_buffer, lower, upper);
            } else {
                // last sample position is unknown
                // => force redraw
                warn!("{}_append right last sample unknown => redrawing", self.id);
                let sample_step = self.sample_step;
                self.redraw(
                    exposed_image,
                    secondary_image,
                    audio_buffer,
                    lower,
                    upper.min(audio_buffer.upper / sample_step * sample_step),
                );
            }
        }
        #[cfg(feature = "dump-waveform")]
        {
            let mut output_file = File::create(format!(
                "{}/waveform_{}_{}.png",
                WAVEFORM_DUMP_DIR,
                Utc::now().format("%H:%M:%S%.6f"),
                self.id,
            )).unwrap();
            self.exposed_image
                .as_ref()
                .unwrap()
                .write_to_png(&mut output_file)
                .unwrap();
        }
        self.is_ready = true;
    }
pub fn render ( & mut self , audio_buffer : & AudioBuffer , lower : usize , upper : usize ) { # [ cfg ( feature " " ) ] let start = Utc :: now ( ) ; // Align requested lower and upper sample bounds in order to keep // a steady offset between redraws. This allows using the same samples // for a given req_step_duration and avoiding flickering // between redraws. let mut lower = lower / self . sample_step * self . sample_step ; let upper = upper / self . sample_step * self . sample_step ; if audio_buffer . eos && upper == audio_buffer . upper || self . contains_eos && ( upper == self . upper || ( ! self . force_redraw && lower >= self . lower ) ) { // reached eos or image already contains eos and won't change if ! self . contains_eos { debug ! ( concat ( " " " " ) self id lower upper self lower self upper self force_redraw ) ; self . contains_eos = true ; } } else if self . contains_eos { self . contains_eos = false ; debug ! ( concat ( " " " " " " ) self id lower upper self lower self upper self force_redraw audio_buffer eos ) ; } if lower < audio_buffer . lower { // first sample might be smaller than audio_buffer.lower // due to alignement on sample_step debug ! ( " " self id lower audio_buffer lower ) ; lower += self . sample_step ; } if lower >= upper { // can't draw current range // reset WaveformImage state debug ! ( " " self id lower upper ) ; self . lower = 0 ; self . upper = 0 ; self . first = None ; self . last = None ; self . contains_eos = false ; self . is_ready = false ; return ; } if upper < lower + 2 * self . sample_step { debug ! ( " " self id lower upper self sample_step ) ; return ; } self . force_redraw |= ! self . is_ready ; if ! self . force_redraw && lower >= self . lower && upper <= self . upper { // target extraction fits in previous extraction return ; } else if upper < self . lower || lower > self . upper { // current samples extraction doesn't overlap with samples in previous image self . force_redraw = true ; debug ! ( concat ( " " " " ) self id self lower self upper lower upper ) ; } let ( exposed_image , secondary_image ) = { let target_width = if self . image_width > 0 { self . image_width . max ( ( ( upper - lower ) * self . x_step / self . sample_step ) as i32 ) } else { INIT_WIDTH . max ( ( ( upper - lower ) * self . x_step / self . sample_step ) as i32 ) } ; if ( target_width == self . image_width && self . req_height == self . image_height ) || ( self . force_redraw && target_width <= self . image_width && self . req_height == self . image_height ) { // expected dimensions fit in current image => reuse it ( self . exposed_image . take ( ) . unwrap ( ) , self . secondary_image . take ( ) . unwrap ( ) , ) } else { // can't reuse => create new images and force redraw self . force_redraw = true ; self . image_width = target_width ; self . image_width_f = f64 :: from ( target_width ) ; self . image_height = self . req_height ; self . half_range = f64 :: from ( self . req_height / 2 ) ; self . full_range = f64 :: from ( self . req_height ) ; debug ! ( " " self id target_width self req_height ) ; ( cairo :: ImageSurface :: create ( // exposed_image cairo :: Format :: Rgb24 , target_width , self . req_height , ) . expect ( & format ! ( " " target_width ) ) , cairo :: ImageSurface :: create ( // will be used as secondary_image cairo :: Format :: Rgb24 , target_width , self . req_height , ) . unwrap ( ) , // exposed_image could be created with same dimensions ) } } ; if self . force_redraw { // Initialization or resolution has changed or seek requested // redraw the whole range from the audio buffer self . redraw ( exposed_image , secondary_image , audio_buffer , lower , upper ) ; } else if lower < self . lower { // can append samples before previous first sample if self . first . is_some ( ) { // first sample position is known // shift previous image to the right // and append samples to the left self . append_left ( exposed_image , secondary_image , audio_buffer , lower ) ; } else { // first sample position is unknown // => force redraw warn ! ( " " self id ) ; let sample_step = self . sample_step ; self . redraw ( exposed_image , secondary_image , audio_buffer , lower , upper . min ( audio_buffer . upper / sample_step * sample_step ) , ) ; } } else if upper > self . upper { // can append samples after previous last sample if self . last . is_some ( ) { // last sample position is known // shift previous image to the left (if necessary) // and append missing samples to the right // update lower in case a call to append_left // ends up adding nothing let lower = lower . max ( self . lower ) ; self . append_right ( exposed_image , secondary_image , audio_buffer , lower , upper ) ; } else { // last sample position is unknown // => force redraw warn ! ( " " self id ) ; let sample_step = self . sample_step ; self . redraw ( exposed_image , secondary_image , audio_buffer , lower , upper . min ( audio_buffer . upper / sample_step * sample_step ) , ) ; } } # [ cfg ( feature " " ) ] { let mut output_file = File :: create ( format ! ( " " WAVEFORM_DUMP_DIR Utc now ( ) format ( " " ) self id ) ) . unwrap ( ) ; self . exposed_image . as_ref ( ) . unwrap ( ) . write_to_png ( & mut output_file ) . unwrap ( ) ; } self . is_ready = true ; }
Render the waveform within the provided limits.
Render the waveform within the provided limits .
&mut self
audio_buffer
&AudioBuffer
lower
usize
upper
usize
&mut self
audio_buffer
&AudioBuffer
lower
usize
upper
usize