add transition_to_{roll,reverse}
[ardour.git] / gtk2_ardour / canvas-waveview.c
index 89f5da7bf628d197170c5bb6cd10f4c55f91d345..747761ea9ae887e6fb1dfb5425580f5aa535ce3d 100644 (file)
@@ -1,4 +1,4 @@
- /*
+/*
      Copyright (C) 2000-2002 Paul Davis 
 
      This program is free software; you can redistribute it and/or modify
      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
      $Id$
- */
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include <libgnomecanvas/libgnomecanvas.h>
+#include <string.h>
+#include <limits.h>
 
- #include <stdio.h>
- #include <math.h>
- #include <libgnomecanvas/libgnomecanvas.h>
- #include <string.h>
- #include <limits.h>
+#include <ardour/dB.h>
 
- #include <ardour/dB.h>
+#include "logmeter.h"
+#include "canvas-waveview.h"
+#include "rgb_macros.h"
 
- #include "canvas-waveview.h"
- #include "rgb_macros.h"
+extern void c_stacktrace();
 
- enum {
+enum {
         PROP_0,
         PROP_DATA_SRC,
         PROP_CHANNEL,
         PROP_HEIGHT,
         PROP_WAVE_COLOR,
         PROP_RECTIFIED,
-        PROP_REGION_START
- };
+        PROP_REGION_START,
+        PROP_LOGSCALED,
+};
 
- static void gnome_canvas_waveview_class_init     (GnomeCanvasWaveViewClass *class);
+static void gnome_canvas_waveview_class_init     (GnomeCanvasWaveViewClass *class);
 
- static void gnome_canvas_waveview_init           (GnomeCanvasWaveView      *waveview);
+static void gnome_canvas_waveview_init           (GnomeCanvasWaveView      *waveview);
 
- static void gnome_canvas_waveview_destroy        (GtkObject            *object);
+static void gnome_canvas_waveview_destroy        (GtkObject            *object);
 
