2 Copyright (C) 2001-2006 Paul Davis
4 This program is free software; you can r>edistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include <boost/scoped_array.hpp>
28 #include <gtkmm2ext/gtk_ui.h>
30 #include "ardour/playlist.h"
31 #include "ardour/audioregion.h"
32 #include "ardour/audiosource.h"
33 #include "ardour/profile.h"
34 #include "ardour/session.h"
36 #include "pbd/memento_command.h"
37 #include "pbd/stacktrace.h"
39 #include "evoral/Curve.hpp"
41 #include "canvas/rectangle.h"
42 #include "canvas/polygon.h"
43 #include "canvas/poly_line.h"
44 #include "canvas/line.h"
45 #include "canvas/text.h"
46 #include "canvas/xfade_curve.h"
47 #include "canvas/debug.h"
48 #include "canvas/utils.h"
49 #include "canvas/colors.h"
51 #include "streamview.h"
52 #include "audio_region_view.h"
53 #include "audio_time_axis.h"
54 #include "public_editor.h"
55 #include "audio_region_editor.h"
56 #include "audio_streamview.h"
57 #include "region_gain_line.h"
58 #include "control_point.h"
59 #include "ghostregion.h"
60 #include "audio_time_axis.h"
61 #include "rgb_macros.h"
62 #include "gui_thread.h"
63 #include "ui_config.h"
67 #define MUTED_ALPHA 48
70 using namespace ARDOUR;
72 using namespace Editing;
73 using namespace ArdourCanvas;
75 static double const handle_size = 10; /* height of fade handles */
77 Cairo::RefPtr<Cairo::Pattern> AudioRegionView::pending_peak_pattern;
79 static Cairo::RefPtr<Cairo::Pattern> create_pending_peak_pattern() {
80 cairo_surface_t * is = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 8, 8);
82 // create checker pattern
83 unsigned char *img = cairo_image_surface_get_data (is);
84 cairo_surface_flush (is);
85 const int stride = cairo_image_surface_get_stride (is);
87 for (int y = 0; y < 8; ++y) {
88 for (int x = 0; x < 8; ++x) {
89 const int off = (y * stride + x * 4);
90 uint32_t *pixel = (uint32_t*) &img[off];
91 if ((x < 4) ^ (y < 4)) {
98 cairo_surface_mark_dirty (is);
100 cairo_pattern_t* pat = cairo_pattern_create_for_surface (is);
101 cairo_pattern_set_extend (pat, CAIRO_EXTEND_REPEAT);
102 Cairo::RefPtr<Cairo::Pattern> p (new Cairo::Pattern (pat, false));
103 cairo_surface_destroy (is);
107 AudioRegionView::AudioRegionView (ArdourCanvas::Container *parent, RouteTimeAxisView &tv, boost::shared_ptr<AudioRegion> r, double spu,
108 uint32_t basic_color)
109 : RegionView (parent, tv, r, spu, basic_color)
113 , fade_in_trim_handle(0)
114 , fade_out_trim_handle(0)
115 , pending_peak_data(0)
116 , start_xfade_curve (0)
117 , start_xfade_rect (0)
118 , _start_xfade_visible (false)
119 , end_xfade_curve (0)
121 , _end_xfade_visible (false)
122 , _amplitude_above_axis(1.0)
123 , trim_fade_in_drag_active(false)
124 , trim_fade_out_drag_active(false)
126 UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &AudioRegionView::parameter_changed));
129 AudioRegionView::AudioRegionView (ArdourCanvas::Container *parent, RouteTimeAxisView &tv, boost::shared_ptr<AudioRegion> r, double spu,
130 uint32_t basic_color, bool recording, TimeAxisViewItem::Visibility visibility)
131 : RegionView (parent, tv, r, spu, basic_color, recording, visibility)
135 , fade_in_trim_handle(0)
136 , fade_out_trim_handle(0)
137 , pending_peak_data(0)
138 , start_xfade_curve (0)
139 , start_xfade_rect (0)
140 , _start_xfade_visible (false)
141 , end_xfade_curve (0)
143 , _end_xfade_visible (false)
144 , _amplitude_above_axis(1.0)
145 , trim_fade_in_drag_active(false)
146 , trim_fade_out_drag_active(false)
148 UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &AudioRegionView::parameter_changed));
151 AudioRegionView::AudioRegionView (const AudioRegionView& other, boost::shared_ptr<AudioRegion> other_region)
152 : RegionView (other, boost::shared_ptr<Region> (other_region))
155 , fade_in_trim_handle(0)
156 , fade_out_trim_handle(0)
157 , pending_peak_data(0)
158 , start_xfade_curve (0)
159 , start_xfade_rect (0)
160 , _start_xfade_visible (false)
161 , end_xfade_curve (0)
163 , _end_xfade_visible (false)
164 , _amplitude_above_axis (other._amplitude_above_axis)
165 , trim_fade_in_drag_active(false)
166 , trim_fade_out_drag_active(false)
170 UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &AudioRegionView::parameter_changed));
174 AudioRegionView::init (bool wfd)
176 // FIXME: Some redundancy here with RegionView::init. Need to figure out
177 // where order is important and where it isn't...
179 if (!pending_peak_pattern) {
180 pending_peak_pattern = create_pending_peak_pattern();
183 // needs to be created first, RegionView::init() calls set_height()
184 pending_peak_data = new ArdourCanvas::Rectangle (group);
185 CANVAS_DEBUG_NAME (pending_peak_data, string_compose ("pending peak rectangle for %1", region()->name()));
186 pending_peak_data->set_outline_color (ArdourCanvas::rgba_to_color (0, 0, 0, 0.0));
187 pending_peak_data->set_pattern (pending_peak_pattern);
188 pending_peak_data->set_data ("regionview", this);
189 pending_peak_data->hide ();
191 RegionView::init (wfd);
193 _amplitude_above_axis = 1.0;
198 fade_in_handle = new ArdourCanvas::Rectangle (group);
199 CANVAS_DEBUG_NAME (fade_in_handle, string_compose ("fade in handle for %1", region()->name()));
200 fade_in_handle->set_outline_color (ArdourCanvas::rgba_to_color (0, 0, 0, 1.0));
201 fade_in_handle->set_fill_color (UIConfiguration::instance().color ("inactive fade handle"));
202 fade_in_handle->set_data ("regionview", this);
203 fade_in_handle->hide ();
205 fade_out_handle = new ArdourCanvas::Rectangle (group);
206 CANVAS_DEBUG_NAME (fade_out_handle, string_compose ("fade out handle for %1", region()->name()));
207 fade_out_handle->set_outline_color (ArdourCanvas::rgba_to_color (0, 0, 0, 1.0));
208 fade_out_handle->set_fill_color (UIConfiguration::instance().color ("inactive fade handle"));
209 fade_out_handle->set_data ("regionview", this);
210 fade_out_handle->hide ();
212 fade_in_trim_handle = new ArdourCanvas::Rectangle (group);
213 CANVAS_DEBUG_NAME (fade_in_handle, string_compose ("fade in trim handle for %1", region()->name()));
214 fade_in_trim_handle->set_outline_color (ArdourCanvas::rgba_to_color (0, 0, 0, 1.0));
215 fade_in_trim_handle->set_fill_color (UIConfiguration::instance().color ("inactive fade handle"));
216 fade_in_trim_handle->set_data ("regionview", this);
217 fade_in_trim_handle->hide ();
219 fade_out_trim_handle = new ArdourCanvas::Rectangle (group);
220 CANVAS_DEBUG_NAME (fade_out_handle, string_compose ("fade out trim handle for %1", region()->name()));
221 fade_out_trim_handle->set_outline_color (ArdourCanvas::rgba_to_color (0, 0, 0, 1.0));
222 fade_out_trim_handle->set_fill_color (UIConfiguration::instance().color ("inactive fade handle"));
223 fade_out_trim_handle->set_data ("regionview", this);
224 fade_out_trim_handle->hide ();
227 setup_fade_handle_positions ();
229 if (!trackview.session()->config.get_show_region_fades()) {
230 set_fade_visibility (false);
233 const string line_name = _region->name() + ":gain";
235 gain_line.reset (new AudioRegionGainLine (line_name, *this, *group, audio_region()->envelope()));
237 update_envelope_visibility ();
240 /* streamview will call set_height() */
241 //set_height (trackview.current_height()); // XXX not correct for Layered mode, but set_height() will fix later.
244 region_sync_changed ();
246 region_resized (ARDOUR::bounds_change);
247 /* region_resized sets ghost region duration */
249 /* region_locked is a synonym for region_renamed () which is called in region_muted() above */
252 envelope_active_changed ();
253 fade_in_active_changed ();
254 fade_out_active_changed ();
256 reset_width_dependent_items (_pixel_width);
258 if (fade_in_handle) {
259 fade_in_handle->Event.connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_in_handle_event), fade_in_handle, this, false));
262 if (fade_out_handle) {
263 fade_out_handle->Event.connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_out_handle_event), fade_out_handle, this, false));
266 if (fade_in_trim_handle) {
267 fade_in_trim_handle->Event.connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_in_handle_event), fade_in_trim_handle, this, true));
270 if (fade_out_trim_handle) {
271 fade_out_trim_handle->Event.connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_out_handle_event), fade_out_trim_handle, this, true));
276 setup_waveform_visibility ();
278 /* XXX sync mark drag? */
281 AudioRegionView::~AudioRegionView ()
283 in_destructor = true;
285 RegionViewGoingAway (this); /* EMIT_SIGNAL */
287 for (vector<ScopedConnection*>::iterator i = _data_ready_connections.begin(); i != _data_ready_connections.end(); ++i) {
290 _data_ready_connections.clear ();
292 for (list<std::pair<framepos_t, ArdourCanvas::Line*> >::iterator i = feature_lines.begin(); i != feature_lines.end(); ++i) {
293 delete ((*i).second);
296 /* all waveviews etc will be destroyed when the group is destroyed */
299 boost::shared_ptr<ARDOUR::AudioRegion>
300 AudioRegionView::audio_region() const
302 // "Guaranteed" to succeed...
303 return boost::dynamic_pointer_cast<AudioRegion>(_region);
307 AudioRegionView::region_changed (const PropertyChange& what_changed)
309 ENSURE_GUI_THREAD (*this, &AudioRegionView::region_changed, what_changed);
311 RegionView::region_changed (what_changed);
313 if (what_changed.contains (ARDOUR::Properties::scale_amplitude)) {
314 region_scale_amplitude_changed ();
316 if (what_changed.contains (ARDOUR::Properties::fade_in)) {
319 if (what_changed.contains (ARDOUR::Properties::fade_out)) {
322 if (what_changed.contains (ARDOUR::Properties::fade_in_active)) {
323 fade_in_active_changed ();
325 if (what_changed.contains (ARDOUR::Properties::fade_out_active)) {
326 fade_out_active_changed ();
328 if (what_changed.contains (ARDOUR::Properties::envelope_active)) {
329 envelope_active_changed ();
331 if (what_changed.contains (ARDOUR::Properties::valid_transients)) {
332 transients_changed ();
337 AudioRegionView::fade_in_changed ()
339 reset_fade_in_shape ();
343 AudioRegionView::fade_out_changed ()
345 reset_fade_out_shape ();
349 AudioRegionView::fade_in_active_changed ()
351 if (start_xfade_rect) {
352 if (audio_region()->fade_in_active()) {
353 start_xfade_rect->set_fill (false);
355 start_xfade_rect->set_fill_color (UIConfiguration::instance().color_mod ("inactive crossfade", "inactive crossfade"));
356 start_xfade_rect->set_fill (true);
362 AudioRegionView::fade_out_active_changed ()
364 if (end_xfade_rect) {
365 if (audio_region()->fade_out_active()) {
366 end_xfade_rect->set_fill (false);
368 end_xfade_rect->set_fill_color (UIConfiguration::instance().color_mod ("inactive crossfade", "inactive crossfade"));
369 end_xfade_rect->set_fill (true);
376 AudioRegionView::region_scale_amplitude_changed ()
378 for (uint32_t n = 0; n < waves.size(); ++n) {
379 waves[n]->gain_changed ();
384 AudioRegionView::region_renamed ()
386 std::string str = RegionView::make_name ();
388 if (audio_region()->speed_mismatch (trackview.session()->frame_rate())) {
389 str = string ("*") + str;
392 if (_region->muted()) {
393 str = string ("!") + str;
396 set_item_name (str, this);
401 AudioRegionView::region_resized (const PropertyChange& what_changed)
403 AudioGhostRegion* agr;
405 RegionView::region_resized(what_changed);
406 PropertyChange interesting_stuff;
408 interesting_stuff.add (ARDOUR::Properties::start);
409 interesting_stuff.add (ARDOUR::Properties::length);
411 if (what_changed.contains (interesting_stuff)) {
413 for (uint32_t n = 0; n < waves.size(); ++n) {
414 waves[n]->region_resized ();
417 for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
418 if ((agr = dynamic_cast<AudioGhostRegion*>(*i)) != 0) {
420 for (vector<WaveView*>::iterator w = agr->waves.begin(); w != agr->waves.end(); ++w) {
421 (*w)->region_resized ();
426 /* hide transient lines that extend beyond the region */
427 list<std::pair<framepos_t, ArdourCanvas::Line*> >::iterator l;
428 framepos_t first = _region->first_frame();
429 framepos_t last = _region->last_frame();
431 for (l = feature_lines.begin(); l != feature_lines.end(); ++l) {
432 if (l->first < first || l->first >= last) {
442 AudioRegionView::reset_width_dependent_items (double pixel_width)
444 if (pixel_width == _width) {
448 RegionView::reset_width_dependent_items(pixel_width);
449 assert(_pixel_width == pixel_width);
451 pending_peak_data->set_x1(pixel_width);
453 if (pixel_width <= 20.0 || _height < 5.0 || !trackview.session()->config.get_show_region_fades()) {
454 if (fade_in_handle) { fade_in_handle->hide(); }
455 if (fade_out_handle) { fade_out_handle->hide(); }
456 if (fade_in_trim_handle) { fade_in_trim_handle->hide(); }
457 if (fade_out_trim_handle) { fade_out_trim_handle->hide(); }
458 if (start_xfade_rect) { start_xfade_rect->set_outline (false); }
459 if (end_xfade_rect) { end_xfade_rect->set_outline (false); }
462 reset_fade_shapes ();
464 /* Update feature lines */
465 AnalysisFeatureList analysis_features;
466 _region->transients (analysis_features);
468 if (feature_lines.size () != analysis_features.size ()) {
469 cerr << "postponed freature line update.\n"; // XXX
470 // AudioRegionView::transients_changed () will pick up on this
474 framepos_t position = _region->position();
476 AnalysisFeatureList::const_iterator i;
477 list<std::pair<framepos_t, ArdourCanvas::Line*> >::iterator l;
479 if (_height >= NAME_HIGHLIGHT_THRESH) {
480 y1 = _height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 1;
484 for (i = analysis_features.begin(), l = feature_lines.begin(); i != analysis_features.end() && l != feature_lines.end(); ++i, ++l) {
485 float x_pos = trackview.editor().sample_to_pixel ((*i) - position);
487 (*l).second->set (ArdourCanvas::Duple (x_pos, 2.0),
488 ArdourCanvas::Duple (x_pos, y1));
493 AudioRegionView::region_muted ()
495 RegionView::region_muted();
496 set_waveform_colors ();
500 AudioRegionView::setup_fade_handle_positions()
502 /* position of fade handle offset from the top of the region view */
503 double const handle_pos = 0.0;
505 if (fade_in_handle) {
506 fade_in_handle->set_y0 (handle_pos);
507 fade_in_handle->set_y1 (handle_pos + handle_size);
510 if (fade_out_handle) {
511 fade_out_handle->set_y0 (handle_pos);
512 fade_out_handle->set_y1 (handle_pos + handle_size);
515 if (fade_in_trim_handle) {
516 fade_in_trim_handle->set_y0 (_height - handle_size);
517 fade_in_trim_handle->set_y1 (_height);
520 if (fade_out_trim_handle) {
521 fade_out_trim_handle->set_y0 (_height - handle_size );
522 fade_out_trim_handle->set_y1 (_height);
527 AudioRegionView::set_height (gdouble height)
529 if (height == _height) {
533 RegionView::set_height (height);
534 pending_peak_data->set_y1 (height);
536 uint32_t wcnt = waves.size();
542 if (!UIConfiguration::instance().get_show_name_highlight() || (height < NAME_HIGHLIGHT_THRESH)) {
543 ht = height / (double) wcnt;
545 ht = (height - NAME_HIGHLIGHT_SIZE) / (double) wcnt;
548 for (uint32_t n = 0; n < wcnt; ++n) {
550 gdouble yoff = floor (ht * n);
552 waves[n]->set_height (ht);
553 waves[n]->set_y_position (yoff);
559 if ((height/wcnt) < NAME_HIGHLIGHT_THRESH) {
562 update_envelope_visibility ();
565 gain_line->set_height ((uint32_t) rint (height - NAME_HIGHLIGHT_SIZE) - 2);
568 reset_fade_shapes ();
570 /* Update heights for any feature lines */
571 framepos_t position = _region->position();
572 list<std::pair<framepos_t, ArdourCanvas::Line*> >::iterator l;
574 if (_height >= NAME_HIGHLIGHT_THRESH) {
575 y1 = _height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 1;
579 for (l = feature_lines.begin(); l != feature_lines.end(); ++l) {
580 float pos_x = trackview.editor().sample_to_pixel((*l).first - position);
581 (*l).second->set (ArdourCanvas::Duple (pos_x, 2.0),
582 ArdourCanvas::Duple (pos_x, y1));
586 name_text->raise_to_top();
589 setup_fade_handle_positions();
593 AudioRegionView::reset_fade_shapes ()
595 if (!trim_fade_in_drag_active) { reset_fade_in_shape (); }
596 if (!trim_fade_out_drag_active) { reset_fade_out_shape (); }
600 AudioRegionView::reset_fade_in_shape ()
602 reset_fade_in_shape_width (audio_region(), (framecnt_t) audio_region()->fade_in()->back()->when);
606 AudioRegionView::reset_fade_in_shape_width (boost::shared_ptr<AudioRegion> ar, framecnt_t width, bool drag_active)
608 trim_fade_in_drag_active = drag_active;
609 if (fade_in_handle == 0) {
613 /* smallest size for a fade is 64 frames */
615 width = std::max ((framecnt_t) 64, width);
617 /* round here to prevent little visual glitches with sub-pixel placement */
618 double const pwidth = floor (width / samples_per_pixel);
619 double const handle_left = pwidth;
621 /* Put the fade in handle so that its left side is at the end-of-fade line */
622 fade_in_handle->set_x0 (handle_left);
623 fade_in_handle->set_x1 (handle_left + handle_size);
625 if (fade_in_trim_handle) {
626 fade_in_trim_handle->set_x0 (0);
627 fade_in_trim_handle->set_x1 (handle_size);
630 if (fade_in_handle->visible()) {
631 //see comment for drag_start
640 if (!trackview.session()->config.get_show_region_fades()) {
645 double effective_height;
647 if (_height >= NAME_HIGHLIGHT_THRESH) {
648 effective_height = _height - NAME_HIGHLIGHT_SIZE;
650 effective_height = _height;
653 /* points *MUST* be in anti-clockwise order */
656 Points::size_type pi;
657 boost::shared_ptr<const Evoral::ControlList> list (audio_region()->fade_in());
658 Evoral::ControlList::const_iterator x;
659 double length = list->length();
661 points.assign (list->size(), Duple());
663 for (x = list->begin(), pi = 0; x != list->end(); ++x, ++pi) {
664 points[pi].x = (pwidth * ((*x)->when/length));
665 points[pi].y = effective_height - ((*x)->value * (effective_height - 1.));
670 redraw_start_xfade_to (ar, width, points, effective_height, handle_left);
672 /* ensure trim handle stays on top */
673 if (frame_handle_start) {
674 frame_handle_start->raise_to_top();
679 AudioRegionView::reset_fade_out_shape ()
681 reset_fade_out_shape_width (audio_region(), (framecnt_t) audio_region()->fade_out()->back()->when);
685 AudioRegionView::reset_fade_out_shape_width (boost::shared_ptr<AudioRegion> ar, framecnt_t width, bool drag_active)
687 trim_fade_out_drag_active = drag_active;
688 if (fade_out_handle == 0) {
692 /* smallest size for a fade is 64 frames */
694 width = std::max ((framecnt_t) 64, width);
697 double const pwidth = floor(trackview.editor().sample_to_pixel (width));
699 /* the right edge should be right on the region frame is the pixel
700 * width is zero. Hence the additional + 1.0 at the end.
703 double const handle_right = rint(trackview.editor().sample_to_pixel (_region->length()) - pwidth);
704 double const trim_handle_right = rint(trackview.editor().sample_to_pixel (_region->length()));
706 /* Put the fade out handle so that its right side is at the end-of-fade line;
708 fade_out_handle->set_x0 (handle_right - handle_size);
709 fade_out_handle->set_x1 (handle_right);
710 if (fade_out_trim_handle) {
711 fade_out_trim_handle->set_x0 (1 + trim_handle_right - handle_size);
712 fade_out_trim_handle->set_x1 (1 + trim_handle_right);
715 if (fade_out_handle->visible()) {
716 //see comment for drag_start
719 /* don't show shape if its too small */
726 if (!trackview.session()->config.get_show_region_fades()) {
731 double effective_height;
733 effective_height = _height;
735 if (UIConfiguration::instance().get_show_name_highlight() && effective_height >= NAME_HIGHLIGHT_THRESH) {
736 effective_height -= NAME_HIGHLIGHT_SIZE;
739 /* points *MUST* be in anti-clockwise order */
742 Points::size_type pi;
743 boost::shared_ptr<const Evoral::ControlList> list (audio_region()->fade_out());
744 Evoral::ControlList::const_iterator x;
745 double length = list->length();
747 points.assign (list->size(), Duple());
749 for (x = list->begin(), pi = 0; x != list->end(); ++x, ++pi) {
750 points[pi].x = _pixel_width - pwidth + (pwidth * ((*x)->when/length));
751 points[pi].y = effective_height - ((*x)->value * (effective_height - 1.));
756 redraw_end_xfade_to (ar, width, points, effective_height, handle_right, pwidth);
758 /* ensure trim handle stays on top */
759 if (frame_handle_end) {
760 frame_handle_end->raise_to_top();
765 AudioRegionView::get_fade_in_shape_width ()
767 return audio_region()->fade_in()->back()->when;
771 AudioRegionView::get_fade_out_shape_width ()
773 return audio_region()->fade_out()->back()->when;
778 AudioRegionView::redraw_start_xfade ()
780 boost::shared_ptr<AudioRegion> ar (audio_region());
782 if (!ar->fade_in() || ar->fade_in()->empty()) {
787 reset_fade_in_shape_width (ar, ar->fade_in()->back()->when);
791 AudioRegionView::redraw_start_xfade_to (boost::shared_ptr<AudioRegion> ar, framecnt_t /*width*/, Points& points, double effective_height,
794 if (points.size() < 2) {
798 if (!start_xfade_curve) {
799 start_xfade_curve = new ArdourCanvas::XFadeCurve (group, ArdourCanvas::XFadeCurve::Start);
800 CANVAS_DEBUG_NAME (start_xfade_curve, string_compose ("xfade start out line for %1", region()->name()));
801 start_xfade_curve->set_fill_color (UIConfiguration::instance().color_mod ("active crossfade", "crossfade alpha"));
802 start_xfade_curve->set_outline_color (UIConfiguration::instance().color ("crossfade line"));
803 start_xfade_curve->set_ignore_events (true);
805 if (!start_xfade_rect) {
806 start_xfade_rect = new ArdourCanvas::Rectangle (group);
807 CANVAS_DEBUG_NAME (start_xfade_rect, string_compose ("xfade start rect for %1", region()->name()));
808 start_xfade_rect->set_outline_color (UIConfiguration::instance().color ("crossfade line"));
809 start_xfade_rect->set_fill (false);
810 start_xfade_rect->set_outline (false);
811 start_xfade_rect->Event.connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_start_xfade_event), start_xfade_rect, this));
812 start_xfade_rect->set_data ("regionview", this);
815 start_xfade_rect->set (ArdourCanvas::Rect (0.0, 0.0, rect_width, effective_height));
819 boost::shared_ptr<AutomationList> inverse = ar->inverse_fade_in ();
821 Points::size_type npoints;
825 /* there is no explicit inverse fade in curve, so take the
826 * regular fade in curve given to use as "points" (already a
827 * set of coordinates), and convert to the inverse shape.
830 npoints = points.size();
831 ipoints.assign (npoints, Duple());
833 for (Points::size_type i = 0, pci = 0; i < npoints; ++i, ++pci) {
834 ArdourCanvas::Duple &p (ipoints[pci]);
835 /* leave x-axis alone but invert with respect to y-axis */
836 p.y = effective_height - points[pci].y;
841 /* there is an explicit inverse fade in curve. Grab the points
842 and convert them into coordinates for the inverse fade in
846 npoints = inverse->size();
847 ipoints.assign (npoints, Duple());
849 Evoral::ControlList::const_iterator x;
850 Points::size_type pi;
851 double length = inverse->length();
853 for (x = inverse->begin(), pi = 0; x != inverse->end(); ++x, ++pi) {
854 ArdourCanvas::Duple& p (ipoints[pi]);
855 p.x = (rect_width * ((*x)->when/length));
856 p.y = effective_height - ((*x)->value * (effective_height));
860 start_xfade_curve->set_inout (points, ipoints);
866 AudioRegionView::redraw_end_xfade ()
868 boost::shared_ptr<AudioRegion> ar (audio_region());
870 if (!ar->fade_out() || ar->fade_out()->empty()) {
876 reset_fade_out_shape_width (ar, ar->fade_out()->back()->when);
880 AudioRegionView::redraw_end_xfade_to (boost::shared_ptr<AudioRegion> ar, framecnt_t width, Points& points, double effective_height,
881 double rect_edge, double rect_width)
883 if (points.size() < 2) {
887 if (!end_xfade_curve) {
888 end_xfade_curve = new ArdourCanvas::XFadeCurve (group, ArdourCanvas::XFadeCurve::End);
889 CANVAS_DEBUG_NAME (end_xfade_curve, string_compose ("xfade end out line for %1", region()->name()));
890 end_xfade_curve->set_fill_color (UIConfiguration::instance().color_mod ("active crossfade", "crossfade alpha"));
891 end_xfade_curve->set_outline_color (UIConfiguration::instance().color ("crossfade line"));
892 end_xfade_curve->set_ignore_events (true);
895 if (!end_xfade_rect) {
896 end_xfade_rect = new ArdourCanvas::Rectangle (group);
897 CANVAS_DEBUG_NAME (end_xfade_rect, string_compose ("xfade end rect for %1", region()->name()));
898 end_xfade_rect->set_outline_color (UIConfiguration::instance().color ("crossfade line"));
899 end_xfade_rect->set_fill (false);
900 end_xfade_rect->set_outline (false);
901 end_xfade_rect->Event.connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_end_xfade_event), end_xfade_rect, this));
902 end_xfade_rect->set_data ("regionview", this);
905 end_xfade_rect->set (ArdourCanvas::Rect (rect_edge, 0.0, rect_edge + rect_width, effective_height));
909 boost::shared_ptr<AutomationList> inverse = ar->inverse_fade_out ();
911 Points::size_type npoints;
915 /* there is no explicit inverse fade out curve, so take the
916 * regular fade out curve given to use as "points" (already a
917 * set of coordinates), and convert to the inverse shape.
920 npoints = points.size();
921 ipoints.assign (npoints, Duple());
923 Points::size_type pci;
925 for (pci = 0; pci < npoints; ++pci) {
926 ArdourCanvas::Duple &p (ipoints[pci]);
927 p.y = effective_height - points[pci].y;
932 /* there is an explicit inverse fade out curve. Grab the points
933 and convert them into coordinates for the inverse fade out
937 npoints = inverse->size();
938 ipoints.assign (npoints, Duple());
940 const double rend = trackview.editor().sample_to_pixel (_region->length() - width);
942 Evoral::ControlList::const_iterator x;
943 Points::size_type pi;
944 double length = inverse->length();
946 for (x = inverse->begin(), pi = 0; x != inverse->end(); ++x, ++pi) {
947 ArdourCanvas::Duple& p (ipoints[pi]);
948 p.x = (rect_width * ((*x)->when/length)) + rend;
949 p.y = effective_height - ((*x)->value * (effective_height));
953 end_xfade_curve->set_inout (ipoints, points);
959 AudioRegionView::hide_xfades ()
966 AudioRegionView::hide_start_xfade ()
968 if (start_xfade_curve) {
969 start_xfade_curve->hide();
971 if (start_xfade_rect) {
972 start_xfade_rect->hide ();
975 _start_xfade_visible = false;
979 AudioRegionView::hide_end_xfade ()
981 if (end_xfade_curve) {
982 end_xfade_curve->hide();
984 if (end_xfade_rect) {
985 end_xfade_rect->hide ();
988 _end_xfade_visible = false;
992 AudioRegionView::show_start_xfade ()
994 if (start_xfade_curve) {
995 start_xfade_curve->show();
997 if (start_xfade_rect) {
998 start_xfade_rect->show ();
1001 _start_xfade_visible = true;
1005 AudioRegionView::show_end_xfade ()
1007 if (end_xfade_curve) {
1008 end_xfade_curve->show();
1010 if (end_xfade_rect) {
1011 end_xfade_rect->show ();
1014 _end_xfade_visible = true;
1018 AudioRegionView::set_samples_per_pixel (gdouble fpp)
1020 RegionView::set_samples_per_pixel (fpp);
1022 if (UIConfiguration::instance().get_show_waveforms ()) {
1023 for (uint32_t n = 0; n < waves.size(); ++n) {
1024 waves[n]->set_samples_per_pixel (fpp);
1029 gain_line->reset ();
1032 reset_fade_shapes ();
1036 AudioRegionView::set_amplitude_above_axis (gdouble a)
1038 for (uint32_t n=0; n < waves.size(); ++n) {
1039 waves[n]->set_amplitude_above_axis (a);
1044 AudioRegionView::set_colors ()
1046 RegionView::set_colors();
1049 gain_line->set_line_color (audio_region()->envelope_active() ?
1050 UIConfiguration::instance().color ("gain line") :
1051 UIConfiguration::instance().color_mod ("gain line inactive", "gain line inactive"));
1054 set_waveform_colors ();
1056 if (start_xfade_curve) {
1057 start_xfade_curve->set_fill_color (UIConfiguration::instance().color_mod ("active crossfade", "crossfade alpha"));
1058 start_xfade_curve->set_outline_color (UIConfiguration::instance().color ("crossfade line"));
1060 if (end_xfade_curve) {
1061 end_xfade_curve->set_fill_color (UIConfiguration::instance().color_mod ("active crossfade", "crossfade alpha"));
1062 end_xfade_curve->set_outline_color (UIConfiguration::instance().color ("crossfade line"));
1065 if (start_xfade_rect) {
1066 start_xfade_rect->set_outline_color (UIConfiguration::instance().color ("crossfade line"));
1068 if (end_xfade_rect) {
1069 end_xfade_rect->set_outline_color (UIConfiguration::instance().color ("crossfade line"));
1074 AudioRegionView::setup_waveform_visibility ()
1076 if (UIConfiguration::instance().get_show_waveforms ()) {
1077 for (uint32_t n = 0; n < waves.size(); ++n) {
1078 /* make sure the zoom level is correct, since we don't update
1079 this when waveforms are hidden.
1082 // waves[n]->set_samples_per_pixel (_samples_per_pixel);
1086 for (uint32_t n = 0; n < waves.size(); ++n) {
1093 AudioRegionView::temporarily_hide_envelope ()
1101 AudioRegionView::unhide_envelope ()
1103 update_envelope_visibility ();
1107 AudioRegionView::update_envelope_visibility ()
1113 if (trackview.editor().current_mouse_mode() == Editing::MouseDraw || trackview.editor().current_mouse_mode() == Editing::MouseContent ) {
1114 gain_line->set_visibility (AutomationLine::VisibleAspects(AutomationLine::ControlPoints|AutomationLine::Line));
1115 gain_line->canvas_group().raise_to_top ();
1116 } else if (UIConfiguration::instance().get_show_region_gain() || trackview.editor().current_mouse_mode() == Editing::MouseRange ) {
1117 gain_line->set_visibility (AutomationLine::VisibleAspects(AutomationLine::Line));
1118 gain_line->canvas_group().raise_to_top ();
1120 gain_line->set_visibility (AutomationLine::VisibleAspects(0));
1125 AudioRegionView::delete_waves ()
1127 for (vector<ScopedConnection*>::iterator i = _data_ready_connections.begin(); i != _data_ready_connections.end(); ++i) {
1130 _data_ready_connections.clear ();
1132 for (vector<WaveView*>::iterator w = waves.begin(); w != waves.end(); ++w) {
1137 pending_peak_data->show ();
1141 AudioRegionView::create_waves ()
1143 // cerr << "AudioRegionView::create_waves() called on " << this << endl;//DEBUG
1144 RouteTimeAxisView& atv (*(dynamic_cast<RouteTimeAxisView*>(&trackview))); // ick
1150 ChanCount nchans = atv.track()->n_channels();
1152 // cerr << "creating waves for " << _region->name() << " with wfd = " << wait_for_data
1153 // << " and channels = " << nchans.n_audio() << endl;
1155 /* in tmp_waves, set up null pointers for each channel so the vector is allocated */
1156 for (uint32_t n = 0; n < nchans.n_audio(); ++n) {
1157 tmp_waves.push_back (0);
1160 for (vector<ScopedConnection*>::iterator i = _data_ready_connections.begin(); i != _data_ready_connections.end(); ++i) {
1164 _data_ready_connections.clear ();
1166 for (uint32_t i = 0; i < nchans.n_audio(); ++i) {
1167 _data_ready_connections.push_back (0);
1170 for (uint32_t n = 0; n < nchans.n_audio(); ++n) {
1172 if (n >= audio_region()->n_channels()) {
1176 // cerr << "\tchannel " << n << endl;
1178 if (wait_for_data) {
1179 if (audio_region()->audio_source(n)->peaks_ready (boost::bind (&AudioRegionView::peaks_ready_handler, this, n), &_data_ready_connections[n], gui_context())) {
1180 // cerr << "\tData is ready\n";
1181 create_one_wave (n, true);
1183 // cerr << "\tdata is not ready\n";
1184 // we'll get a PeaksReady signal from the source in the future
1185 // and will call create_one_wave(n) then.
1186 pending_peak_data->show ();
1190 // cerr << "\tdon't delay, display today!\n";
1191 create_one_wave (n, true);
1198 AudioRegionView::create_one_wave (uint32_t which, bool /*direct*/)
1200 //cerr << "AudioRegionView::create_one_wave() called which: " << which << " this: " << this << endl;//DEBUG
1201 RouteTimeAxisView& atv (*(dynamic_cast<RouteTimeAxisView*>(&trackview))); // ick
1202 if (!trackview.session() || trackview.session()->deletion_in_progress () || !atv.track()) {
1203 /* peaks_ready_handler() may be called from peak_thread_work() while
1204 * session deletion is in progress.
1205 * Since session-unload happens in the GUI thread, we need to test
1210 uint32_t nchans = atv.track()->n_channels().n_audio();
1212 uint32_t nwaves = std::min (nchans, audio_region()->n_channels());
1215 /* compare to set_height(), use _height as set by streamview (child_height),
1216 * not trackview.current_height() to take stacked layering into acconnt
1218 if (!UIConfiguration::instance().get_show_name_highlight() || (_height < NAME_HIGHLIGHT_THRESH)) {
1219 ht = _height / (double) nchans;
1221 ht = (_height - NAME_HIGHLIGHT_SIZE) / (double) nchans;
1224 /* first waveview starts at 1.0, not 0.0 since that will overlap the
1228 gdouble yoff = which * ht;
1230 WaveView *wave = new WaveView (group, audio_region ());
1231 CANVAS_DEBUG_NAME (wave, string_compose ("wave view for chn %1 of %2", which, get_item_name()));
1233 wave->set_channel (which);
1234 wave->set_y_position (yoff);
1235 wave->set_height (ht);
1236 wave->set_samples_per_pixel (samples_per_pixel);
1237 wave->set_show_zero_line (true);
1238 wave->set_clip_level (UIConfiguration::instance().get_waveform_clip_level ());
1239 wave->set_start_shift (1.0);
1241 wave->Event.connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_wave_view_event), wave, this));
1243 switch (UIConfiguration::instance().get_waveform_shape()) {
1245 wave->set_shape (WaveView::Rectified);
1248 wave->set_shape (WaveView::Normal);
1251 wave->set_logscaled (UIConfiguration::instance().get_waveform_scale() == Logarithmic);
1253 vector<ArdourCanvas::WaveView*> v;
1255 set_some_waveform_colors (v);
1257 if (!UIConfiguration::instance().get_show_waveforms ()) {
1261 /* note: calling this function is serialized by the lock
1262 held in the peak building thread that signals that
1263 peaks are ready for use *or* by the fact that it is
1264 called one by one from the GUI thread.
1267 if (which < nchans) {
1268 tmp_waves[which] = wave;
1270 /* n-channel track, >n-channel source */
1273 /* see if we're all ready */
1275 for (n = 0; n < nchans; ++n) {
1276 if (tmp_waves[n] == 0) {
1281 if (n == nwaves && waves.empty()) {
1282 /* all waves are ready */
1283 tmp_waves.resize(nwaves);
1288 /* indicate peak-completed */
1289 pending_peak_data->hide ();
1291 /* Restore stacked coverage */
1292 std::string str = trackview.gui_property ("layer-display");
1294 LayerDisplay layer_display;
1295 update_coverage_frames (LayerDisplay (string_2_enum (str, layer_display)));
1299 /* channel wave created, don't hook into peaks ready anymore */
1300 delete _data_ready_connections[which];
1301 _data_ready_connections[which] = 0;
1305 AudioRegionView::peaks_ready_handler (uint32_t which)
1307 Gtkmm2ext::UI::instance()->call_slot (invalidator (*this), boost::bind (&AudioRegionView::create_one_wave, this, which, false));
1308 // cerr << "AudioRegionView::peaks_ready_handler() called on " << which << " this: " << this << endl;
1312 AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev, bool with_guard_points)
1318 uint32_t before_p, after_p;
1319 double mx = ev->button.x;
1320 double my = ev->button.y;
1322 item->canvas_to_item (mx, my);
1324 framecnt_t const frame_within_region = (framecnt_t) floor (mx * samples_per_pixel);
1326 if (!gain_line->control_points_adjacent (frame_within_region, before_p, after_p)) {
1327 /* no adjacent points */
1331 /*y is in item frame */
1332 double const bx = gain_line->nth (before_p)->get_x();
1333 double const ax = gain_line->nth (after_p)->get_x();
1334 double const click_ratio = (ax - mx) / (ax - bx);
1336 double y = ((gain_line->nth (before_p)->get_y() * click_ratio) + (gain_line->nth (after_p)->get_y() * (1 - click_ratio)));
1338 /* don't create points that can't be seen */
1340 update_envelope_visibility ();
1342 framepos_t rpos = region ()->position ();
1343 framepos_t fx = trackview.editor().pixel_to_sample (mx) + rpos;
1344 trackview.editor ().snap_to_with_modifier (fx, ev);
1347 if (fx > _region->length()) {
1351 /* compute vertical fractional position */
1353 y = 1.0 - (y / (gain_line->height()));
1355 /* map using gain line */
1357 gain_line->view_to_model_coord (mx, y);
1359 /* XXX STATEFUL: can't convert to stateful diff until we
1360 can represent automation data with it.
1363 XMLNode &before = audio_region()->envelope()->get_state();
1364 MementoCommand<AudioRegion>* region_memento = 0;
1366 if (!audio_region()->envelope_active()) {
1367 XMLNode ®ion_before = audio_region()->get_state();
1368 audio_region()->set_envelope_active(true);
1369 XMLNode ®ion_after = audio_region()->get_state();
1370 region_memento = new MementoCommand<AudioRegion>(*(audio_region().get()), ®ion_before, ®ion_after);
1373 if (audio_region()->envelope()->editor_add (fx, y, with_guard_points)) {
1374 XMLNode &after = audio_region()->envelope()->get_state();
1375 std::list<Selectable*> results;
1377 trackview.editor().begin_reversible_command (_("add gain control point"));
1379 if (region_memento) {
1380 trackview.session()->add_command (region_memento);
1383 trackview.session()->add_command (new MementoCommand<AutomationList>(*audio_region()->envelope().get(), &before, &after));
1385 gain_line->get_selectables (fx + region ()->position (), fx + region ()->position (), 0.0, 1.0, results);
1386 trackview.editor ().get_selection ().set (results);
1388 trackview.editor ().commit_reversible_command ();
1389 trackview.session ()->set_dirty ();
1394 AudioRegionView::remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent* /*ev*/)
1396 ControlPoint *cp = reinterpret_cast<ControlPoint *> (item->get_data ("control_point"));
1397 audio_region()->envelope()->erase (cp->model());
1401 AudioRegionView::add_ghost (TimeAxisView& tv)
1403 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(&trackview);
1409 double unit_position = _region->position () / samples_per_pixel;
1410 AudioGhostRegion* ghost = new AudioGhostRegion (*this, tv, trackview, unit_position);
1413 nchans = rtv->track()->n_channels().n_audio();
1415 for (uint32_t n = 0; n < nchans; ++n) {
1417 if (n >= audio_region()->n_channels()) {
1421 WaveView *wave = new WaveView (ghost->group, audio_region());
1422 CANVAS_DEBUG_NAME (wave, string_compose ("ghost wave for %1", get_item_name()));
1424 wave->set_channel (n);
1425 wave->set_samples_per_pixel (samples_per_pixel);
1426 wave->set_amplitude_above_axis (_amplitude_above_axis);
1428 ghost->waves.push_back(wave);
1431 ghost->set_height ();
1432 ghost->set_duration (_region->length() / samples_per_pixel);
1433 ghost->set_colors();
1434 ghosts.push_back (ghost);
1440 AudioRegionView::entered ()
1442 trackview.editor().set_current_trimmable (_region);
1443 trackview.editor().set_current_movable (_region);
1445 update_envelope_visibility();
1447 if ((trackview.editor().current_mouse_mode() == Editing::MouseObject)) {
1448 if (start_xfade_rect) {
1449 start_xfade_rect->set_outline (true);
1451 if (end_xfade_rect) {
1452 end_xfade_rect->set_outline (true);
1454 if (fade_in_handle) {
1455 fade_in_handle->show ();
1456 fade_in_handle->raise_to_top ();
1458 if (fade_out_handle) {
1459 fade_out_handle->show ();
1460 fade_out_handle->raise_to_top ();
1462 if (fade_in_trim_handle) {
1463 boost::shared_ptr<AudioRegion> ar (audio_region());
1464 if (!ar->locked() && (ar->fade_in()->back()->when > 64 || (ar->can_trim() & Trimmable::FrontTrimEarlier))) {
1465 fade_in_trim_handle->show ();
1466 fade_in_trim_handle->raise_to_top ();
1468 fade_in_trim_handle->hide ();
1471 if (fade_out_trim_handle) {
1472 boost::shared_ptr<AudioRegion> ar (audio_region());
1473 if (!ar->locked() && (ar->fade_out()->back()->when > 64 || (ar->can_trim() & Trimmable::EndTrimLater))) {
1474 fade_out_trim_handle->show ();
1475 fade_out_trim_handle->raise_to_top ();
1477 fade_out_trim_handle->hide ();
1480 } else { //this happens when we switch tools; if we switch away from Grab mode, hide all the fade handles
1481 if (fade_in_handle) { fade_in_handle->hide(); }
1482 if (fade_out_handle) { fade_out_handle->hide(); }
1483 if (fade_in_trim_handle) { fade_in_trim_handle->hide(); }
1484 if (fade_out_trim_handle) { fade_out_trim_handle->hide(); }
1485 if (start_xfade_rect) { start_xfade_rect->set_outline (false); }
1486 if (end_xfade_rect) { end_xfade_rect->set_outline (false); }
1491 AudioRegionView::exited ()
1493 trackview.editor().set_current_trimmable (boost::shared_ptr<Trimmable>());
1494 trackview.editor().set_current_movable (boost::shared_ptr<Movable>());
1497 // gain_line->remove_visibility (AutomationLine::ControlPoints);
1500 if (fade_in_handle) { fade_in_handle->hide(); }
1501 if (fade_out_handle) { fade_out_handle->hide(); }
1502 if (fade_in_trim_handle) { fade_in_trim_handle->hide(); }
1503 if (fade_out_trim_handle) { fade_out_trim_handle->hide(); }
1504 if (start_xfade_rect) { start_xfade_rect->set_outline (false); }
1505 if (end_xfade_rect) { end_xfade_rect->set_outline (false); }
1509 AudioRegionView::envelope_active_changed ()
1512 gain_line->set_line_color (audio_region()->envelope_active() ?
1513 UIConfiguration::instance().color ("gain line") :
1514 UIConfiguration::instance().color_mod ("gain line inactive", "gain line inactive"));
1515 update_envelope_visibility ();
1520 AudioRegionView::color_handler ()
1522 //case cMutedWaveForm:
1524 //case cWaveFormClip:
1528 //case cGainLineInactive:
1530 envelope_active_changed();
1535 AudioRegionView::set_waveform_colors ()
1537 set_some_waveform_colors (waves);
1541 AudioRegionView::set_some_waveform_colors (vector<ArdourCanvas::WaveView*>& waves_to_color)
1543 ArdourCanvas::Color fill;
1544 ArdourCanvas::Color outline;
1545 ArdourCanvas::Color clip = UIConfiguration::instance().color ("clipped waveform");
1546 ArdourCanvas::Color zero = UIConfiguration::instance().color ("zero line");
1549 if (_region->muted()) {
1550 /* hide outline with zero alpha */
1551 outline = UINT_RGBA_CHANGE_A(UIConfiguration::instance().color ("selected waveform outline"), 0);
1552 fill = UINT_RGBA_CHANGE_A(UIConfiguration::instance().color ("selected waveform fill"), MUTED_ALPHA);
1554 outline = UIConfiguration::instance().color ("selected waveform outline");
1555 fill = UIConfiguration::instance().color ("selected waveform fill");
1559 outline = UIConfiguration::instance().color ("recording waveform outline");
1560 fill = UIConfiguration::instance().color ("recording waveform fill");
1562 if (_region->muted()) {
1563 /* hide outline with zero alpha */
1564 outline = UINT_RGBA_CHANGE_A(UIConfiguration::instance().color ("waveform outline"), 0);
1565 fill = UINT_RGBA_CHANGE_A(UIConfiguration::instance().color ("waveform fill"), MUTED_ALPHA);
1567 outline = UIConfiguration::instance().color ("waveform outline");
1568 fill = UIConfiguration::instance().color ("waveform fill");
1573 for (vector<ArdourCanvas::WaveView*>::iterator w = waves_to_color.begin(); w != waves_to_color.end(); ++w) {
1574 (*w)->set_fill_color (fill);
1575 (*w)->set_outline_color (outline);
1576 (*w)->set_clip_color (clip);
1577 (*w)->set_zero_color (zero);
1582 AudioRegionView::set_frame_color ()
1588 RegionView::set_frame_color ();
1590 set_waveform_colors ();
1594 AudioRegionView::set_fade_visibility (bool yn)
1597 if (start_xfade_curve) { start_xfade_curve->show (); }
1598 if (end_xfade_curve) { end_xfade_curve->show (); }
1599 if (start_xfade_rect) { start_xfade_rect->show (); }
1600 if (end_xfade_rect) { end_xfade_rect->show (); }
1602 if (start_xfade_curve) { start_xfade_curve->hide(); }
1603 if (end_xfade_curve) { end_xfade_curve->hide(); }
1604 if (fade_in_handle) { fade_in_handle->hide(); }
1605 if (fade_out_handle) { fade_out_handle->hide(); }
1606 if (fade_in_trim_handle) { fade_in_trim_handle->hide(); }
1607 if (fade_out_trim_handle) { fade_out_trim_handle->hide(); }
1608 if (start_xfade_rect) { start_xfade_rect->hide (); }
1609 if (end_xfade_rect) { end_xfade_rect->hide (); }
1610 if (start_xfade_rect) { start_xfade_rect->set_outline (false); }
1611 if (end_xfade_rect) { end_xfade_rect->set_outline (false); }
1616 AudioRegionView::update_coverage_frames (LayerDisplay d)
1619 /* don't do coverage frames unless we're in stacked mode */
1623 RegionView::update_coverage_frames (d);
1625 if (fade_in_handle) { fade_in_handle->raise_to_top (); }
1626 if (fade_out_handle) { fade_out_handle->raise_to_top (); }
1627 if (fade_in_trim_handle) { fade_in_trim_handle->raise_to_top (); }
1628 if (fade_out_trim_handle) { fade_out_trim_handle->raise_to_top (); }
1632 AudioRegionView::show_region_editor ()
1635 editor = new AudioRegionEditor (trackview.session(), audio_region());
1643 AudioRegionView::transients_changed ()
1645 AnalysisFeatureList analysis_features;
1646 _region->transients (analysis_features);
1647 framepos_t position = _region->position();
1648 framepos_t first = _region->first_frame();
1649 framepos_t last = _region->last_frame();
1652 if (_height >= NAME_HIGHLIGHT_THRESH) {
1653 y1 = _height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 1;
1658 while (feature_lines.size() < analysis_features.size()) {
1659 ArdourCanvas::Line* canvas_item = new ArdourCanvas::Line(group);
1660 CANVAS_DEBUG_NAME (canvas_item, string_compose ("transient group for %1", region()->name()));
1661 canvas_item->set_outline_color (UIConfiguration::instance().color ("zero line")); // also in Editor::leave_handler()
1663 canvas_item->set (ArdourCanvas::Duple (-1.0, 2.0),
1664 ArdourCanvas::Duple (1.0, y1));
1666 canvas_item->raise_to_top ();
1667 canvas_item->show ();
1669 canvas_item->set_data ("regionview", this);
1670 canvas_item->Event.connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_feature_line_event), canvas_item, this));
1672 feature_lines.push_back (make_pair(0, canvas_item));
1675 while (feature_lines.size() > analysis_features.size()) {
1676 ArdourCanvas::Line* line = feature_lines.back().second;
1677 feature_lines.pop_back ();
1681 AnalysisFeatureList::const_iterator i;
1682 list<std::pair<framepos_t, ArdourCanvas::Line*> >::iterator l;
1684 for (i = analysis_features.begin(), l = feature_lines.begin(); i != analysis_features.end() && l != feature_lines.end(); ++i, ++l) {
1686 float *pos = new float;
1687 *pos = trackview.editor().sample_to_pixel (*i - position);
1690 ArdourCanvas::Duple (*pos, 2.0),
1691 ArdourCanvas::Duple (*pos, y1)
1694 (*l).second->set_data ("position", pos); // is this *modified* (drag?), if not use *i
1697 if (l->first < first || l->first >= last) {
1706 AudioRegionView::update_transient(float /*old_pos*/, float new_pos)
1708 /* Find frame at old pos, calulate new frame then update region transients*/
1709 list<std::pair<framepos_t, ArdourCanvas::Line*> >::iterator l;
1711 for (l = feature_lines.begin(); l != feature_lines.end(); ++l) {
1713 /* Line has been updated in drag so we compare to new_pos */
1715 float* pos = (float*) (*l).second->get_data ("position");
1717 if (rint(new_pos) == rint(*pos)) {
1718 framepos_t position = _region->position();
1719 framepos_t old_frame = (*l).first;
1720 framepos_t new_frame = trackview.editor().pixel_to_sample (new_pos) + position;
1721 _region->update_transient (old_frame, new_frame);
1728 AudioRegionView::remove_transient (float pos)
1730 /* this is called from Editor::remove_transient () with pos == get_data ("position")
1731 * which is the item's x-coordinate inside the ARV.
1733 * Find frame at old pos, calulate new frame then update region transients
1735 list<std::pair<framepos_t, ArdourCanvas::Line*> >::iterator l;
1737 for (l = feature_lines.begin(); l != feature_lines.end(); ++l) {
1738 float *line_pos = (float*) (*l).second->get_data ("position");
1739 if (rint(pos) == rint(*line_pos)) {
1740 _region->remove_transient ((*l).first);
1747 AudioRegionView::thaw_after_trim ()
1749 RegionView::thaw_after_trim ();
1756 AudioRegionView::show_xfades ()
1758 show_start_xfade ();
1763 AudioRegionView::drag_start ()
1765 TimeAxisViewItem::drag_start ();
1767 //we used to hide xfades here. I don't see the point with the new model, but we can re-implement if needed
1771 AudioRegionView::drag_end ()
1773 TimeAxisViewItem::drag_end ();
1774 //see comment for drag_start
1776 if (fade_in_handle && fade_in_handle->visible()) {
1777 // lenght of region or fade changed, re-check
1778 // if fade_in_trim_handle or fade_out_trim_handle should
1779 // be visible. -- If the fade_in_handle is visible
1780 // we have focus and are not in internal edit mode.
1786 AudioRegionView::parameter_changed (string const & p)
1788 if (p == "show-waveforms") {
1789 setup_waveform_visibility ();