diff options
Diffstat (limited to 'libs/canvas/canvas')
-rw-r--r-- | libs/canvas/canvas/debug.h | 1 | ||||
-rw-r--r-- | libs/canvas/canvas/fwd.h | 7 | ||||
-rw-r--r-- | libs/canvas/canvas/wave_view.h | 271 | ||||
-rw-r--r-- | libs/canvas/canvas/wave_view_private.h | 365 |
4 files changed, 3 insertions, 641 deletions
diff --git a/libs/canvas/canvas/debug.h b/libs/canvas/canvas/debug.h index ecf7eee46f..b0797531b0 100644 --- a/libs/canvas/canvas/debug.h +++ b/libs/canvas/canvas/debug.h @@ -33,7 +33,6 @@ namespace PBD { LIBCANVAS_API extern DebugBits CanvasEvents; LIBCANVAS_API extern DebugBits CanvasRender; LIBCANVAS_API extern DebugBits CanvasEnterLeave; - LIBCANVAS_API extern DebugBits WaveView; } } diff --git a/libs/canvas/canvas/fwd.h b/libs/canvas/canvas/fwd.h index 61cab3c9d2..bae8ef20fb 100644 --- a/libs/canvas/canvas/fwd.h +++ b/libs/canvas/canvas/fwd.h @@ -22,18 +22,17 @@ #define __canvas_canvas_fwd_h__ namespace ArdourCanvas { - class WaveView; class Line; - class LineSet; + class LineSet; class Rectangle; - class Ruler; + class Ruler; class Polygon; class PolyLine; class GtkCanvas; class GtkCanvasViewport; class Text; class Curve; - class ScrollGroup; + class ScrollGroup; } #endif /* __canvas_canvas_fwd_h__ */ diff --git a/libs/canvas/canvas/wave_view.h b/libs/canvas/canvas/wave_view.h deleted file mode 100644 index 1767262151..0000000000 --- a/libs/canvas/canvas/wave_view.h +++ /dev/null @@ -1,271 +0,0 @@ -/* - Copyright (C) 2011-2013 Paul Davis - Copyright (C) 2017 Tim Mayberry - Author: Carl Hetherington <cth@carlh.net> - - 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. - - 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. - -*/ - -#ifndef __CANVAS_WAVE_VIEW_H__ -#define __CANVAS_WAVE_VIEW_H__ - -#include <boost/shared_ptr.hpp> -#include <boost/scoped_ptr.hpp> - -#include "ardour/types.h" - -#include <glibmm/refptr.h> - -#include "canvas/visibility.h" -#include "canvas/item.h" - -namespace ARDOUR { - class AudioRegion; -} - -namespace Gdk { - class Pixbuf; -} - -class WaveViewTest; - -namespace ArdourCanvas { - -class WaveViewCacheGroup; -class WaveViewDrawRequest; -class WaveViewDrawRequestQueue; -class WaveViewImage; -class WaveViewProperties; -class WaveViewDrawingThread; - -class LIBCANVAS_API WaveView : public Item, public sigc::trackable -{ -public: - enum Shape { Normal, Rectified }; - - std::string debug_name () const; - - /* Displays a single channel of waveform data for the given Region. - - x = 0 in the waveview corresponds to the first waveform datum taken - from region->start() samples into the source data. - - x = N in the waveview corresponds to the (N * spp)'th sample - measured from region->start() into the source data. - - when drawing, we will map the zeroth-pixel of the waveview - into a window. - - The waveview itself contains a set of pre-rendered Cairo::ImageSurfaces - that cache sections of the display. This is filled on-demand and - never cleared until something explicitly marks the cache invalid - (such as a change in samples_per_pixel, the log scaling, rectified or - other view parameters). - */ - - WaveView (Canvas*, boost::shared_ptr<ARDOUR::AudioRegion>); - WaveView (Item*, boost::shared_ptr<ARDOUR::AudioRegion>); - ~WaveView (); - - virtual void prepare_for_render (Rect const& window_area) const; - - virtual void render (Rect const & area, Cairo::RefPtr<Cairo::Context>) const; - - void compute_bounding_box () const; - - void set_samples_per_pixel (double); - void set_height (Distance); - void set_channel (int); - void set_region_start (ARDOUR::frameoffset_t); - - /** Change the first position drawn by @param pixels. - * @param pixels must be positive. This is used by - * AudioRegionViews in Ardour to avoid drawing the - * first pixel of a waveform, and exists in case - * there are uses for WaveView where we do not - * want this behaviour. - */ - void set_start_shift (double pixels); - - void set_fill_color (Gtkmm2ext::Color); - void set_outline_color (Gtkmm2ext::Color); - - void region_resized (); - void gain_changed (); - - void set_show_zero_line (bool); - bool show_zero_line () const; - - void set_zero_color (Gtkmm2ext::Color); - void set_clip_color (Gtkmm2ext::Color); - void set_logscaled (bool); - - void set_gradient_depth (double); - double gradient_depth () const; - - void set_shape (Shape); - - void set_always_get_image_in_thread (bool yn); - - /* currently missing because we don't need them (yet): - * set_shape_independent(); - * set_logscaled_independent(); - */ - - static void set_global_gradient_depth (double); - static void set_global_logscaled (bool); - static void set_global_shape (Shape); - static void set_global_show_waveform_clipping (bool); - - static double global_gradient_depth () { return _global_gradient_depth; } - - static bool global_logscaled () { return _global_logscaled; } - - static Shape global_shape () { return _global_shape; } - - void set_amplitude_above_axis (double v); - - double amplitude_above_axis () const; - - static void set_clip_level (double dB); - static PBD::Signal0<void> ClipLevelChanged; - - static void start_drawing_thread (); - static void stop_drawing_thread (); - - static void set_image_cache_size (uint64_t); - -#ifdef CANVAS_COMPATIBILITY - void*& property_gain_src () { - return _foo_void; - } - void*& property_gain_function () { - return _foo_void; - } - -private: - void* _foo_void; -#endif - -private: - friend class ::WaveViewTest; - friend class WaveViewThreadClient; - friend class WaveViewDrawingThread; - - boost::shared_ptr<ARDOUR::AudioRegion> _region; - - boost::scoped_ptr<WaveViewProperties> _props; - - mutable boost::shared_ptr<WaveViewImage> _image; - - mutable boost::shared_ptr<WaveViewCacheGroup> _cache_group; - - bool _shape_independent; - bool _logscaled_independent; - bool _gradient_depth_independent; - - /** Under almost conditions, this is going to return _region->length(), - * but if region_start has been reset, then we need to use this modified - * computation. - */ - ARDOUR::framecnt_t region_length () const; - - /** Under almost conditions, this is going to return _region->start() + - * _region->length(), but if region_start has been reset, then we need to use - * this modified computation. - */ - ARDOUR::framepos_t region_end () const; - - /** - * _image stays non-null after the first time it is set - */ - bool rendered () const { return _image.get(); } - - bool draw_image_in_gui_thread () const; - - /** If true, calls to render() will render a missing wave image in the GUI - * thread. Generally set to false, but true after a call to set_height(). - */ - mutable bool _draw_image_in_gui_thread; - - /** If true, calls to render() will render a missing wave image in the GUI - * thread. Set true for waveviews we expect to keep updating (e.g. while - * recording) - */ - bool _always_draw_image_in_gui_thread; - - void init(); - - mutable boost::shared_ptr<WaveViewDrawRequest> current_request; - - PBD::ScopedConnectionList invalidation_connection; - - static double _global_gradient_depth; - static bool _global_logscaled; - static Shape _global_shape; - static bool _global_show_waveform_clipping; - static double _global_clip_level; - - static PBD::Signal0<void> VisualPropertiesChanged; - - void handle_visual_property_change (); - void handle_clip_level_change (); - - struct LineTips { - double top; - double bot; - double spread; - bool clip_max; - bool clip_min; - - LineTips () : top (0.0), bot (0.0), clip_max (false), clip_min (false) {} - }; - - static ArdourCanvas::Coord y_extent (double, Shape const, double const height); - - static void compute_tips (ARDOUR::PeakData const& peak, LineTips& tips, double const effective_height); - - static void draw_image (Cairo::RefPtr<Cairo::ImageSurface>&, ARDOUR::PeakData*, int n_peaks, - boost::shared_ptr<WaveViewDrawRequest>); - static void draw_absent_image (Cairo::RefPtr<Cairo::ImageSurface>&, ARDOUR::PeakData*, int); - - ARDOUR::framecnt_t optimal_image_width_samples () const; - - void set_image (boost::shared_ptr<WaveViewImage> img) const; - - // @return true if item area intersects with draw area - bool get_item_and_draw_rect_in_window_coords (Rect const& canvas_rect, Rect& item_area, - Rect& draw_rect) const; - - boost::shared_ptr<WaveViewDrawRequest> create_draw_request (WaveViewProperties const&) const; - - void queue_draw_request (boost::shared_ptr<WaveViewDrawRequest> const&) const; - - static void process_draw_request (boost::shared_ptr<WaveViewDrawRequest>); - - boost::shared_ptr<WaveViewCacheGroup> get_cache_group () const; - - /** - * Notify the Cache that we are dropping our reference to the - * CacheGroup so it can also do so if it is the only reference holder - * of the cache group. - */ - void reset_cache_group (); -}; - -} // namespace ArdourCanvas - -#endif // __CANVAS_WAVE_VIEW_H__ diff --git a/libs/canvas/canvas/wave_view_private.h b/libs/canvas/canvas/wave_view_private.h deleted file mode 100644 index d870300998..0000000000 --- a/libs/canvas/canvas/wave_view_private.h +++ /dev/null @@ -1,365 +0,0 @@ -/* - Copyright (C) 2017 Tim Mayberry - - 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. - - 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. - -*/ - -#ifndef __CANVAS_WAVE_VIEW_PRIVATE_H__ -#define __CANVAS_WAVE_VIEW_PRIVATE_H__ - -#include <deque> - -#include "canvas/wave_view.h" - -namespace ARDOUR { - class AudioRegion; -} - -namespace ArdourCanvas { - -struct WaveViewProperties -{ -public: // ctors - WaveViewProperties (boost::shared_ptr<ARDOUR::AudioRegion> region); - - // WaveViewProperties (WaveViewProperties const& other) = default; - - // WaveViewProperties& operator=(WaveViewProperties const& other) = default; - -public: // member variables - - framepos_t region_start; - framepos_t region_end; - uint16_t channel; - double height; - double samples_per_pixel; - double amplitude; - double amplitude_above_axis; - Gtkmm2ext::Color fill_color; - Gtkmm2ext::Color outline_color; - Gtkmm2ext::Color zero_color; - Gtkmm2ext::Color clip_color; - bool show_zero; - bool logscaled; - WaveView::Shape shape; - double gradient_depth; - double start_shift; - -private: // member variables - - framepos_t sample_start; - framepos_t sample_end; - -public: // methods - - bool is_valid () const - { - return (sample_end != 0 && samples_per_pixel != 0); - } - - void set_width_samples (ARDOUR::framecnt_t const width_samples) - { - assert (is_valid()); - assert (width_samples != 0); - ARDOUR::framecnt_t half_width = width_samples / 2; - framepos_t new_sample_start = std::max (region_start, get_center_sample () - half_width); - framepos_t new_sample_end = std::min (get_center_sample () + half_width, region_end); - assert (new_sample_start <= new_sample_end); - sample_start = new_sample_start; - sample_end = new_sample_end; - } - - uint64_t get_width_pixels () const - { - return (uint64_t)std::max (1LL, llrint (ceil (get_length_samples () / samples_per_pixel))); - } - - - void set_sample_offsets (framepos_t const start, framepos_t const end) - { - assert (start <= end); - - // sample_start and sample_end are bounded by the region limits. - if (start < region_start) { - sample_start = region_start; - } else if (start > region_end) { - sample_start = region_end; - } else { - sample_start = start; - } - - if (end > region_end) { - sample_end = region_end; - } else if (end < region_start) { - sample_end = region_start; - } else { - sample_end = end; - } - - assert (sample_start <= sample_end); - } - - framepos_t get_sample_start () const - { - return sample_start; - } - - framepos_t get_sample_end () const - { - return sample_end; - } - - void set_sample_positions_from_pixel_offsets (double start_pixel, double end_pixel) - { - assert (start_pixel <= end_pixel); - /** - * It is possible for the new sample positions to be past the region_end, - * so we have to do bounds checking/adjustment for this in set_sample_offsets. - */ - framepos_t new_sample_start = region_start + (start_pixel * samples_per_pixel); - framepos_t new_sample_end = region_start + (end_pixel * samples_per_pixel); - set_sample_offsets (new_sample_start, new_sample_end); - } - - ARDOUR::framecnt_t get_length_samples () const - { - assert (sample_start <= sample_end); - return sample_end - sample_start; - } - - framepos_t get_center_sample () - { - return sample_start + (get_length_samples() / 2); - } - - bool is_equivalent (WaveViewProperties const& other) - { - return (samples_per_pixel == other.samples_per_pixel && - contains (other.sample_start, other.sample_end) && channel == other.channel && - height == other.height && amplitude == other.amplitude && - amplitude_above_axis == other.amplitude_above_axis && fill_color == other.fill_color && - outline_color == other.outline_color && zero_color == other.zero_color && - clip_color == other.clip_color && show_zero == other.show_zero && - logscaled == other.logscaled && shape == other.shape && - gradient_depth == other.gradient_depth); - // region_start && start_shift?? - } - - bool contains (framepos_t start, framepos_t end) - { - return (sample_start <= start && end <= sample_end); - } -}; - -struct WaveViewImage { -public: // ctors - WaveViewImage (boost::shared_ptr<const ARDOUR::AudioRegion> const& region_ptr, - WaveViewProperties const& properties); - - ~WaveViewImage (); - -public: // member variables - boost::weak_ptr<const ARDOUR::AudioRegion> region; - WaveViewProperties props; - Cairo::RefPtr<Cairo::ImageSurface> cairo_image; - uint64_t timestamp; - -public: // methods - bool finished() { return static_cast<bool>(cairo_image); } - - bool - contains_image_with_properties (WaveViewProperties const& other_props) - { - return cairo_image && props.is_equivalent (other_props); - } - - bool is_valid () { - return props.is_valid (); - } - - size_t size_in_bytes () - { - // 4 = bytes per FORMAT_ARGB32 pixel - return props.height * props.get_width_pixels() * 4; - } -}; - -struct WaveViewDrawRequest -{ -public: - WaveViewDrawRequest (); - ~WaveViewDrawRequest (); - - bool stopped() const { return (bool) g_atomic_int_get (const_cast<gint*>(&stop)); } - void cancel() { g_atomic_int_set (&stop, 1); } - bool finished() { return image->finished(); } - - boost::shared_ptr<WaveViewImage> image; - - bool is_valid () { - return (image && image->is_valid()); - } - -private: - gint stop; /* intended for atomic access */ -}; - -class WaveViewCache; - -class WaveViewCacheGroup -{ -public: - WaveViewCacheGroup (WaveViewCache& parent_cache); - - ~WaveViewCacheGroup (); - -public: - - // @return image with matching properties or null - boost::shared_ptr<WaveViewImage> lookup_image (WaveViewProperties const&); - - void add_image (boost::shared_ptr<WaveViewImage>); - - bool full () const { return _cached_images.size() > max_size(); } - - static uint32_t max_size () { return 16; } - - void clear_cache (); - -private: - - /** - * At time of writing we don't strictly need a reference to the parent cache - * as there is only a single global cache but if the image cache ever becomes - * a per canvas cache then a using a reference is handy. - */ - WaveViewCache& _parent_cache; - - typedef std::list<boost::shared_ptr<WaveViewImage> > ImageCache; - ImageCache _cached_images; -}; - -class WaveViewCache -{ -public: - static WaveViewCache* get_instance (); - - uint64_t image_cache_threshold () const { return _image_cache_threshold; } - void set_image_cache_threshold (uint64_t); - - void clear_cache (); - - boost::shared_ptr<WaveViewCacheGroup> get_cache_group (boost::shared_ptr<ARDOUR::AudioSource>); - - void reset_cache_group (boost::shared_ptr<WaveViewCacheGroup>&); - -private: - WaveViewCache(); - ~WaveViewCache(); - -private: - typedef std::map<boost::shared_ptr<ARDOUR::AudioSource>, boost::shared_ptr<WaveViewCacheGroup> > - CacheGroups; - - CacheGroups cache_group_map; - - uint64_t image_cache_size; - uint64_t _image_cache_threshold; - -private: - friend class WaveViewCacheGroup; - - void increase_size (uint64_t bytes); - void decrease_size (uint64_t bytes); - - bool full () { return image_cache_size > _image_cache_threshold; } -}; - -class WaveViewDrawRequestQueue -{ -public: - - void enqueue (boost::shared_ptr<WaveViewDrawRequest>&); - - // @return valid request or null if non-blocking or no request is available - boost::shared_ptr<WaveViewDrawRequest> dequeue (bool block); - - void wake_up (); - -private: - - mutable Glib::Threads::Mutex _queue_mutex; - Glib::Threads::Cond _cond; - - typedef std::deque<boost::shared_ptr<WaveViewDrawRequest> > DrawRequestQueueType; - DrawRequestQueueType _queue; -}; - -class WaveViewDrawingThread -{ -public: - WaveViewDrawingThread (); - ~WaveViewDrawingThread (); - -private: - void start (); - void quit (); - void run (); - -private: - Glib::Threads::Thread* _thread; - gint _quit; -}; - -class WaveViewThreads { -private: - WaveViewThreads (); - ~WaveViewThreads (); - -public: - static void initialize (); - static void deinitialize (); - - static bool enabled () { return (instance); } - - static void enqueue_draw_request (boost::shared_ptr<WaveViewDrawRequest>&); - -private: - friend class WaveViewDrawingThread; - - static void wake_up (); - - // will block until a request is available - static boost::shared_ptr<WaveViewDrawRequest> dequeue_draw_request (); - - void start_threads (); - void stop_threads (); - -private: - static uint32_t init_count; - static WaveViewThreads* instance; - - // TODO use std::unique_ptr when possible - typedef std::vector<boost::shared_ptr<WaveViewDrawingThread> > WaveViewThreadList; - - WaveViewThreadList _threads; - WaveViewDrawRequestQueue _request_queue; -}; - - -} // namespace ArdourCanvas - -#endif // __CANVAS_WAVE_VIEW_PRIVATE_H__ |