- static void gnome_canvas_waveview_set_property   (GObject        *object,
+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,
+static void gnome_canvas_waveview_get_property   (GObject        *object,
                                                   guint           prop_id,
                                                   GValue         *value,
                                                   GParamSpec     *pspec);
 
- static void   gnome_canvas_waveview_update       (GnomeCanvasItem *item,
+static void   gnome_canvas_waveview_update       (GnomeCanvasItem *item,
                                                   double          *affine,
                                                   ArtSVP          *clip_path,
                                                   int              flags);
 
- static void   gnome_canvas_waveview_bounds       (GnomeCanvasItem *item,
+static void   gnome_canvas_waveview_bounds       (GnomeCanvasItem *item,
                                                   double          *x1,
                                                   double          *y1,
                                                   double          *x2,
                                                   double          *y2);
 
- static double gnome_canvas_waveview_point        (GnomeCanvasItem  *item,
+static double gnome_canvas_waveview_point        (GnomeCanvasItem  *item,
                                                   double            x,
                                                   double            y,
                                                   int               cx,
                                                   int               cy,
                                                   GnomeCanvasItem **actual_item);
 
- static void gnome_canvas_waveview_render         (GnomeCanvasItem *item,
+static void gnome_canvas_waveview_render         (GnomeCanvasItem *item,
                                                   GnomeCanvasBuf  *buf);
 
- static void gnome_canvas_waveview_draw           (GnomeCanvasItem *item,
+static void gnome_canvas_waveview_draw           (GnomeCanvasItem *item,
                                                   GdkDrawable     *drawable,
                                                   int              x,
                                                   int              y,
                                                   int              w,
                                                   int              h);
 
- static void gnome_canvas_waveview_set_data_src   (GnomeCanvasWaveView *,
+static void gnome_canvas_waveview_set_data_src   (GnomeCanvasWaveView *,
                                                   void *);
 
- static void gnome_canvas_waveview_set_channel    (GnomeCanvasWaveView *,
+static void gnome_canvas_waveview_set_channel    (GnomeCanvasWaveView *,
                                                   guint32);
 
- static gint32 gnome_canvas_waveview_ensure_cache (GnomeCanvasWaveView *waveview,
+static gint32 gnome_canvas_waveview_ensure_cache (GnomeCanvasWaveView *waveview,
                                                   gulong               start_sample,
                                                   gulong               end_sample);
 
- static GnomeCanvasItemClass *parent_class;
+static GnomeCanvasItemClass *parent_class;
 
- GType
- gnome_canvas_waveview_get_type (void)
- {
+GType
+gnome_canvas_waveview_get_type (void)
+{
         static GType waveview_type;
 
         if (!waveview_type) {
         return waveview_type;
  }
 
- static void
- gnome_canvas_waveview_class_init (GnomeCanvasWaveViewClass *class)
- {
+static void
+gnome_canvas_waveview_class_init (GnomeCanvasWaveViewClass *class)
+{
         GObjectClass *gobject_class;
         GtkObjectClass *object_class;
         GnomeCanvasItemClass *item_class;
                  g_param_spec_boolean ("rectified", 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,
         item_class->point = gnome_canvas_waveview_point;
         item_class->render = gnome_canvas_waveview_render;
         item_class->draw = gnome_canvas_waveview_draw;
- }
+}
 
 GnomeCanvasWaveViewCache*
 gnome_canvas_waveview_cache_new ()
@@ -306,6 +317,7 @@ gnome_canvas_waveview_init (GnomeCanvasWaveView *waveview)
        waveview->gain_curve_function = NULL;
        waveview->gain_src = NULL;
        waveview->rectified = FALSE;
+       waveview->logscaled = FALSE;
        waveview->region_start = 0;
        waveview->samples_per_unit = 1.0;
        waveview->amplitude_above_axis = 1.0;
@@ -331,6 +343,7 @@ gnome_canvas_waveview_destroy (GtkObject *object)
 }
 
 #define DEBUG_CACHE 0
+#undef CACHE_MEMMOVE_OPTIMIZATION
 
 static gint32
 gnome_canvas_waveview_ensure_cache (GnomeCanvasWaveView *waveview, gulong start_sample, gulong end_sample)
@@ -345,6 +358,10 @@ gnome_canvas_waveview_ensure_cache (GnomeCanvasWaveView *waveview, gulong start_
        gulong copied;
        GnomeCanvasWaveViewCache *cache;
        float* gain;
+#ifdef CACHE_MEMMOVE_OPTIMIZATION
+       gulong present_frames;
+       gulong present_entries;
+#endif
 
        cache = waveview->cache;
 
@@ -422,7 +439,6 @@ gnome_canvas_waveview_ensure_cache (GnomeCanvasWaveView *waveview, gulong start_
 
        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 */
@@ -571,7 +587,29 @@ gnome_canvas_waveview_ensure_cache (GnomeCanvasWaveView *waveview, gulong start_
                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(coefficient_to_dB(buf[n].max));
+                       } else if (buf[n].max < 0.0f) {
+                               buf[n].max = -alt_log_meter(coefficient_to_dB(-buf[n].max));
+                       }
+                       
+                       if (buf[n].min > 0.0f) {
+                               buf[n].min = alt_log_meter(coefficient_to_dB(buf[n].min));
+                       } else if (buf[n].min < 0.0f) {
+                               buf[n].min = -alt_log_meter(coefficient_to_dB(-buf[n].min));
+                       }
+               }
+       }
+
        cache->start = ostart;
        cache->end = new_cache_end;
 
@@ -764,6 +802,17 @@ gnome_canvas_waveview_set_property (GObject      *object,
                        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;
@@ -863,6 +912,10 @@ gnome_canvas_waveview_get_property (GObject      *object,
                g_value_set_boolean (value, waveview->rectified);
                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;
@@ -971,7 +1024,7 @@ gnome_canvas_waveview_render (GnomeCanvasItem *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,
@@ -981,7 +1034,8 @@ gnome_canvas_waveview_render (GnomeCanvasItem *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