X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fcanvas-waveview.c;h=1e28a2733090f00863c221fa8173349125e3a30f;hb=a49b0f53aa2d83a9291c35f323f90b46d8869390;hp=ce46811d2c33e97e7d6b3f030bc010ea0e9fdf92;hpb=209d967b1bb80a9735d690d8f4f0455ecb9970ca;p=ardour.git diff --git a/gtk2_ardour/canvas-waveview.c b/gtk2_ardour/canvas-waveview.c index ce46811d2c..1e28a27330 100644 --- a/gtk2_ardour/canvas-waveview.c +++ b/gtk2_ardour/canvas-waveview.c @@ -1,149 +1,342 @@ /* - Copyright (C) 2000-2002 Paul Davis + Copyright (C) 2000-2002 Paul Davis - This program 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 2 of the License, or - (at your option) any later version. + This program 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 2 of the License, or + (at your option) any later version. - This program 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. + This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id$ + $Id$ */ #include #include -#include +#include +#include #include #include +#include -#include +#include "ardour/dB.h" +#include "logmeter.h" #include "canvas-waveview.h" #include "rgb_macros.h" +/* POSIX guarantees casting between void* and function pointers, ISO C doesn't + * We can work around warnings by going one step deeper in our casts + */ +#ifdef _POSIX_VERSION +#define POSIX_FUNC_PTR_CAST(type, object) *((type*) &(object)) +#endif // _POSIX_VERSION + +extern void c_stacktrace(); + enum { - ARG_0, - ARG_DATA_SRC, - ARG_CHANNEL, - ARG_LENGTH_FUNCTION, - ARG_PEAK_FUNCTION, - ARG_GAIN_FUNCTION, - ARG_GAIN_SRC, - ARG_CACHE, - ARG_CACHE_UPDATER, - ARG_SAMPLES_PER_PIXEL, - ARG_AMPLITUDE_ABOVE_AXIS, - ARG_X, - ARG_Y, - ARG_HEIGHT, - ARG_WAVE_COLOR, - ARG_RECTIFIED, - ARG_SOURCEFILE_LENGTH_FUNCTION, - ARG_REGION_START + PROP_0, + PROP_DATA_SRC, + PROP_CHANNEL, + PROP_LENGTH_FUNCTION, + PROP_SOURCEFILE_LENGTH_FUNCTION, + PROP_PEAK_FUNCTION, + PROP_GAIN_FUNCTION, + PROP_GAIN_SRC, + PROP_CACHE, + PROP_CACHE_UPDATER, + PROP_SAMPLES_PER_UNIT, + PROP_AMPLITUDE_ABOVE_AXIS, + PROP_X, + PROP_Y, + PROP_HEIGHT, + PROP_WAVE_COLOR, + PROP_CLIP_COLOR, + PROP_ZERO_COLOR, + PROP_FILL_COLOR, + PROP_FILLED, + PROP_RECTIFIED, + PROP_ZERO_LINE, + PROP_REGION_START, + PROP_LOGSCALED, }; -static void gtk_canvas_waveview_class_init (GtkCanvasWaveViewClass *class); -static void gtk_canvas_waveview_init (GtkCanvasWaveView *waveview); -static void gtk_canvas_waveview_set_arg (GtkObject *object, - GtkArg *arg, - guint arg_id); -static void gtk_canvas_waveview_get_arg (GtkObject *object, - GtkArg *arg, - guint arg_id); +static void gnome_canvas_waveview_class_init (GnomeCanvasWaveViewClass *class); -static void gtk_canvas_waveview_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags); -static void gtk_canvas_waveview_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2); -static double gtk_canvas_waveview_point (GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item); +static void gnome_canvas_waveview_init (GnomeCanvasWaveView *waveview); -static void gtk_canvas_waveview_render (GtkCanvasItem *item, GtkCanvasBuf *buf); -static void gtk_canvas_waveview_draw (GtkCanvasItem *item, GdkDrawable *drawable, int x, int y, int w, int h); +static void gnome_canvas_waveview_destroy (GtkObject *object); -static void gtk_canvas_waveview_set_data_src (GtkCanvasWaveView *, void *); -static void gtk_canvas_waveview_set_channel (GtkCanvasWaveView *, guint32); +static void gnome_canvas_waveview_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void gnome_canvas_waveview_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); -static gint32 gtk_canvas_waveview_ensure_cache (GtkCanvasWaveView *waveview, gulong start_sample, gulong end_sample); +static void gnome_canvas_waveview_update (GnomeCanvasItem *item, + double *affine, + ArtSVP *clip_path, + int flags); -static GtkCanvasItemClass *parent_class; +static void gnome_canvas_waveview_bounds (GnomeCanvasItem *item, + double *x1, + double *y1, + double *x2, + double *y2); -GtkType -gtk_canvas_waveview_get_type (void) -{ - static GtkType waveview_type = 0; +static double gnome_canvas_waveview_point (GnomeCanvasItem *item, + double x, + double y, + int cx, + int cy, + GnomeCanvasItem **actual_item); - if (!waveview_type) { - GtkTypeInfo waveview_info = { - "GtkCanvasWaveView", - sizeof (GtkCanvasWaveView), - sizeof (GtkCanvasWaveViewClass), - (GtkClassInitFunc) gtk_canvas_waveview_class_init, - (GtkObjectInitFunc) gtk_canvas_waveview_init, - NULL, /* reserved_1 */ - NULL, /* reserved_2 */ - (GtkClassInitFunc) NULL - }; +static void gnome_canvas_waveview_render (GnomeCanvasItem *item, + GnomeCanvasBuf *buf); - waveview_type = gtk_type_unique (gtk_canvas_item_get_type (), &waveview_info); - } +static void gnome_canvas_waveview_draw (GnomeCanvasItem *item, + GdkDrawable *drawable, + int x, + int y, + int w, + int h); - return waveview_type; -} +static void gnome_canvas_waveview_set_data_src (GnomeCanvasWaveView *, + void *); + +static void gnome_canvas_waveview_set_channel (GnomeCanvasWaveView *, + guint32); + +static guint32 gnome_canvas_waveview_ensure_cache (GnomeCanvasWaveView *waveview, + gulong start_sample, + gulong end_sample); + +static GnomeCanvasItemClass *parent_class; + +GType +gnome_canvas_waveview_get_type (void) +{ + static GType waveview_type; + + if (!waveview_type) { + static const GTypeInfo object_info = { + sizeof (GnomeCanvasWaveViewClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gnome_canvas_waveview_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GnomeCanvasWaveView), + 0, /* n_preallocs */ + (GInstanceInitFunc) gnome_canvas_waveview_init, + NULL /* value_table */ + }; + + waveview_type = g_type_register_static (GNOME_TYPE_CANVAS_ITEM, "GnomeCanvasWaveView", + &object_info, 0); + } + + return waveview_type; + } static void -gtk_canvas_waveview_class_init (GtkCanvasWaveViewClass *class) +gnome_canvas_waveview_class_init (GnomeCanvasWaveViewClass *class) { - GtkObjectClass *object_class; - GtkCanvasItemClass *item_class; - - object_class = (GtkObjectClass *) class; - item_class = (GtkCanvasItemClass *) class; - - parent_class = gtk_type_class (gtk_canvas_item_get_type ()); - - gtk_object_add_arg_type ("GtkCanvasWaveView::data_src", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_DATA_SRC); - gtk_object_add_arg_type ("GtkCanvasWaveView::channel", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_CHANNEL); - gtk_object_add_arg_type ("GtkCanvasWaveView::length_function", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_LENGTH_FUNCTION); - gtk_object_add_arg_type ("GtkCanvasWaveView::sourcefile_length_function", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_SOURCEFILE_LENGTH_FUNCTION); - gtk_object_add_arg_type ("GtkCanvasWaveView::peak_function", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_PEAK_FUNCTION); - gtk_object_add_arg_type ("GtkCanvasWaveView::gain_function", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_GAIN_FUNCTION); - gtk_object_add_arg_type ("GtkCanvasWaveView::gain_src", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_GAIN_SRC); - gtk_object_add_arg_type ("GtkCanvasWaveView::cache", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_CACHE); - gtk_object_add_arg_type ("GtkCanvasWaveView::cache_updater", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_CACHE_UPDATER); - gtk_object_add_arg_type ("GtkCanvasWaveView::samples_per_unit", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_SAMPLES_PER_PIXEL); - gtk_object_add_arg_type ("GtkCanvasWaveView::amplitude_above_axis", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_AMPLITUDE_ABOVE_AXIS); - gtk_object_add_arg_type ("GtkCanvasWaveView::x", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X); - gtk_object_add_arg_type ("GtkCanvasWaveView::y", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y); - gtk_object_add_arg_type ("GtkCanvasWaveView::height", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_HEIGHT); - gtk_object_add_arg_type ("GtkCanvasWaveView::wave_color", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_WAVE_COLOR); - gtk_object_add_arg_type ("GtkCanvasWaveView::rectified", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_RECTIFIED); - gtk_object_add_arg_type ("GtkCanvasWaveView::region_start", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_REGION_START); - - object_class->set_arg = gtk_canvas_waveview_set_arg; - object_class->get_arg = gtk_canvas_waveview_get_arg; - - item_class->update = gtk_canvas_waveview_update; - item_class->bounds = gtk_canvas_waveview_bounds; - item_class->point = gtk_canvas_waveview_point; - item_class->render = gtk_canvas_waveview_render; - item_class->draw = gtk_canvas_waveview_draw; + GObjectClass *gobject_class; + GtkObjectClass *object_class; + GnomeCanvasItemClass *item_class; + + gobject_class = (GObjectClass *) class; + object_class = (GtkObjectClass *) class; + item_class = (GnomeCanvasItemClass *) class; + + parent_class = g_type_class_peek_parent (class); + + gobject_class->set_property = gnome_canvas_waveview_set_property; + gobject_class->get_property = gnome_canvas_waveview_get_property; + + g_object_class_install_property + (gobject_class, + PROP_DATA_SRC, + g_param_spec_pointer ("data_src", NULL, NULL, + (G_PARAM_READABLE | G_PARAM_WRITABLE))); + + g_object_class_install_property + (gobject_class, + PROP_CHANNEL, + g_param_spec_uint ("channel", NULL, NULL, + 0, G_MAXUINT, 0, + (G_PARAM_READABLE | G_PARAM_WRITABLE))); + + g_object_class_install_property + (gobject_class, + PROP_LENGTH_FUNCTION, + g_param_spec_pointer ("length_function", NULL, NULL, + (G_PARAM_READABLE | G_PARAM_WRITABLE))); + + g_object_class_install_property + (gobject_class, + PROP_SOURCEFILE_LENGTH_FUNCTION, + g_param_spec_pointer ("sourcefile_length_function", NULL, NULL, + (G_PARAM_READABLE | G_PARAM_WRITABLE))); + + g_object_class_install_property + (gobject_class, + PROP_PEAK_FUNCTION, + g_param_spec_pointer ("peak_function", NULL, NULL, + (G_PARAM_READABLE | G_PARAM_WRITABLE))); + + g_object_class_install_property + (gobject_class, + PROP_GAIN_FUNCTION, + g_param_spec_pointer ("gain_function", NULL, NULL, + (G_PARAM_READABLE | G_PARAM_WRITABLE))); + + g_object_class_install_property + (gobject_class, + PROP_GAIN_SRC, + g_param_spec_pointer ("gain_src", NULL, NULL, + (G_PARAM_READABLE | G_PARAM_WRITABLE))); + + g_object_class_install_property + (gobject_class, + PROP_CACHE, + g_param_spec_pointer ("cache", NULL, NULL, + (G_PARAM_READABLE | G_PARAM_WRITABLE))); + + g_object_class_install_property + (gobject_class, + PROP_CACHE_UPDATER, + g_param_spec_boolean ("cache_updater", NULL, NULL, + FALSE, + (G_PARAM_READABLE | G_PARAM_WRITABLE))); + + g_object_class_install_property + (gobject_class, + PROP_SAMPLES_PER_UNIT, + g_param_spec_double ("samples_per_unit", NULL, NULL, + 0.0, G_MAXDOUBLE, 0.0, + (G_PARAM_READABLE | G_PARAM_WRITABLE))); + + g_object_class_install_property + (gobject_class, + PROP_AMPLITUDE_ABOVE_AXIS, + g_param_spec_double ("amplitude_above_axis", NULL, NULL, + 0.0, G_MAXDOUBLE, 0.0, + (G_PARAM_READABLE | G_PARAM_WRITABLE))); + + g_object_class_install_property + (gobject_class, + PROP_X, + g_param_spec_double ("x", NULL, NULL, + 0.0, G_MAXDOUBLE, 0.0, + (G_PARAM_READABLE | G_PARAM_WRITABLE))); + + g_object_class_install_property + (gobject_class, + PROP_Y, + g_param_spec_double ("y", NULL, NULL, + 0.0, G_MAXDOUBLE, 0.0, + (G_PARAM_READABLE | G_PARAM_WRITABLE))); + + g_object_class_install_property + (gobject_class, + PROP_HEIGHT, + g_param_spec_double ("height", NULL, NULL, + 0.0, G_MAXDOUBLE, 0.0, + (G_PARAM_READABLE | G_PARAM_WRITABLE))); + + g_object_class_install_property + (gobject_class, + PROP_WAVE_COLOR, + g_param_spec_uint ("wave_color", NULL, NULL, + 0, G_MAXUINT, 0, + (G_PARAM_READABLE | G_PARAM_WRITABLE))); + + g_object_class_install_property + (gobject_class, + PROP_CLIP_COLOR, + g_param_spec_uint ("clip_color", NULL, NULL, + 0, G_MAXUINT, 0, + (G_PARAM_READABLE | G_PARAM_WRITABLE))); + + g_object_class_install_property + (gobject_class, + PROP_ZERO_COLOR, + g_param_spec_uint ("zero_color", NULL, NULL, + 0, G_MAXUINT, 0, + (G_PARAM_READABLE | G_PARAM_WRITABLE))); + + g_object_class_install_property + (gobject_class, + PROP_FILL_COLOR, + g_param_spec_uint ("fill_color", NULL, NULL, + 0, G_MAXUINT, 0, + (G_PARAM_READABLE | G_PARAM_WRITABLE))); + + g_object_class_install_property + (gobject_class, + PROP_FILLED, + g_param_spec_boolean ("filled", NULL, NULL, + FALSE, + (G_PARAM_READABLE | G_PARAM_WRITABLE))); + + g_object_class_install_property + (gobject_class, + PROP_RECTIFIED, + g_param_spec_boolean ("rectified", NULL, NULL, + FALSE, + (G_PARAM_READABLE | G_PARAM_WRITABLE))); + + g_object_class_install_property + (gobject_class, + PROP_ZERO_LINE, + g_param_spec_boolean ("zero_line", NULL, NULL, + FALSE, + (G_PARAM_READABLE | G_PARAM_WRITABLE))); + + g_object_class_install_property + (gobject_class, + PROP_LOGSCALED, + g_param_spec_boolean ("logscaled", NULL, NULL, + FALSE, + (G_PARAM_READABLE | G_PARAM_WRITABLE))); + + g_object_class_install_property + (gobject_class, + PROP_REGION_START, + g_param_spec_uint ("region_start", NULL, NULL, + 0, G_MAXUINT, 0, + (G_PARAM_READABLE | G_PARAM_WRITABLE))); + + object_class->destroy = gnome_canvas_waveview_destroy; + + item_class->update = gnome_canvas_waveview_update; + item_class->bounds = gnome_canvas_waveview_bounds; + item_class->point = gnome_canvas_waveview_point; + item_class->render = gnome_canvas_waveview_render; + item_class->draw = gnome_canvas_waveview_draw; } -GtkCanvasWaveViewCache* -gtk_canvas_waveview_cache_new () +GnomeCanvasWaveViewCache* +gnome_canvas_waveview_cache_new () { - GtkCanvasWaveViewCache *c; + GnomeCanvasWaveViewCache *c; - c = g_malloc (sizeof (GtkCanvasWaveViewCache)); + c = g_malloc (sizeof (GnomeCanvasWaveViewCache)); c->allocated = 2048; - c->data = g_malloc (sizeof (GtkCanvasWaveViewCacheEntry) * c->allocated); + c->data = g_malloc (sizeof (GnomeCanvasWaveViewCacheEntry) * c->allocated); c->data_size = 0; c->start = 0; c->end = 0; @@ -152,14 +345,14 @@ gtk_canvas_waveview_cache_new () } void -gtk_canvas_waveview_cache_destroy (GtkCanvasWaveViewCache* cache) +gnome_canvas_waveview_cache_destroy (GnomeCanvasWaveViewCache* cache) { g_free (cache->data); g_free (cache); } static void -gtk_canvas_waveview_init (GtkCanvasWaveView *waveview) +gnome_canvas_waveview_init (GnomeCanvasWaveView *waveview) { waveview->x = 0.0; waveview->y = 0.0; @@ -173,6 +366,9 @@ gtk_canvas_waveview_init (GtkCanvasWaveView *waveview) waveview->gain_curve_function = NULL; waveview->gain_src = NULL; waveview->rectified = FALSE; + waveview->logscaled = FALSE; + waveview->filled = TRUE; + waveview->zero_line = FALSE; waveview->region_start = 0; waveview->samples_per_unit = 1.0; waveview->amplitude_above_axis = 1.0; @@ -180,15 +376,32 @@ gtk_canvas_waveview_init (GtkCanvasWaveView *waveview) waveview->screen_width = gdk_screen_width (); waveview->reload_cache_in_render = FALSE; - waveview->wave_color = RGBA_TO_UINT(44,35,126,255); + waveview->wave_color = 0; + waveview->clip_color = 0; + waveview->zero_color = 0; + waveview->fill_color = 0; +} + +static void +gnome_canvas_waveview_destroy (GtkObject *object) +{ + GnomeCanvasWaveView *waveview; - GTK_CANVAS_ITEM(waveview)->object.flags |= GTK_CANVAS_ITEM_NO_AUTO_REDRAW; + g_return_if_fail (object != NULL); + g_return_if_fail (GNOME_IS_CANVAS_WAVEVIEW (object)); + + waveview = GNOME_CANVAS_WAVEVIEW (object); + + if (GTK_OBJECT_CLASS (parent_class)->destroy) + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); } #define DEBUG_CACHE 0 +#undef CACHE_MEMMOVE_OPTIMIZATION -static gint32 -gtk_canvas_waveview_ensure_cache (GtkCanvasWaveView *waveview, gulong start_sample, gulong end_sample) +/** @return cache index of start_sample within the cache */ +static guint32 +gnome_canvas_waveview_ensure_cache (GnomeCanvasWaveView *waveview, gulong start_sample, gulong end_sample) { gulong required_cache_entries; gulong rf1, rf2,rf3, required_frames; @@ -197,11 +410,13 @@ gtk_canvas_waveview_ensure_cache (GtkCanvasWaveView *waveview, gulong start_samp gulong npeaks; gulong offset; gulong ostart; - gulong present_frames; - gulong present_entries; gulong copied; - GtkCanvasWaveViewCache *cache; + GnomeCanvasWaveViewCache *cache; float* gain; +#ifdef CACHE_MEMMOVE_OPTIMIZATION + gulong present_frames; + gulong present_entries; +#endif cache = waveview->cache; @@ -209,12 +424,13 @@ gtk_canvas_waveview_ensure_cache (GtkCanvasWaveView *waveview, gulong start_samp end_sample = end_sample + waveview->region_start; #if DEBUG_CACHE // printf("waveview->region_start == %lu\n",waveview->region_start); - printf ("=> 0x%x cache @ 0x%x range: %lu - %lu request: %lu - %lu (%lu frames)\n", + // c_stacktrace (); + printf ("\n\n=> 0x%x cache @ 0x%x range: %lu - %lu request: %lu - %lu (%lu frames)\n", waveview, cache, cache->start, cache->end, start_sample, end_sample, end_sample - start_sample); #endif - + if (cache->start <= start_sample && cache->end >= end_sample) { #if DEBUG_CACHE // printf ("0x%x: cache hit for %lu-%lu (cache holds: %lu-%lu\n", @@ -224,13 +440,13 @@ gtk_canvas_waveview_ensure_cache (GtkCanvasWaveView *waveview, gulong start_samp } /* make sure the cache is at least twice as wide as the screen width, and put the start sample - in the middle, ensuring that we cover the end_sample. + in the middle, ensuring that we cover the end_sample. */ /* Note the assumption that we have a 1:1 units:pixel ratio for the canvas. Its everywhere ... */ - + half_width = (gulong) floor ((waveview->screen_width * waveview->samples_per_unit)/2.0 + 0.5); - + if (start_sample < half_width) { new_cache_start = 0; } else { @@ -245,12 +461,16 @@ gtk_canvas_waveview_ensure_cache (GtkCanvasWaveView *waveview, gulong start_samp /* but make sure it doesn't extend beyond the end of the source material */ - rf3 = (gulong) (waveview->sourcefile_length_function (waveview->data_src)) + 1; - rf3 -= new_cache_start; + rf3 = (gulong) (waveview->sourcefile_length_function (waveview->data_src, waveview->samples_per_unit)) + 1; + if (rf3 < new_cache_start) { + rf3 = 0; + } else { + rf3 -= new_cache_start; + } #if DEBUG_CACHE - fprintf (stderr, "\n\nAVAILABLE FRAMES = %lu of %lu, start = %lu, sstart = %lu, cstart = %lu\n", - rf3, waveview->sourcefile_length_function (waveview->data_src), + fprintf (stderr, "AVAILABLE FRAMES = %lu of %lu, start = %lu, sstart = %lu, cstart = %lu\n", + rf3, waveview->sourcefile_length_function (waveview->data_src, waveview->samples_per_unit), waveview->region_start, start_sample, new_cache_start); #endif @@ -262,12 +482,12 @@ gtk_canvas_waveview_ensure_cache (GtkCanvasWaveView *waveview, gulong start_samp #if DEBUG_CACHE fprintf (stderr, "new cache = %lu - %lu\n", new_cache_start, new_cache_end); - fprintf(stderr,"required_cach_entries = %lu, samples_per_unit = %f\n", - required_cache_entries,waveview->samples_per_unit); + fprintf(stderr,"required_cach_entries = %lu, samples_per_unit = %f req frames = %lu\n", + required_cache_entries,waveview->samples_per_unit, required_frames); #endif if (required_cache_entries > cache->allocated) { - cache->data = g_realloc (cache->data, sizeof (GtkCanvasWaveViewCacheEntry) * required_cache_entries); + cache->data = g_realloc (cache->data, sizeof (GnomeCanvasWaveViewCacheEntry) * required_cache_entries); cache->allocated = required_cache_entries; // cache->start = 0; // cache->end = 0; @@ -275,9 +495,8 @@ gtk_canvas_waveview_ensure_cache (GtkCanvasWaveView *waveview, gulong start_samp ostart = new_cache_start; -#undef CACHE_MEMMOVE_OPTIMIZATION #ifdef CACHE_MEMMOVE_OPTIMIZATION - + /* data is not entirely in the cache, so go fetch it, making sure to fill the cache */ /* some of the required cache entries are in the cache, but in the wrong @@ -285,32 +504,32 @@ gtk_canvas_waveview_ensure_cache (GtkCanvasWaveView *waveview, gulong start_samp */ if (cache->start < new_cache_start && new_cache_start < cache->end) { - - /* case one: the common area is at the end of the existing cache. move it + + /* case one: the common area is at the end of the existing cache. move it to the beginning of the cache, and set up to refill whatever remains. - - + + wv->cache_start wv->cache_end |-------------------------------------------------------| cache |--------------------------------| requested <-------------------> "present" - new_cache_start new_cache_end + new_cache_start new_cache_end */ - + present_frames = cache->end - new_cache_start; present_entries = (gulong) floor (present_frames / waveview->samples_per_unit); -#if DEBUG_CACHE +#if DEBUG_CACHE fprintf (stderr, "existing material at end of current cache, move to start of new cache\n" "\tcopy from %lu to start\n", cache->data_size - present_entries); #endif memmove (&cache->data[0], &cache->data[cache->data_size - present_entries], - present_entries * sizeof (GtkCanvasWaveViewCacheEntry)); - + present_entries * sizeof (GnomeCanvasWaveViewCacheEntry)); + #if DEBUG_CACHE fprintf (stderr, "satisfied %lu of %lu frames, offset = %lu, will start at %lu (ptr = 0x%x)\n", present_frames, required_frames, present_entries, new_cache_start + present_entries, @@ -324,8 +543,8 @@ gtk_canvas_waveview_ensure_cache (GtkCanvasWaveView *waveview, gulong start_samp } else if (new_cache_end > cache->start && new_cache_end < cache->end) { - /* case two: the common area lives at the beginning of the existing cache. - + /* case two: the common area lives at the beginning of the existing cache. + wv->cache_start wv->cache_end |-----------------------------------------------------| |--------------------------------| @@ -334,15 +553,15 @@ gtk_canvas_waveview_ensure_cache (GtkCanvasWaveView *waveview, gulong start_samp new_cache_start new_cache_end */ - + present_frames = new_cache_end - cache->start; present_entries = (gulong) floor (present_frames / waveview->samples_per_unit); memmove (&cache->data[cache->data_size - present_entries], &cache->data[0], - present_entries * sizeof (GtkCanvasWaveViewCacheEntry)); - -#if DEBUG_CACHE + present_entries * sizeof (GnomeCanvasWaveViewCacheEntry)); + +#if DEBUG_CACHE fprintf (stderr, "existing material at start of current cache, move to start of end cache\n"); #endif @@ -356,7 +575,7 @@ gtk_canvas_waveview_ensure_cache (GtkCanvasWaveView *waveview, gulong start_samp offset = 0; required_frames -= present_frames; - + } else { copied = 0; offset = 0; @@ -371,8 +590,8 @@ gtk_canvas_waveview_ensure_cache (GtkCanvasWaveView *waveview, gulong start_samp // fprintf(stderr,"length == %lu\n",waveview->length_function (waveview->data_src)); // required_frames = MIN (waveview->length_function (waveview->data_src) - new_cache_start, required_frames); + npeaks = (gulong) floor (required_frames / waveview->samples_per_unit); - npeaks = MAX (1, npeaks); required_frames = npeaks * waveview->samples_per_unit; #if DEBUG_CACHE @@ -389,17 +608,21 @@ gtk_canvas_waveview_ensure_cache (GtkCanvasWaveView *waveview, gulong start_samp // start_sample, end_sample); #endif - waveview->peak_function (waveview->data_src, npeaks, new_cache_start, required_frames, cache->data + offset, waveview->channel,waveview->samples_per_unit); + if (required_frames) { + waveview->peak_function (waveview->data_src, npeaks, new_cache_start, required_frames, cache->data + offset, waveview->channel,waveview->samples_per_unit); - /* take into account any copied peaks */ + /* take into account any copied peaks */ - npeaks += copied; + npeaks += copied; + } else { + npeaks = copied; + } if (npeaks < cache->allocated) { #if DEBUG_CACHE fprintf (stderr, "zero fill cache for %lu at %lu\n", cache->allocated - npeaks, npeaks); #endif - memset (&cache->data[npeaks], 0, sizeof (GtkCanvasWaveViewCacheEntry) * (cache->allocated - npeaks)); + memset (&cache->data[npeaks], 0, sizeof (GnomeCanvasWaveViewCacheEntry) * (cache->allocated - npeaks)); cache->data_size = npeaks; } else { cache->data_size = cache->allocated; @@ -418,23 +641,45 @@ gtk_canvas_waveview_ensure_cache (GtkCanvasWaveView *waveview, gulong start_samp } free (gain); - + } - + + /* do optional log scaling. this implementation is not particularly efficient */ + + if (waveview->logscaled) { + guint32 n; + GnomeCanvasWaveViewCacheEntry* buf = cache->data; + + for (n = 0; n < cache->data_size; ++n) { + + if (buf[n].max > 0.0f) { + buf[n].max = alt_log_meter(fast_coefficient_to_dB(buf[n].max)); + } else if (buf[n].max < 0.0f) { + buf[n].max = -alt_log_meter(fast_coefficient_to_dB(-buf[n].max)); + } + + if (buf[n].min > 0.0f) { + buf[n].min = alt_log_meter(fast_coefficient_to_dB(buf[n].min)); + } else if (buf[n].min < 0.0f) { + buf[n].min = -alt_log_meter(fast_coefficient_to_dB(-buf[n].min)); + } + } + } + cache->start = ostart; cache->end = new_cache_end; out: #if DEBUG_CACHE - fprintf (stderr, "return cache index = %d\n", - (gint32) floor ((((double) (start_sample - cache->start)) / waveview->samples_per_unit) + 0.5)); + fprintf (stderr, "return cache index = %d\n", + (guint32) floor ((((double) (start_sample - cache->start)) / waveview->samples_per_unit) + 0.5)); #endif - return (gint32) floor ((((double) (start_sample - cache->start)) / waveview->samples_per_unit) + 0.5); + return (guint32) floor ((((double) (start_sample - cache->start)) / waveview->samples_per_unit) + 0.5); } void -gtk_canvas_waveview_set_data_src (GtkCanvasWaveView *waveview, void *data_src) +gnome_canvas_waveview_set_data_src (GnomeCanvasWaveView *waveview, void *data_src) { if (waveview->cache_updater) { @@ -442,7 +687,7 @@ gtk_canvas_waveview_set_data_src (GtkCanvasWaveView *waveview, void *data_src) waveview->reload_cache_in_render = TRUE; return; } - + waveview->cache->start = 0; waveview->cache->end = 0; } @@ -451,17 +696,17 @@ gtk_canvas_waveview_set_data_src (GtkCanvasWaveView *waveview, void *data_src) } void -gtk_canvas_waveview_set_channel (GtkCanvasWaveView *waveview, guint32 chan) +gnome_canvas_waveview_set_channel (GnomeCanvasWaveView *waveview, guint32 chan) { if (waveview->channel == chan) { return; } - + waveview->channel = chan; } -static void -gtk_canvas_waveview_reset_bounds (GtkCanvasItem *item) +static void +gnome_canvas_waveview_reset_bounds (GnomeCanvasItem *item) { double x1, x2, y1, y2; @@ -470,14 +715,14 @@ gtk_canvas_waveview_reset_bounds (GtkCanvasItem *item) int Ix1, Ix2, Iy1, Iy2; double i2w[6]; - gtk_canvas_waveview_bounds (item, &x1, &y1, &x2, &y2); + gnome_canvas_waveview_bounds (item, &x1, &y1, &x2, &y2); i1.x = x1; i1.y = y1; i2.x = x2; i2.y = y2; - gtk_canvas_item_i2w_affine (item, i2w); + gnome_canvas_item_i2w_affine (item, i2w); art_affine_point (&w1, &i1, i2w); art_affine_point (&w2, &i2, i2w); @@ -486,59 +731,71 @@ gtk_canvas_waveview_reset_bounds (GtkCanvasItem *item) Iy1 = (int) rint(w1.y); Iy2 = (int) rint(w2.y); - gtk_canvas_update_bbox (item, Ix1, Iy1, Ix2, Iy2); + gnome_canvas_update_bbox (item, Ix1, Iy1, Ix2, Iy2); } -/* - * CANVAS CALLBACKS +/* + * CANVAS CALLBACKS */ static void -gtk_canvas_waveview_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) +gnome_canvas_waveview_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) + { - GtkCanvasItem *item; - GtkCanvasWaveView *waveview; - int redraw; - int calc_bounds; + (void) pspec; + + GnomeCanvasItem *item; + GnomeCanvasWaveView *waveview; + int redraw = FALSE; + int calc_bounds = FALSE; - item = GTK_CANVAS_ITEM (object); - waveview = GTK_CANVAS_WAVEVIEW (object); + g_return_if_fail (object != NULL); + g_return_if_fail (GNOME_IS_CANVAS_WAVEVIEW (object)); - redraw = FALSE; - calc_bounds = FALSE; + item = GNOME_CANVAS_ITEM (object); + waveview = GNOME_CANVAS_WAVEVIEW (object); - switch (arg_id) { - case ARG_DATA_SRC: - gtk_canvas_waveview_set_data_src (waveview, GTK_VALUE_POINTER(*arg)); + void * ptr; + switch (prop_id) { + case PROP_DATA_SRC: + gnome_canvas_waveview_set_data_src (waveview, g_value_get_pointer(value)); redraw = TRUE; break; - case ARG_CHANNEL: - gtk_canvas_waveview_set_channel (waveview, GTK_VALUE_UINT(*arg)); + case PROP_CHANNEL: + gnome_canvas_waveview_set_channel (waveview, g_value_get_uint(value)); redraw = TRUE; break; - case ARG_LENGTH_FUNCTION: - waveview->length_function = GTK_VALUE_POINTER(*arg); + case PROP_LENGTH_FUNCTION: + ptr = g_value_get_pointer(value); + waveview->length_function = POSIX_FUNC_PTR_CAST(waveview_length_function_t, ptr); redraw = TRUE; break; - case ARG_SOURCEFILE_LENGTH_FUNCTION: - waveview->sourcefile_length_function = GTK_VALUE_POINTER(*arg); + + case PROP_SOURCEFILE_LENGTH_FUNCTION: + ptr = g_value_get_pointer(value); + waveview->sourcefile_length_function = POSIX_FUNC_PTR_CAST(waveview_sourcefile_length_function_t, ptr); redraw = TRUE; break; - case ARG_PEAK_FUNCTION: - waveview->peak_function = GTK_VALUE_POINTER(*arg); + case PROP_PEAK_FUNCTION: + ptr = g_value_get_pointer(value); + waveview->peak_function = POSIX_FUNC_PTR_CAST(waveview_peak_function_t, ptr); redraw = TRUE; break; - case ARG_GAIN_FUNCTION: - waveview->gain_curve_function = GTK_VALUE_POINTER(*arg); - redraw = TRUE; + case PROP_GAIN_FUNCTION: + ptr = g_value_get_pointer(value); + waveview->gain_curve_function = POSIX_FUNC_PTR_CAST(waveview_gain_curve_function_t, ptr); + redraw = TRUE; break; - case ARG_GAIN_SRC: - waveview->gain_src = GTK_VALUE_POINTER(*arg); + case PROP_GAIN_SRC: + waveview->gain_src = g_value_get_pointer(value); if (waveview->cache_updater) { waveview->cache->start = 0; waveview->cache->end = 0; @@ -547,19 +804,19 @@ gtk_canvas_waveview_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) calc_bounds = TRUE; break; - case ARG_CACHE: - waveview->cache = GTK_VALUE_POINTER(*arg); + case PROP_CACHE: + waveview->cache = g_value_get_pointer(value); redraw = TRUE; break; - case ARG_CACHE_UPDATER: - waveview->cache_updater = GTK_VALUE_BOOL(*arg); + case PROP_CACHE_UPDATER: + waveview->cache_updater = g_value_get_boolean(value); redraw = TRUE; break; - case ARG_SAMPLES_PER_PIXEL: - if ((waveview->samples_per_unit = GTK_VALUE_DOUBLE(*arg)) < 1.0) { + case PROP_SAMPLES_PER_UNIT: + if ((waveview->samples_per_unit = g_value_get_double(value)) < 1.0) { waveview->samples_per_unit = 1.0; } if (waveview->cache_updater) { @@ -570,47 +827,94 @@ gtk_canvas_waveview_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) calc_bounds = TRUE; break; - case ARG_AMPLITUDE_ABOVE_AXIS: - waveview->amplitude_above_axis = GTK_VALUE_DOUBLE(*arg); + case PROP_AMPLITUDE_ABOVE_AXIS: + waveview->amplitude_above_axis = g_value_get_double(value); redraw = TRUE; break; - case ARG_X: - if (waveview->x != GTK_VALUE_DOUBLE (*arg)) { - waveview->x = GTK_VALUE_DOUBLE (*arg); + case PROP_X: + if (waveview->x != g_value_get_double (value)) { + waveview->x = g_value_get_double (value); calc_bounds = TRUE; } break; - case ARG_Y: - if (waveview->y != GTK_VALUE_DOUBLE (*arg)) { - waveview->y = GTK_VALUE_DOUBLE (*arg); + case PROP_Y: + if (waveview->y != g_value_get_double (value)) { + waveview->y = g_value_get_double (value); calc_bounds = TRUE; } break; - case ARG_HEIGHT: - if (waveview->height != fabs (GTK_VALUE_DOUBLE (*arg))) { - waveview->height = fabs (GTK_VALUE_DOUBLE (*arg)); + case PROP_HEIGHT: + if (waveview->height != fabs (g_value_get_double (value))) { + waveview->height = fabs (g_value_get_double (value)); + redraw = TRUE; + } + break; + + case PROP_WAVE_COLOR: + if (waveview->wave_color != g_value_get_uint(value)) { + waveview->wave_color = g_value_get_uint(value); redraw = TRUE; } break; - case ARG_WAVE_COLOR: - if (waveview->wave_color != GTK_VALUE_INT(*arg)) { - waveview->wave_color = GTK_VALUE_INT(*arg); + case PROP_CLIP_COLOR: + if (waveview->clip_color != g_value_get_uint(value)) { + waveview->clip_color = g_value_get_uint(value); redraw = TRUE; } break; - case ARG_RECTIFIED: - if (waveview->rectified != GTK_VALUE_BOOL(*arg)) { - waveview->rectified = GTK_VALUE_BOOL(*arg); + case PROP_ZERO_COLOR: + if (waveview->zero_color != g_value_get_uint(value)) { + waveview->zero_color = g_value_get_uint(value); redraw = TRUE; } break; - case ARG_REGION_START: - waveview->region_start = GTK_VALUE_UINT(*arg); + + case PROP_FILL_COLOR: + if (waveview->fill_color != g_value_get_uint(value)) { + waveview->fill_color = g_value_get_uint(value); + redraw = TRUE; + } + break; + + case PROP_FILLED: + if (waveview->filled != g_value_get_boolean(value)) { + waveview->filled = g_value_get_boolean(value); + redraw = TRUE; + } + break; + + case PROP_RECTIFIED: + if (waveview->rectified != g_value_get_boolean(value)) { + waveview->rectified = g_value_get_boolean(value); + redraw = TRUE; + } + break; + + case PROP_ZERO_LINE: + if (waveview->zero_line != g_value_get_boolean(value)) { + waveview->zero_line = g_value_get_boolean(value); + redraw = TRUE; + } + break; + + case PROP_LOGSCALED: + if (waveview->logscaled != g_value_get_boolean(value)) { + waveview->logscaled = g_value_get_boolean(value); + if (waveview->cache_updater) { + waveview->cache->start = 0; + waveview->cache->end = 0; + } + redraw = TRUE; + calc_bounds = TRUE; + } + break; + case PROP_REGION_START: + waveview->region_start = g_value_get_uint(value); redraw = TRUE; calc_bounds = TRUE; break; @@ -621,108 +925,142 @@ gtk_canvas_waveview_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) } if (calc_bounds) { - gtk_canvas_waveview_reset_bounds (item); + gnome_canvas_waveview_reset_bounds (item); } if (redraw) { - gtk_canvas_item_request_update (item); + gnome_canvas_item_request_update (item); } } static void -gtk_canvas_waveview_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +gnome_canvas_waveview_get_property ( + GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) { - GtkCanvasWaveView *waveview; - waveview = GTK_CANVAS_WAVEVIEW (object); - switch (arg_id) { - case ARG_DATA_SRC: - GTK_VALUE_POINTER(*arg) = waveview->data_src; + g_return_if_fail (object != NULL); + g_return_if_fail (GNOME_IS_CANVAS_WAVEVIEW (object)); + + GnomeCanvasWaveView *waveview = GNOME_CANVAS_WAVEVIEW (object); + + switch (prop_id) { + case PROP_DATA_SRC: + g_value_set_pointer(value, waveview->data_src); + break; + + case PROP_CHANNEL: + g_value_set_uint(value, waveview->channel); break; - case ARG_CHANNEL: - GTK_VALUE_UINT(*arg) = waveview->channel; + case PROP_LENGTH_FUNCTION: + g_value_set_pointer(value, POSIX_FUNC_PTR_CAST(void*, waveview->length_function)); break; - case ARG_LENGTH_FUNCTION: - GTK_VALUE_POINTER(*arg) = waveview->length_function; + case PROP_SOURCEFILE_LENGTH_FUNCTION: + g_value_set_pointer(value, POSIX_FUNC_PTR_CAST(void*, waveview->sourcefile_length_function)); break; - case ARG_SOURCEFILE_LENGTH_FUNCTION: - GTK_VALUE_POINTER(*arg) = waveview->sourcefile_length_function; + case PROP_PEAK_FUNCTION: + g_value_set_pointer(value, POSIX_FUNC_PTR_CAST(void*, waveview->peak_function)); break; - case ARG_PEAK_FUNCTION: - GTK_VALUE_POINTER(*arg) = waveview->peak_function; + case PROP_GAIN_FUNCTION: + g_value_set_pointer(value, POSIX_FUNC_PTR_CAST(void*, waveview->gain_curve_function)); break; - case ARG_GAIN_FUNCTION: - GTK_VALUE_POINTER(*arg) = waveview->gain_curve_function; + case PROP_GAIN_SRC: + g_value_set_pointer(value, waveview->gain_src); break; - case ARG_GAIN_SRC: - GTK_VALUE_POINTER(*arg) = waveview->gain_src; + case PROP_CACHE: + g_value_set_pointer(value, waveview->cache); break; - case ARG_CACHE: - GTK_VALUE_POINTER(*arg) = waveview->cache; + case PROP_CACHE_UPDATER: + g_value_set_boolean(value, waveview->cache_updater); break; - case ARG_CACHE_UPDATER: - GTK_VALUE_BOOL(*arg) = waveview->cache_updater; + case PROP_SAMPLES_PER_UNIT: + g_value_set_double(value, waveview->samples_per_unit); break; - case ARG_SAMPLES_PER_PIXEL: - GTK_VALUE_DOUBLE(*arg) = waveview->samples_per_unit; + case PROP_AMPLITUDE_ABOVE_AXIS: + g_value_set_double(value, waveview->amplitude_above_axis); break; - case ARG_AMPLITUDE_ABOVE_AXIS: - GTK_VALUE_DOUBLE(*arg) = waveview->amplitude_above_axis; + case PROP_X: + g_value_set_double (value, waveview->x); break; - case ARG_X: - GTK_VALUE_DOUBLE (*arg) = waveview->x; + case PROP_Y: + g_value_set_double (value, waveview->y); break; - case ARG_Y: - GTK_VALUE_DOUBLE (*arg) = waveview->y; + case PROP_HEIGHT: + g_value_set_double (value, waveview->height); break; - case ARG_HEIGHT: - GTK_VALUE_DOUBLE (*arg) = waveview->height; + case PROP_WAVE_COLOR: + g_value_set_uint (value, waveview->wave_color); break; - case ARG_WAVE_COLOR: - GTK_VALUE_INT (*arg) = waveview->wave_color; + case PROP_CLIP_COLOR: + g_value_set_uint (value, waveview->clip_color); break; - case ARG_RECTIFIED: - GTK_VALUE_BOOL (*arg) = waveview->rectified; + case PROP_ZERO_COLOR: + g_value_set_uint (value, waveview->zero_color); + break; + + case PROP_FILL_COLOR: + g_value_set_uint (value, waveview->fill_color); + break; + + case PROP_FILLED: + g_value_set_boolean (value, waveview->filled); + break; + + case PROP_RECTIFIED: + g_value_set_boolean (value, waveview->rectified); + break; + + case PROP_ZERO_LINE: + g_value_set_boolean (value, waveview->zero_line); + break; + + case PROP_LOGSCALED: + g_value_set_boolean (value, waveview->logscaled); + break; + + case PROP_REGION_START: + g_value_set_uint (value, waveview->region_start); + break; - case ARG_REGION_START: - GTK_VALUE_UINT (*arg) = waveview->region_start; default: - arg->type = GTK_TYPE_INVALID; + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void -gtk_canvas_waveview_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +gnome_canvas_waveview_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) { - GtkCanvasWaveView *waveview; + GnomeCanvasWaveView *waveview; double x, y; - waveview = GTK_CANVAS_WAVEVIEW (item); + waveview = GNOME_CANVAS_WAVEVIEW (item); // check_cache (waveview, "start of update"); if (parent_class->update) (* parent_class->update) (item, affine, clip_path, flags); - gtk_canvas_waveview_reset_bounds (item); + gnome_canvas_waveview_reset_bounds (item); /* get the canvas coordinates of the view. Do NOT use affines for this, because they do not round to the integer units used @@ -732,16 +1070,16 @@ gtk_canvas_waveview_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_pa x = waveview->x; y = waveview->y; - gtk_canvas_item_i2w (item, &x, &y); - gtk_canvas_w2c (GTK_CANVAS(item->canvas), x, y, &waveview->bbox_ulx, &waveview->bbox_uly); + gnome_canvas_item_i2w (item, &x, &y); + gnome_canvas_w2c (GNOME_CANVAS(item->canvas), x, y, &waveview->bbox_ulx, &waveview->bbox_uly); waveview->samples = waveview->length_function (waveview->data_src); x = waveview->x + (waveview->samples / waveview->samples_per_unit); y = waveview->y + waveview->height; - gtk_canvas_item_i2w (item, &x, &y); - gtk_canvas_w2c (GTK_CANVAS(item->canvas), x, y, &waveview->bbox_lrx, &waveview->bbox_lry); + gnome_canvas_item_i2w (item, &x, &y); + gnome_canvas_w2c (GNOME_CANVAS(item->canvas), x, y, &waveview->bbox_lrx, &waveview->bbox_lry); /* cache the half-height and the end point in canvas units */ @@ -751,23 +1089,28 @@ gtk_canvas_waveview_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_pa UINT_TO_RGBA (waveview->wave_color, &waveview->wave_r, &waveview->wave_g, &waveview->wave_b, &waveview->wave_a); + UINT_TO_RGBA (waveview->clip_color, &waveview->clip_r, &waveview->clip_g, &waveview->clip_b, + &waveview->clip_a); + UINT_TO_RGBA (waveview->fill_color, &waveview->fill_r, &waveview->fill_g, &waveview->fill_b, + &waveview->fill_a); // check_cache (waveview, "end of update"); } static void -gtk_canvas_waveview_render (GtkCanvasItem *item, - GtkCanvasBuf *buf) +gnome_canvas_waveview_render (GnomeCanvasItem *item, + GnomeCanvasBuf *buf) { - GtkCanvasWaveView *waveview; + GnomeCanvasWaveView *waveview; gulong s1, s2; int clip_length = 0; int pymin, pymax; - int cache_index; + guint cache_index; double half_height; - int x, end, begin; + int x; + char rectify; - waveview = GTK_CANVAS_WAVEVIEW (item); + waveview = GNOME_CANVAS_WAVEVIEW (item); // check_cache (waveview, "start of render"); @@ -776,23 +1119,33 @@ gtk_canvas_waveview_render (GtkCanvasItem *item, } if (buf->is_bg) { - gtk_canvas_buf_ensure_buf (buf); + gnome_canvas_buf_ensure_buf (buf); buf->is_bg = FALSE; } - begin = MAX(waveview->bbox_ulx,buf->rect.x0); + /* a "unit" means a pixel */ - if (waveview->bbox_lrx >= 0) { - end = MIN(waveview->bbox_lrx,buf->rect.x1); - } else { - end = buf->rect.x1; - } + /* begin: render start x (units) */ + int const begin = MAX (waveview->bbox_ulx, buf->rect.x0); + + /* zbegin: start x for zero line (units) */ + int const zbegin = (begin == waveview->bbox_ulx) ? (begin + 1) : begin; + + /* end: render end x (units) */ + int const end = (waveview->bbox_lrx >= 0) ? MIN (waveview->bbox_lrx,buf->rect.x1) : buf->rect.x1; + + /* zend: end x for zero-line (units) */ + int const zend = (end == waveview->bbox_lrx) ? (end - 1) : end; if (begin == end) { return; } - s1 = floor ((begin - waveview->bbox_ulx) * waveview->samples_per_unit) ; + /* s1: start sample + s2: end sample + */ + + s1 = floor ((begin - waveview->bbox_ulx) * waveview->samples_per_unit); // fprintf (stderr, "0x%x begins at sample %f\n", waveview, waveview->bbox_ulx * waveview->samples_per_unit); @@ -807,7 +1160,7 @@ gtk_canvas_waveview_render (GtkCanvasItem *item, #if 0 printf ("0x%x r (%d..%d)(%d..%d) bbox (%d..%d)(%d..%d)" - " b/e %d..%d s= %lu..%lu\n", + " b/e %d..%d s= %lu..%lu @ %f\n", waveview, buf->rect.x0, buf->rect.x1, @@ -817,7 +1170,8 @@ gtk_canvas_waveview_render (GtkCanvasItem *item, waveview->bbox_lrx, waveview->bbox_uly, waveview->bbox_lry, - begin, end, s1, s2); + begin, end, s1, s2, + waveview->samples_per_unit); #endif /* now ensure that the cache is full and properly @@ -832,11 +1186,19 @@ gtk_canvas_waveview_render (GtkCanvasItem *item, waveview->reload_cache_in_render = FALSE; } - cache_index = gtk_canvas_waveview_ensure_cache (waveview, s1, s2); - // check_cache (waveview, "post-ensure"); - /* + /* don't rectify at single-sample zoom */ + if (waveview->rectified && waveview->samples_per_unit > 1) { + rectify = TRUE; + } + else { + rectify = FALSE; + } + + clip_length = MIN(5,(waveview->height/4)); + + /* Now draw each line, clipping it appropriately. The clipping is done by the macros PAINT_FOO(). */ @@ -844,107 +1206,651 @@ gtk_canvas_waveview_render (GtkCanvasItem *item, half_height = waveview->half_height; /* this makes it slightly easier to comprehend whats going on */ - #define origin half_height - for (x = begin; x < end; x++) { - + if (waveview->filled && !rectify) { + int prev_pymin = 1; + int prev_pymax = 0; + int last_pymin = 1; + int last_pymax = 0; + int next_pymin, next_pymax; double max, min; - int clip_max, clip_min; - - clip_max = 0; - clip_min = 0; + int next_clip_max = 0; + int next_clip_min = 0; + + if (s1 < waveview->samples_per_unit) { + /* we haven't got a prev vars to compare with, so outline the whole line here */ + prev_pymax = (int) rint ((item->y1 + origin) * item->canvas->pixels_per_unit); + prev_pymin = prev_pymax; + } + else { + s1 -= waveview->samples_per_unit; + } + + if(end == waveview->bbox_lrx) { + /* we don't have the NEXT vars for the last sample */ + last_pymax = (int) rint ((item->y1 + origin) * item->canvas->pixels_per_unit); + last_pymin = last_pymax; + } + else { + s2 += waveview->samples_per_unit; + } + + cache_index = gnome_canvas_waveview_ensure_cache (waveview, s1, s2); + + /* + * Compute the variables outside the rendering rect + */ + if(prev_pymax != prev_pymin) { + + prev_pymax = (int) rint ((item->y1 + origin - MIN(waveview->cache->data[cache_index].max, 1.0) * half_height) * item->canvas->pixels_per_unit); + prev_pymin = (int) rint ((item->y1 + origin - MAX(waveview->cache->data[cache_index].min, -1.0) * half_height) * item->canvas->pixels_per_unit); + ++cache_index; + } + if(last_pymax != last_pymin) { + /* take the index of one sample right of what we render */ + guint index = cache_index + (end - begin); + + if (index >= waveview->cache->data_size) { + + /* the data we want is off the end of the cache, which must mean its beyond + the end of the region's source; hence the peak values are 0 */ + last_pymax = (int) rint ((item->y1 + origin) * item->canvas->pixels_per_unit); + last_pymin = (int) rint ((item->y1 + origin) * item->canvas->pixels_per_unit); + + } else { + + last_pymax = (int) rint ((item->y1 + origin - MIN(waveview->cache->data[index].max, 1.0) * half_height) * item->canvas->pixels_per_unit); + last_pymin = (int) rint ((item->y1 + origin - MAX(waveview->cache->data[index].min, -1.0) * half_height) * item->canvas->pixels_per_unit); + } + + } + + /* + * initialize NEXT* variables for the first run, duplicated in the loop for speed + */ max = waveview->cache->data[cache_index].max; min = waveview->cache->data[cache_index].min; - + if (max >= 1.0) { max = 1.0; - clip_max = 1; + next_clip_max = 1; } if (min <= -1.0) { min = -1.0; - clip_min = 1; + next_clip_min = 1; } - /* don't rectify at single-sample zoom */ + max *= half_height; + min *= half_height; + + next_pymax = (int) rint ((item->y1 + origin - max) * item->canvas->pixels_per_unit); + next_pymin = (int) rint ((item->y1 + origin - min) * item->canvas->pixels_per_unit); + + /* + * And now the loop + */ + for(x = begin; x < end; ++x) { + int clip_max = next_clip_max; + int clip_min = next_clip_min; + int fill_max, fill_min; + + pymax = next_pymax; + pymin = next_pymin; + + /* compute next */ + if(x == end - 1) { + /*next is now the last column, which is outside the rendering rect, and possibly outside the region*/ + next_pymax = last_pymax; + next_pymin = last_pymin; + } + else { + ++cache_index; + + if (cache_index < waveview->cache->data_size) { + max = waveview->cache->data[cache_index].max; + min = waveview->cache->data[cache_index].min; + } else { + max = min = 0; + } + + next_clip_max = 0; + next_clip_min = 0; + + if (max >= 1.0) { + max = 1.0; + next_clip_max = 1; + } + + if (min <= -1.0) { + min = -1.0; + next_clip_min = 1; + } + + max *= half_height; + min *= half_height; + + next_pymax = (int) rint ((item->y1 + origin - max) * item->canvas->pixels_per_unit); + next_pymin = (int) rint ((item->y1 + origin - min) * item->canvas->pixels_per_unit); + } + + /* render */ + if (pymax == pymin) { + PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin); + } else { + if((prev_pymax < pymax && next_pymax < pymax) || + (prev_pymax == pymax && next_pymax == pymax)) { + fill_max = pymax + 1; + PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax); + } + else { + fill_max = MAX(prev_pymax, next_pymax); + if(pymax == fill_max) { + PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax); + ++fill_max; + } + else { + PAINT_VERTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax, fill_max); + } + } + + if((prev_pymin > pymin && next_pymin > pymin) || + (prev_pymin == pymin && next_pymin == pymin)) { + fill_min = pymin - 1; + PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin-1); + } + else { + fill_min = MIN(prev_pymin, next_pymin); + if(pymin == fill_min) { + PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin); + } + else { + PAINT_VERTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, fill_min, pymin); + } + } + + if(fill_max < fill_min) { + PAINT_VERTA(buf, waveview->fill_r, waveview->fill_g, waveview->fill_b, waveview->fill_a, x, fill_max, fill_min); + } + else if(fill_max == fill_min) { + PAINT_DOTA(buf, waveview->fill_r, waveview->fill_g, waveview->fill_b, waveview->fill_a, x, fill_max); + } + } + + if (clip_max) { + PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymax, pymax+clip_length); + } + + if (clip_min) { + PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymin-clip_length, pymin); + } + + prev_pymax = pymax; + prev_pymin = pymin; + } + + } else if (waveview->filled && rectify) { - if (waveview->rectified && waveview->samples_per_unit > 1) { + int prev_pymax = -1; + int last_pymax = -1; + int next_pymax; + double max, min; + int next_clip_max = 0; + int next_clip_min = 0; + + // for rectified, this stays constant throughout the loop + pymin = (int) rint ((item->y1 + waveview->height) * item->canvas->pixels_per_unit); + + if(s1 < waveview->samples_per_unit) { + /* we haven't got a prev vars to compare with, so outline the whole line here */ + prev_pymax = pymin; + } + else { + s1 -= waveview->samples_per_unit; + } + + if(end == waveview->bbox_lrx) { + /* we don't have the NEXT vars for the last sample */ + last_pymax = pymin; + } + else { + s2 += waveview->samples_per_unit; + } + + cache_index = gnome_canvas_waveview_ensure_cache (waveview, s1, s2); + + /* + * Compute the variables outside the rendering rect + */ + if(prev_pymax < 0) { + max = MIN(waveview->cache->data[cache_index].max, 1.0); + min = MAX(waveview->cache->data[cache_index].min, -1.0); if (fabs (min) > fabs (max)) { max = fabs (min); - } + } - max = max * waveview->height; + prev_pymax = (int) rint ((item->y1 + waveview->height - max * waveview->height) * item->canvas->pixels_per_unit); + ++cache_index; + } + if(last_pymax < 0) { + /* take the index of one sample right of what we render */ + int index = cache_index + (end - begin); - pymax = (int) rint ((item->y1 + waveview->height - max) * item->canvas->pixels_per_unit); - pymin = (int) rint ((item->y1 + waveview->height) * item->canvas->pixels_per_unit); + max = MIN(waveview->cache->data[index].max, 1.0); + min = MAX(waveview->cache->data[index].min, -1.0); - } else { - - max = max * half_height; - min = min * half_height; - - pymax = (int) rint ((item->y1 + origin - max) * item->canvas->pixels_per_unit); - pymin = (int) rint ((item->y1 + origin - min) * item->canvas->pixels_per_unit); + if (fabs (min) > fabs (max)) { + max = fabs (min); + } + + last_pymax = (int) rint ((item->y1 + waveview->height - max * waveview->height) * item->canvas->pixels_per_unit); } - /* OK, now fill the RGB buffer at x=i with a line between pymin and pymax, - or, if samples_per_unit == 1, then a dot at each location. - */ + /* + * initialize NEXT* variables for the first run, duplicated in the loop for speed + */ + max = waveview->cache->data[cache_index].max; + min = waveview->cache->data[cache_index].min; - if (pymax == pymin) { - PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin); - } else { - PAINT_VERTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax, pymin); + if (max >= 1.0) { + max = 1.0; + next_clip_max = 1; } - - /* show clipped waveforms with small red lines */ - if (clip_max || clip_min) { - clip_length = MIN(5,(waveview->height/4)); + if (min <= -1.0) { + min = -1.0; + next_clip_min = 1; } - if (clip_max) { - PAINT_VERT(buf, 255, 0, 0, x, pymax, pymax+clip_length); + if (fabs (min) > fabs (max)) { + max = fabs (min); } - if (clip_min) { - PAINT_VERT(buf, 255, 0, 0, x, pymin-clip_length, pymin); + next_pymax = (int) rint ((item->y1 + waveview->height - max * waveview->height) * item->canvas->pixels_per_unit); + + /* + * And now the loop + */ + for(x = begin; x < end; ++x) { + int clip_max = next_clip_max; + int clip_min = next_clip_min; + int fill_max; + + pymax = next_pymax; + + /* compute next */ + if(x == end - 1) { + /*next is now the last column, which is outside the rendering rect, and possibly outside the region*/ + next_pymax = last_pymax; + } + else { + ++cache_index; + + max = waveview->cache->data[cache_index].max; + min = waveview->cache->data[cache_index].min; + + if (max >= 1.0) { + max = 1.0; + next_clip_max = 1; + } + + if (min <= -1.0) { + min = -1.0; + next_clip_min = 1; + } + + if (fabs (min) > fabs (max)) { + max = fabs (min); + } + + next_pymax = (int) rint ((item->y1 + waveview->height - max * waveview->height) * item->canvas->pixels_per_unit); + } + + /* render */ + if (pymax == pymin) { + PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin); + } else { + if((prev_pymax < pymax && next_pymax < pymax) || + (prev_pymax == pymax && next_pymax == pymax)) { + fill_max = pymax + 1; + PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax); + } + else { + fill_max = MAX(prev_pymax, next_pymax); + if(pymax == fill_max) { + PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax); + ++fill_max; + } + else { + PAINT_VERTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax, fill_max); + } + } + + if(fill_max < pymin) { + PAINT_VERTA(buf, waveview->fill_r, waveview->fill_g, waveview->fill_b, waveview->fill_a, x, fill_max, pymin); + } + else if(fill_max == pymin) { + PAINT_DOTA(buf, waveview->fill_r, waveview->fill_g, waveview->fill_b, waveview->fill_a, x, pymin); + } + } + + if (clip_max) { + PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymax, pymax+clip_length); + } + + if (clip_min) { + PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymin-clip_length, pymin); + } + + prev_pymax = pymax; } + } + else { + cache_index = gnome_canvas_waveview_ensure_cache (waveview, s1, s2); - /* presto, we're done */ - - cache_index++; + for (x = begin; x < end; x++) { + + double max, min; + int clip_max, clip_min; + + clip_max = 0; + clip_min = 0; + + max = waveview->cache->data[cache_index].max; + min = waveview->cache->data[cache_index].min; + + if (max >= 1.0) { + max = 1.0; + clip_max = 1; + } + + if (min <= -1.0) { + min = -1.0; + clip_min = 1; + } + + if (rectify) { + + if (fabs (min) > fabs (max)) { + max = fabs (min); + } + + max = max * waveview->height; + + pymax = (int) rint ((item->y1 + waveview->height - max) * item->canvas->pixels_per_unit); + pymin = (int) rint ((item->y1 + waveview->height) * item->canvas->pixels_per_unit); + + } else { + + max = max * half_height; + min = min * half_height; + + pymax = (int) rint ((item->y1 + origin - max) * item->canvas->pixels_per_unit); + pymin = (int) rint ((item->y1 + origin - min) * item->canvas->pixels_per_unit); + } + + /* OK, now fill the RGB buffer at x=i with a line between pymin and pymax, + or, if samples_per_unit == 1, then a dot at each location. + */ + + if (pymax == pymin) { + PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin); + } else { + PAINT_VERTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax, pymin); + } + + /* show clipped waveforms with small red lines */ + + if (clip_max) { + PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymax, pymax+clip_length); + } + + if (clip_min) { + PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymin-clip_length, pymin); + } + + /* presto, we're done */ + + cache_index++; + } } + if (!waveview->rectified && waveview->zero_line && waveview->height >= 100) { + // Paint zeroline. + + unsigned char zero_r, zero_g, zero_b, zero_a; + UINT_TO_RGBA( waveview->zero_color, &zero_r, &zero_g, &zero_b, &zero_a); + int zeroline_y = (int) rint ((item->y1 + origin) * item->canvas->pixels_per_unit); + PAINT_HORIZA(buf, zero_r, zero_g, zero_b, zero_a, zbegin, zend, zeroline_y); + } #undef origin } static void -gtk_canvas_waveview_draw (GtkCanvasItem *item, - GdkDrawable *drawable, - int x, int y, - int width, int height) +gnome_canvas_waveview_draw (GnomeCanvasItem *item, + GdkDrawable *drawable, + int x, int y, + int width, int height) { - GtkCanvasWaveView *waveview; + GnomeCanvasWaveView *waveview; + cairo_t* cr; + gulong s1, s2; + int cache_index; + gboolean rectify; + double origin; + double clip_length; + double xoff; + double yoff = 0.0; + double ulx; + double uly; + double lrx; + double lry; + + waveview = GNOME_CANVAS_WAVEVIEW (item); + + /* compute intersection of Drawable area and waveview, + in canvas coordinate space + */ + + if (x > waveview->bbox_ulx) { + ulx = x; + } else { + ulx = waveview->bbox_ulx; + } + + if (y > waveview->bbox_uly) { + uly = y; + } else { + uly = waveview->bbox_uly; + } + + if (x + width > waveview->bbox_lrx) { + lrx = waveview->bbox_lrx; + } else { + lrx = x + width; + } + + if (y + height > waveview->bbox_lry) { + lry = waveview->bbox_lry; + } else { + lry = y + height; + } + + /* figure out which samples we need for the resulting intersection */ + + s1 = floor ((ulx - waveview->bbox_ulx) * waveview->samples_per_unit) ; + + if (lrx == waveview->bbox_lrx) { + /* This avoids minor rounding errors when we have the + entire region visible. + */ + s2 = waveview->samples; + } else { + s2 = s1 + floor ((lrx - ulx) * waveview->samples_per_unit); + } + + /* translate back to buffer coordinate space */ + + ulx -= x; + uly -= y; + lrx -= x; + lry -= y; + + /* don't rectify at single-sample zoom */ + if(waveview->rectified && waveview->samples_per_unit > 1.0) { + rectify = TRUE; + } else { + rectify = FALSE; + } + + clip_length = MIN(5,(waveview->height/4)); - waveview = GTK_CANVAS_WAVEVIEW (item); + cr = gdk_cairo_create (drawable); + cairo_set_line_width (cr, 0.5); - if (parent_class->draw) { - (* parent_class->draw) (item, drawable, x, y, width, height); + origin = waveview->bbox_uly - y + waveview->half_height; + + cairo_rectangle (cr, ulx, uly, lrx - ulx, lry - uly); + cairo_clip (cr); + + if (waveview->cache_updater && waveview->reload_cache_in_render) { + waveview->cache->start = 0; + waveview->cache->end = 0; + waveview->reload_cache_in_render = FALSE; } - fprintf (stderr, "please don't use the CanvasWaveView item in a non-aa Canvas\n"); - abort (); + cache_index = gnome_canvas_waveview_ensure_cache (waveview, s1, s2); + +#if 0 + printf ("%p r (%d,%d)(%d,%d)[%d x %d] bbox (%d,%d)(%d,%d)[%d x %d]" + " draw (%.1f,%.1f)(%.1f,%.1f)[%.1f x %.1f] s= %lu..%lu\n", + waveview, + x, y, + x + width, + y + height, + width, + height, + waveview->bbox_ulx, + waveview->bbox_uly, + waveview->bbox_lrx, + waveview->bbox_lry, + waveview->bbox_lrx - waveview->bbox_ulx, + waveview->bbox_lry - waveview->bbox_uly, + ulx, uly, + lrx, lry, + lrx - ulx, + lry - uly, + s1, s2); +#endif + + /* draw the top half */ + + for (xoff = ulx; xoff < lrx; xoff++) { + double max, min; + + max = waveview->cache->data[cache_index].max; + min = waveview->cache->data[cache_index].min; + + if (min <= -1.0) { + min = -1.0; + } + + if (max >= 1.0) { + max = 1.0; + } + + if (rectify) { + if (fabs (min) > fabs (max)) { + max = fabs (min); + } + } + + yoff = origin - (waveview->half_height * max) + 0.5; + + if (xoff == ulx) { + /* first point */ + cairo_move_to (cr, xoff+0.5, yoff); + } else { + cairo_line_to (cr, xoff+0.5, yoff); + } + + cache_index++; + } + + /* from the final top point, move out of the clip zone */ + + cairo_line_to (cr, xoff + 10, yoff); + + /* now draw the bottom half */ + + for (--xoff, --cache_index; xoff >= ulx; --xoff) { + double min; + + min = waveview->cache->data[cache_index].min; + + if (min <= -1.0) { + min = -1.0; + } + + yoff = origin - (waveview->half_height * min) + 0.5; + + cairo_line_to (cr, xoff+0.5, yoff); + cache_index--; + } + + /* from the final lower point, move out of the clip zone */ + + cairo_line_to (cr, xoff - 10, yoff); + + /* close path to fill */ + + cairo_close_path (cr); + + /* fill and stroke */ + + cairo_set_source_rgba (cr, + (waveview->fill_r/255.0), + (waveview->fill_g/255.0), + (waveview->fill_b/255.0), + (waveview->fill_a/255.0)); + cairo_fill_preserve (cr); + cairo_set_source_rgba (cr, + (waveview->wave_r/255.0), + (waveview->wave_g/255.0), + (waveview->wave_b/255.0), + (waveview->wave_a/255.0)); + cairo_stroke (cr); + + cairo_destroy (cr); } +#if 0 + if (clip_max || clip_min) { + cairo_set_source_rgba (cr, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a); + } + + if (clip_max) { + cairo_move_to (cr, xoff, yoff1); + cairo_line_to (cr, xoff, yoff1 + clip_length); + cairo_stroke (cr); + } + + if (clip_min) { + cairo_move_to (cr, xoff, yoff2); + cairo_line_to (cr, xoff, yoff2 - clip_length); + cairo_stroke (cr); + } + +#endif + static void -gtk_canvas_waveview_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2) +gnome_canvas_waveview_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2) { - GtkCanvasWaveView *waveview = GTK_CANVAS_WAVEVIEW (item); + GnomeCanvasWaveView *waveview = GNOME_CANVAS_WAVEVIEW (item); *x1 = waveview->x; *y1 = waveview->y; @@ -954,22 +1860,29 @@ gtk_canvas_waveview_bounds (GtkCanvasItem *item, double *x1, double *y1, double #if 0 x = 0; y = 0; - gtk_canvas_item_i2w (item, &x, &y); - gtk_canvas_w2c_d (GTK_CANVAS(item->canvas), x, y, &a, &b); + gnome_canvas_item_i2w (item, &x, &y); + gnome_canvas_w2c_d (GNOME_CANVAS(item->canvas), x, y, &a, &b); x = *x2; y = *y2; - gtk_canvas_item_i2w (item, &x, &y); - gtk_canvas_w2c_d (GTK_CANVAS(item->canvas), x, y, &c, &d); + gnome_canvas_item_i2w (item, &x, &y); + gnome_canvas_w2c_d (GNOME_CANVAS(item->canvas), x, y, &c, &d); printf ("item bounds now (%g,%g),(%g,%g)\n", a, b, c, d); -#endif +#endif } static double -gtk_canvas_waveview_point (GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item) +gnome_canvas_waveview_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item) { - /* XXX for now, point is never inside the wave - GtkCanvasWaveView *waveview; + (void) item; + (void) x; + (void) y; + (void) cx; + (void) cy; + (void) actual_item; + + /* XXX for now, point is never inside the wave + GnomeCanvasWaveView *waveview; double x1, y1, x2, y2; double dx, dy; */ @@ -977,16 +1890,16 @@ gtk_canvas_waveview_point (GtkCanvasItem *item, double x, double y, int cx, int return DBL_MAX; #if 0 - waveview = GTK_CANVAS_WAVEVIEW (item); + waveview = GNOME_CANVAS_WAVEVIEW (item); *actual_item = item; /* Find the bounds for the rectangle plus its outline width */ - gtk_canvas_waveview_bounds (item, &x1, &y1, &x2, &y2); + gnome_canvas_waveview_bounds (item, &x1, &y1, &x2, &y2); /* Is point inside rectangle */ - + if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2)) { return 0.0; }