spek

Acoustic spectrum analyser
git clone http://git.hanabi.in/repos/spek.git
Log | Files | Refs | README

commit 71a8cccb4b7c8ad33b2c7b998716d03839f331b6
parent 3feb64543e97ca48c37c57aa81c94509fff0f549
Author: Alexander Kojevnikov <alexander@kojevnikov.com>
Date:   Sun, 16 May 2010 20:51:55 +1000

Factor out the ruler code

Diffstat:
Msrc/Makefile.am | 1+
Asrc/spek-ruler.vala | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/spek-spectrogram.vala | 56+++++++++++---------------------------------------------
3 files changed, 99 insertions(+), 45 deletions(-)

diff --git a/src/Makefile.am b/src/Makefile.am @@ -2,6 +2,7 @@ bin_PROGRAMS = spek spek_SOURCES = \ spek.vala \ + spek-ruler.vala \ spek-source.vala \ spek-spectrogram.vala \ spek-window.vala diff --git a/src/spek-ruler.vala b/src/spek-ruler.vala @@ -0,0 +1,86 @@ +/* spek-spectrogram.vala + * + * Copyright (C) 2010 Alexander Kojevnikov <alexander@kojevnikov.com> + * + * Spek is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Spek is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Spek. If not, see <http://www.gnu.org/licenses/>. + */ + +using Cairo; + +namespace Spek { + class Ruler : GLib.Object { + + private string sample_label; + private int[] factors; + private int units; + private UnitToPixel unit_to_pixel; + private FormatTick format_tick; + + public delegate double UnitToPixel (int unit); + public delegate string FormatTick (int unit); + + public Ruler ( + string sample_label, int[] factors, int units, + UnitToPixel unit_to_pixel, FormatTick format_tick) { + this.sample_label = sample_label; + this.factors = factors; + this.units = units; + this.unit_to_pixel = unit_to_pixel; + this.format_tick = format_tick; + } + + public void draw (Context cr) { + // Mesure the sample label. + TextExtents ext; + cr.text_extents (sample_label, out ext); + var label_width = ext.width; + + // Select the factor to use, we want some space between the labels. + int factor = 0; + foreach (var f in factors) { + if (unit_to_pixel (f) >= 1.5 * label_width) { + factor = f; + break; + } + } + + // Add the ticks. + int[] ticks = { 0, units }; + if (factor > 0) { + for (var tick = factor; tick < units; tick += factor) { + if (unit_to_pixel (units - tick) < label_width) { + break; + } + ticks += tick; + } + // TODO: `ticks = ticks[0:-1]` crashes, file a bug. + } + + // Draw the ticks. + double GAP = 10; + double TICK_LEN = 4; + foreach (var tick in ticks) { + var label = format_tick (tick); + var pos = unit_to_pixel (tick); + cr.text_extents (label, out ext); + // TODO: use font measurements instead ext.height + cr.move_to (pos - ext.width / 2, GAP + ext.height); + cr.show_text (label); + cr.move_to (pos, 0); + cr.rel_line_to (0, TICK_LEN); + cr.stroke (); + } + } + } +} +\ No newline at end of file diff --git a/src/spek-spectrogram.vala b/src/spek-spectrogram.vala @@ -123,46 +123,17 @@ namespace Spek { cr.select_font_face ("sans-serif", FontSlant.NORMAL, FontWeight.NORMAL); cr.set_font_size (10.0); - // Mesure the label text. - TextExtents ext; - cr.text_extents ("00:00", out ext); - double label_width = ext.width; - - // Select the factor to use, we want some space between the labels. - int duration_seconds = (int) (source.duration / 1000000000); - int[] time_factors = {1, 2, 5, 10, 20, 30, 1*60, 2*60, 5*60, 10*60, 20*60, 30*60}; - int time_factor = 0; - foreach (var factor in time_factors) { - if (time_to_px (factor, w, duration_seconds) >= 1.5 * label_width) { - time_factor = factor; - break; - } - } - - // Add the ticks. - int[] ticks = { 0, duration_seconds }; - if (time_factor > 0) { - for (var tick = time_factor; tick < duration_seconds; tick += time_factor) { - if (time_to_px (duration_seconds - tick, w, duration_seconds) < label_width) { - break; - } - ticks += tick; - } - // TODO: `ticks = ticks[0:-1]` crashes, file a bug. - } - - // Draw the ticks. - foreach (var tick in ticks) { - var label = "%d:%02d".printf (tick / 60, tick % 60); - var pos = PADDING + time_to_px (tick, w, duration_seconds); - cr.text_extents (label, out ext); - // TODO: use font measurements instead ext.height - cr.move_to (pos - ext.width / 2, h - PADDING + GAP + ext.height); - cr.show_text (label); - cr.move_to (pos, h - PADDING); - cr.rel_line_to (0, 4); - cr.stroke (); - } + // Time ruler. + var duration_seconds = (int) (source.duration / 1000000000); + var time_ruler = new Ruler ( + "00:00", + {1, 2, 5, 10, 20, 30, 1*60, 2*60, 5*60, 10*60, 20*60, 30*60}, + duration_seconds, + unit => (w - 2 * PADDING) * unit / duration_seconds, + unit => "%d:%02d".printf (unit / 60, unit % 60)); + cr.translate (PADDING, h - PADDING); + time_ruler.draw (cr); + cr.identity_matrix (); } // Border around the spectrogram. @@ -180,11 +151,6 @@ namespace Spek { cr.identity_matrix (); } - // TODO: factor out the ruler logic and pass this as an anonymous method. - private double time_to_px (int time, double w, int duration_seconds) { - return (w - 2 * PADDING) * time / duration_seconds; - } - private void put_pixel (ImageSurface surface, int x, int y, uint32 color) { var i = y * surface.get_stride () + x * 4; unowned uchar[] data = surface.get_data ();