if CANVAS_DEBUG is defined, then the env variable CANVAS_HARLEQUIN_DEBUGGING will...
[ardour.git] / libs / canvas / canvas / wave_view.h
1 /*
2     Copyright (C) 2011-2013 Paul Davis
3     Author: Carl Hetherington <cth@carlh.net>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 */
20
21 #include <boost/shared_ptr.hpp>
22 #include <boost/shared_array.hpp>
23 #include <boost/scoped_array.hpp>
24
25 #include "pbd/properties.h"
26
27 #include "ardour/types.h"
28
29 #include <glibmm/refptr.h>
30
31 #include "canvas/visibility.h"
32 #include "canvas/item.h"
33 #include "canvas/fill.h"
34 #include "canvas/outline.h"
35
36 namespace ARDOUR {
37         class AudioRegion;
38 }
39
40 namespace Gdk {
41         class Pixbuf;
42 }
43
44 class WaveViewTest;
45         
46 namespace ArdourCanvas {
47
48 class LIBCANVAS_API WaveView : public Item
49 {
50 public:
51
52         enum Shape { 
53                 Normal,
54                 Rectified
55         };
56         
57         struct CacheEntry {
58                 int channel;
59                 Coord height;
60                 float amplitude;
61                 Color fill_color;
62                 Color outline_color;
63                 framepos_t start;
64                 framepos_t end;
65                 Cairo::RefPtr<Cairo::ImageSurface> image;
66         CacheEntry() : 
67                 channel (0), height (0), amplitude(0), fill_color (0), 
68                         outline_color (0), start (0), end (0), image (0) {} 
69         CacheEntry(int chan, Coord hght, float amp, Color fcol, Color ocol, 
70                    framepos_t strt, framepos_t ed, Cairo::RefPtr<Cairo::ImageSurface> img) :
71                 channel (chan), height (hght), amplitude (amp), fill_color (fcol),
72                         outline_color (ocol), start (strt), end (ed), image (img) {} 
73         };
74         
75     /* Displays a single channel of waveform data for the given Region.
76
77        x = 0 in the waveview corresponds to the first waveform datum taken
78        from region->start() samples into the source data.
79
80        x = N in the waveview corresponds to the (N * spp)'th sample 
81        measured from region->start() into the source data.
82
83        when drawing, we will map the zeroth-pixel of the waveview
84        into a window. 
85
86        The waveview itself contains a set of pre-rendered Cairo::ImageSurfaces
87        that cache sections of the display. This is filled on-demand and
88        never cleared until something explicitly marks the cache invalid
89        (such as a change in samples_per_pixel, the log scaling, rectified or
90        other view parameters).
91     */
92
93
94         WaveView (Canvas *, boost::shared_ptr<ARDOUR::AudioRegion>);
95         WaveView (Item*, boost::shared_ptr<ARDOUR::AudioRegion>);
96        ~WaveView ();
97
98         void render (Rect const & area, Cairo::RefPtr<Cairo::Context>) const;
99         void compute_bounding_box () const;
100     
101         void set_samples_per_pixel (double);
102         void set_height (Distance);
103         void set_channel (int);
104         void set_region_start (ARDOUR::frameoffset_t);
105
106         void set_fill_color (Color);
107         void set_outline_color (Color);
108         
109         void region_resized ();
110         void gain_changed ();
111
112         void set_show_zero_line (bool);
113         bool show_zero_line() const { return _show_zero; }
114         void set_zero_color (Color);
115         void set_clip_color (Color);
116         void set_logscaled (bool);
117         void set_gradient_depth (double);
118         double gradient_depth() const { return _gradient_depth; }
119         void set_shape (Shape);
120
121         /* currently missing because we don't need them (yet):
122            set_shape_independent();
123            set_logscaled_independent()
124         */
125
126         static void set_global_gradient_depth (double);
127         static void set_global_logscaled (bool);
128         static void set_global_shape (Shape);
129         static void set_global_show_waveform_clipping (bool);
130     
131         static double  global_gradient_depth()  { return _global_gradient_depth; }
132         static bool    global_logscaled()  { return _global_logscaled; }
133         static Shape   global_shape()  { return _global_shape; }
134
135         void set_amplitude_above_axis (double v);
136         double amplitude_above_axis () const { return _amplitude_above_axis; }
137
138         static void set_clip_level (double dB);
139         static PBD::Signal0<void> ClipLevelChanged;
140
141 #ifdef CANVAS_COMPATIBILITY     
142         void*& property_gain_src () {
143                 return _foo_void;
144         }
145         void*& property_gain_function () {
146                 return _foo_void;
147         }
148 private:
149         void* _foo_void;
150
151 #endif
152
153         friend class ::WaveViewTest;
154
155         static std::map <boost::shared_ptr<ARDOUR::AudioSource>, std::vector <CacheEntry> > _image_cache;
156         void consolidate_image_cache () const;
157         void invalidate_image_cache ();
158
159         boost::shared_ptr<ARDOUR::AudioRegion> _region;
160         int    _channel;
161         double _samples_per_pixel;
162         Coord  _height;
163         bool   _show_zero;
164         Color  _zero_color;
165         Color  _clip_color;
166         bool   _logscaled;
167         Shape  _shape;
168         double _gradient_depth;
169         bool   _shape_independent;
170         bool   _logscaled_independent;
171         bool   _gradient_depth_independent;
172         double _amplitude_above_axis;
173         float  _region_amplitude;
174
175         /** The `start' value to use for the region; we can't use the region's
176          *  value as the crossfade editor needs to alter it.
177          */
178         ARDOUR::frameoffset_t _region_start;
179
180         PBD::ScopedConnectionList invalidation_connection;
181
182         static double _global_gradient_depth;
183         static bool   _global_logscaled;
184         static Shape  _global_shape;
185         static bool   _global_show_waveform_clipping;
186         static double _clip_level;
187
188         static PBD::Signal0<void> VisualPropertiesChanged;
189
190         void handle_visual_property_change ();
191         void handle_clip_level_change ();
192
193         void get_image (Cairo::RefPtr<Cairo::ImageSurface>& image, framepos_t start, framepos_t end, double& image_offset) const;
194
195         ArdourCanvas::Coord y_extent (double, bool) const;
196         void draw_image (Cairo::RefPtr<Cairo::ImageSurface>&, ARDOUR::PeakData*, int) const;
197 };
198
199 }