2 Copyright (C) 2001 Paul Davis
4 This program is free software; you can redistribute 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.
26 #include <gtkmm2ext/gtk_ui.h>
28 #include <ardour/playlist.h>
29 #include <ardour/audioregion.h>
30 #include <ardour/sndfilesource.h>
31 #include <ardour/diskstream.h>
33 #include "streamview.h"
34 #include "regionview.h"
35 #include "audio_time_axis.h"
36 #include "canvas-simplerect.h"
37 #include "canvas-simpleline.h"
38 #include "canvas-waveview.h"
39 #include "public_editor.h"
40 #include "region_editor.h"
41 #include "region_gain_line.h"
42 #include "ghostregion.h"
43 #include "audio_time_axis.h"
45 #include "rgb_macros.h"
46 #include "gui_thread.h"
51 using namespace ARDOUR;
52 using namespace Editing;
54 static const int32_t sync_mark_width = 9;
56 sigc::signal<void,AudioRegionView*> AudioRegionView::AudioRegionViewGoingAway;
58 AudioRegionView::AudioRegionView (Gnome::Canvas::Group *parent, AudioTimeAxisView &tv,
61 double amplitude_above_axis,
62 Gdk::Color& basic_color,
65 : TimeAxisViewItem (r.name(), parent, tv, spu, basic_color, r.position(), r.length(),
66 TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowNameText|
67 TimeAxisViewItem::ShowNameHighlight|
68 TimeAxisViewItem::ShowFrame)),
72 Gnome::Canvas::Points *shape;
77 in_destructor = false;
78 _amplitude_above_axis = amplitude_above_axis;
85 if ((node = region.extra_xml ("GUI")) != 0) {
88 _flags = WaveformVisible;
92 if (trackview.editor.new_regionviews_display_gain()) {
93 _flags |= EnvelopeVisible;
96 compute_colors (basic_color);
100 gtk_object_set_data (GTK_OBJECT(name_highlight), "regionview", this);
101 gtk_object_set_data (GTK_OBJECT(name_text), "regionview", this);
103 shape = new Gnome::Canvas::Points ();
105 /* an equilateral triangle */
107 shape->push_back (Gnome::Art::Point (-((sync_mark_width-1)/2), 1));
108 shape->push_back (Gnome::Art::Point ((sync_mark_width - 1)/2, 1));
109 shape->push_back (Gnome::Art::Point (0, sync_mark_width - 1));
110 shape->push_back (Gnome::Art::Point (-((sync_mark_width-1)/2), 1));
112 sync_mark = new Gnome::Canvas::Polygon (*group);
113 sync_mark->set_property ("points", shape);
114 sync_mark->set_property ("fill_color_rgba", fill_color);
116 gnome_canvas_points_unref (shape->gobj());
118 fade_in_shape = new Gnome::Canvas::Polygon (*group);
119 fade_in_shape->set_property ("fill_color_rgba", fade_color);
120 fade_in_shape->set_data ("regionview", this);
122 fade_out_shape = new Gnome::Canvas::Polygon (*group);
123 fade_out_shape->set_property ("fill_color_rgba", fade_color);
124 fade_out_shape->set_data ("regionview", this);
130 UINT_TO_RGBA(fill_color,&r,&g,&b,&a);
133 fade_in_handle = new Gnome::Canvas::SimpleRect (*group);
134 fade_in_handle->set_property ("fill_color_rgba", RGBA_TO_UINT(r,g,b,0));
135 fade_in_handle->set_property ("outline_pixels", 0);
136 fade_in_handle->set_property ("y1", 2.0);
137 fade_in_handle->set_property ("y2", 7.0);
139 fade_in_handle->set_data ("regionview", this);
141 fade_out_handle = new Gnome::Canvas::SimpleRect (*group);
142 fade_out_handle->set_property ("fill_color_rgba", RGBA_TO_UINT(r,g,b,0));
143 fade_out_handle->set_property ("outline_pixels", 0);
144 fade_out_handle->set_property ("y1", 2.0);
145 fade_out_handle->set_property ("y2", 7.0);
147 gtk_object_set_data (GTK_OBJECT(fade_out_handle), "regionview", this);
150 string foo = region.name();
154 gain_line = new AudioRegionGainLine (foo, tv.session(), *this, &group, region.envelope(),
155 PublicEditor::canvas_control_point_event,
156 PublicEditor::canvas_line_event);
158 if (!(_flags & EnvelopeVisible)) {
164 reset_width_dependent_items ((double) region.length() / samples_per_unit);
168 set_height (trackview.height);
171 region_sync_changed ();
172 region_resized (BoundsChanged);
173 set_waveview_data_src();
175 envelope_active_changed ();
176 fade_in_active_changed ();
177 fade_out_active_changed ();
179 region.StateChanged.connect (mem_fun(*this, &AudioRegionView::region_changed));
181 gtk_signal_connect (GTK_OBJECT(group), "event",
182 GTK_SIGNAL_FUNC (PublicEditor::canvas_region_view_event),
184 gtk_signal_connect (GTK_OBJECT(name_highlight), "event",
185 GTK_SIGNAL_FUNC (PublicEditor::canvas_region_view_name_highlight_event),
188 gtk_signal_connect (GTK_OBJECT(name_text), "event",
189 GTK_SIGNAL_FUNC (PublicEditor::canvas_region_view_name_event),
192 gtk_signal_connect (GTK_OBJECT(fade_in_shape), "event",
193 GTK_SIGNAL_FUNC (PublicEditor::canvas_fade_in_event),
196 gtk_signal_connect (GTK_OBJECT(fade_in_handle), "event",
197 GTK_SIGNAL_FUNC (PublicEditor::canvas_fade_in_handle_event),
200 gtk_signal_connect (GTK_OBJECT(fade_out_shape), "event",
201 GTK_SIGNAL_FUNC ( PublicEditor::canvas_fade_out_event),
204 gtk_signal_connect_object (GTK_OBJECT(fade_out_handle), "event",
205 GTK_SIGNAL_FUNC ( PublicEditor::canvas_fade_out_handle_event),
210 /* XXX sync mark drag? */
214 AudioRegionView::~AudioRegionView ()
216 in_destructor = true;
218 AudioRegionViewGoingAway (this); /* EMIT_SIGNAL */
220 for (vector<GnomeCanvasWaveViewCache *>::iterator cache = wave_caches.begin(); cache != wave_caches.end() ; ++cache) {
221 gnome_canvas_waveview_cache_destroy (*cache);
224 /* all waveviews will be destroyed when the group is destroyed */
226 for (vector<GhostRegion*>::iterator g = ghosts.begin(); g != ghosts.end(); ++g) {
238 AudioRegionView::_lock_toggle (Gnome::Canvas::Item* item, GdkEvent* ev, void* arg)
241 case GDK_BUTTON_RELEASE:
242 static_cast<AudioRegionView*>(arg)->lock_toggle ();
252 AudioRegionView::lock_toggle ()
254 region.set_locked (!region.locked());
258 AudioRegionView::region_changed (Change what_changed)
260 ENSURE_GUI_THREAD (bind (mem_fun(*this, &AudioRegionView::region_changed), what_changed));
262 if (what_changed & BoundsChanged) {
263 region_resized (what_changed);
264 region_sync_changed ();
266 if (what_changed & Region::MuteChanged) {
269 if (what_changed & Region::OpacityChanged) {
272 if (what_changed & ARDOUR::NameChanged) {
275 if (what_changed & Region::SyncOffsetChanged) {
276 region_sync_changed ();
278 if (what_changed & Region::LayerChanged) {
281 if (what_changed & Region::LockChanged) {
284 if (what_changed & AudioRegion::ScaleAmplitudeChanged) {
285 region_scale_amplitude_changed ();
287 if (what_changed & AudioRegion::FadeInChanged) {
290 if (what_changed & AudioRegion::FadeOutChanged) {
293 if (what_changed & AudioRegion::FadeInActiveChanged) {
294 fade_in_active_changed ();
296 if (what_changed & AudioRegion::FadeOutActiveChanged) {
297 fade_out_active_changed ();
299 if (what_changed & AudioRegion::EnvelopeActiveChanged) {
300 envelope_active_changed ();
305 AudioRegionView::fade_in_changed ()
307 reset_fade_in_shape ();
311 AudioRegionView::fade_out_changed ()
313 reset_fade_out_shape ();
317 AudioRegionView::set_fade_in_active (bool yn)
319 region.set_fade_in_active (yn);
323 AudioRegionView::set_fade_out_active (bool yn)
325 region.set_fade_out_active (yn);
329 AudioRegionView::fade_in_active_changed ()
333 UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
335 if (region.fade_in_active()) {
336 col = RGBA_TO_UINT(r,g,b,120);
337 fade_in_shape->set_property ("fill_color_rgba", col);
338 fade_in_shape->set_property ("width_pixels", 0);
339 fade_in_shape->set_property ("outline_color_rgba", RGBA_TO_UINT(r,g,b,0));
341 col = RGBA_TO_UINT(r,g,b,0);
342 fade_in_shape->set_property ("fill_color_rgba", col);
343 fade_in_shape->set_property ("width_pixels", 1);
344 fade_in_shape->set_property ("outline_color_rgba", RGBA_TO_UINT(r,g,b,255));
349 AudioRegionView::fade_out_active_changed ()
353 UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
355 if (region.fade_out_active()) {
356 col = RGBA_TO_UINT(r,g,b,120);
357 fade_out_shape->set_property ("fill_color_rgba", col);
358 fade_out_shape->set_property ("width_pixels", 0);
359 fade_out_shape->set_property ("outline_color_rgba", RGBA_TO_UINT(r,g,b,0));
361 col = RGBA_TO_UINT(r,g,b,0);
362 fade_out_shape->set_property ("fill_color_rgba", col);
363 fade_out_shape->set_property ("width_pixels", 1);
364 fade_out_shape->set_property ("outline_color_rgba", RGBA_TO_UINT(r,g,b,255));
370 AudioRegionView::region_scale_amplitude_changed ()
372 ENSURE_GUI_THREAD (mem_fun(*this, &AudioRegionView::region_scale_amplitude_changed));
374 for (uint32_t n = 0; n < waves.size(); ++n) {
375 // force a reload of the cache
376 gnome_canvas_item_set (waves[n], "data_src", ®ion, NULL);
381 AudioRegionView::region_locked ()
383 /* name will show locked status */
388 AudioRegionView::region_resized (Change what_changed)
392 if (what_changed & ARDOUR::PositionChanged) {
393 set_position (region.position(), 0);
396 if (what_changed & Change (StartChanged|LengthChanged)) {
398 set_duration (region.length(), 0);
400 unit_length = region.length() / samples_per_unit;
402 reset_width_dependent_items (unit_length);
404 for (uint32_t n = 0; n < waves.size(); ++n) {
405 gnome_canvas_item_set (waves[n], "region_start", (guint32) region.start(), NULL);
408 for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
410 (*i)->set_duration (unit_length);
412 for (vector<GnomeCanvasItem*>::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) {
413 gnome_canvas_item_set ((*w), "region_start", region.start(), NULL);
420 AudioRegionView::reset_width_dependent_items (double pixel_width)
422 TimeAxisViewItem::reset_width_dependent_items (pixel_width);
423 _pixel_width = pixel_width;
426 zero_line->set_property ("x2", pixel_width - 1.0);
429 if (pixel_width <= 6.0) {
430 fade_in_handle->hide();
431 fade_out_handle->hide();
434 fade_in_handle->hide();
435 fade_out_handle->hide();
437 fade_in_handle->show();
438 fade_out_handle->show();
442 reset_fade_shapes ();
446 AudioRegionView::region_layered ()
448 AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (&get_time_axis_view());
449 atv->view->region_layered (this);
453 AudioRegionView::region_muted ()
458 for (uint32_t n=0; n < waves.size(); ++n) {
459 if (region.muted()) {
460 gnome_canvas_item_set (waves[n], "wave_color", color_map[cMutedWaveForm], NULL);
462 gnome_canvas_item_set (waves[n], "wave_color", color_map[cWaveForm], NULL);
468 AudioRegionView::region_opacity ()
474 AudioRegionView::raise ()
480 AudioRegionView::raise_to_top ()
482 region.raise_to_top ();
486 AudioRegionView::lower ()
492 AudioRegionView::lower_to_bottom ()
494 region.lower_to_bottom ();
498 AudioRegionView::set_position (jack_nframes_t pos, void* src, double* ignored)
503 if (!(ret = TimeAxisViewItem::set_position (pos, this, &delta))) {
512 for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
513 (*i)->group->move (delta, 0.0);
521 AudioRegionView::set_height (gdouble height)
523 uint32_t wcnt = waves.size();
525 TimeAxisViewItem::set_height (height - 2);
529 for (uint32_t n=0; n < wcnt; ++n) {
532 if ((height) < NAME_HIGHLIGHT_THRESH) {
533 ht = ((height-2*wcnt) / (double) wcnt);
535 ht = (((height-2*wcnt) - NAME_HIGHLIGHT_SIZE) / (double) wcnt);
538 gdouble yoff = n * (ht+1);
540 gnome_canvas_item_set (waves[n], "height", ht, NULL);
541 gnome_canvas_item_set (waves[n], "y", yoff + 2, NULL);
544 if ((height/wcnt) < NAME_HIGHLIGHT_SIZE) {
547 if (_flags & EnvelopeVisible) {
553 gain_line->set_height ((uint32_t) rint (height - NAME_HIGHLIGHT_SIZE));
554 reset_fade_shapes ();
556 name_text->raise_to_top();
560 AudioRegionView::manage_zero_line ()
566 if (_height >= 100) {
567 gdouble wave_midpoint = (_height - NAME_HIGHLIGHT_SIZE) / 2.0;
568 zero_line->set_property ("y1", wave_midpoint);
569 zero_line->set_property ("y2", wave_midpoint);
577 AudioRegionView::reset_fade_shapes ()
579 reset_fade_in_shape ();
580 reset_fade_out_shape ();
584 AudioRegionView::reset_fade_in_shape ()
586 reset_fade_in_shape_width ((jack_nframes_t) region.fade_in().back()->when);
590 AudioRegionView::reset_fade_in_shape_width (jack_nframes_t width)
592 /* smallest size for a fade is 64 frames */
594 width = std::max ((jack_nframes_t) 64, width);
596 GnomeCanvasPoints* points;
597 double pwidth = width / samples_per_unit;
598 uint32_t npoints = std::min (gdk_screen_width(), (int) pwidth);
602 fade_in_shape->hide();
603 fade_in_handle->hide();
607 double handle_center;
608 handle_center = pwidth;
610 if (handle_center > 7.0) {
611 handle_center -= 3.0;
616 fade_in_handle->set_property ("x1", handle_center - 3.0);
617 fade_in_handle->set_property ("x2", handle_center + 3.0);
620 fade_in_shape->hide();
624 fade_in_shape->show();
626 float curve[npoints];
627 region.fade_in().get_vector (0, region.fade_in().back()->when, curve, npoints);
629 points = get_canvas_points ("fade in shape", npoints+3);
631 if (_height > NAME_HIGHLIGHT_THRESH) {
632 h = _height - NAME_HIGHLIGHT_SIZE;
637 /* points *MUST* be in anti-clockwise order */
640 double xdelta = pwidth/npoints;
642 for (pi = 0, pc = 0; pc < npoints; ++pc) {
643 points->coords[pi++] = 1 + (pc * xdelta);
644 points->coords[pi++] = 2 + (h - (curve[pc] * h));
649 points->coords[pi++] = pwidth;
650 points->coords[pi++] = 2;
652 points->coords[pi++] = 1;
653 points->coords[pi++] = 2;
655 /* connect the dots ... */
657 points->coords[pi++] = points->coords[0];
658 points->coords[pi] = points->coords[1];
660 fade_in_shape->set_property ("points", points);
661 gnome_canvas_points_unref (points);
665 AudioRegionView::reset_fade_out_shape ()
667 reset_fade_out_shape_width ((jack_nframes_t) region.fade_out().back()->when);
671 AudioRegionView::reset_fade_out_shape_width (jack_nframes_t width)
673 /* smallest size for a fade is 64 frames */
675 width = std::max ((jack_nframes_t) 64, width);
677 GnomeCanvasPoints* points;
678 double pwidth = width / samples_per_unit;
679 uint32_t npoints = std::min (gdk_screen_width(), (int) pwidth);
683 fade_out_shape->hide();
684 fade_out_handle->hide();
688 double handle_center;
689 handle_center = (region.length() - width) / samples_per_unit;
691 if (handle_center > 7.0) {
692 handle_center -= 3.0;
697 fade_out_handle->set_property ("x1", handle_center - 3.0);
698 fade_out_handle->set_property ("x2", handle_center + 3.0);
700 /* don't show shape if its too small */
703 fade_out_shape->hide();
707 fade_out_shape->show();
709 float curve[npoints];
710 region.fade_out().get_vector (0, region.fade_out().back()->when, curve, npoints);
712 if (_height > NAME_HIGHLIGHT_THRESH) {
713 h = _height - NAME_HIGHLIGHT_SIZE;
718 /* points *MUST* be in anti-clockwise order */
720 points = get_canvas_points ("fade out shape", npoints+3);
723 double xdelta = pwidth/npoints;
725 for (pi = 0, pc = 0; pc < npoints; ++pc) {
726 points->coords[pi++] = _pixel_width - 1 - pwidth + (pc*xdelta);
727 points->coords[pi++] = 2 + (h - (curve[pc] * h));
732 points->coords[pi++] = _pixel_width;
733 points->coords[pi++] = h;
735 points->coords[pi++] = _pixel_width;
736 points->coords[pi++] = 2;
738 /* connect the dots ... */
740 points->coords[pi++] = points->coords[0];
741 points->coords[pi] = points->coords[1];
743 fade_out_shape->set_property ("points", points);
744 gnome_canvas_points_unref (points);
748 AudioRegionView::set_samples_per_unit (gdouble spu)
750 TimeAxisViewItem::set_samples_per_unit (spu);
752 for (uint32_t n=0; n < waves.size(); ++n) {
753 gnome_canvas_item_set (waves[n], "samples_per_unit", spu, NULL);
756 for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
757 (*i)->set_samples_per_unit (spu);
758 (*i)->set_duration (region.length() / samples_per_unit);
762 reset_fade_shapes ();
763 region_sync_changed ();
767 AudioRegionView::set_duration (jack_nframes_t frames, void *src)
769 if (!TimeAxisViewItem::set_duration (frames, src)) {
773 for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
774 (*i)->set_duration (region.length() / samples_per_unit);
781 AudioRegionView::set_amplitude_above_axis (gdouble spp)
783 for (uint32_t n=0; n < waves.size(); ++n) {
784 gnome_canvas_item_set (waves[n], "amplitude_above_axis", spp, NULL);
789 AudioRegionView::compute_colors (Gdk::Color& basic_color)
791 TimeAxisViewItem::compute_colors (basic_color);
794 /* gain color computed in envelope_active_changed() */
796 UINT_TO_RGBA (fill_color, &r, &g, &b, &a);
797 fade_color = RGBA_TO_UINT(r,g,b,120);
801 AudioRegionView::set_colors ()
803 TimeAxisViewItem::set_colors ();
805 gain_line->set_line_color (region.envelope_active() ? color_map[cGainLine] : color_map[cGainLineInactive]);
806 sync_mark->set_property ("fill_color_rgba", fill_color);
808 for (uint32_t n=0; n < waves.size(); ++n) {
809 if (region.muted()) {
810 gnome_canvas_item_set (waves[n], "wave_color", color_map[cMutedWaveForm], NULL);
812 gnome_canvas_item_set (waves[n], "wave_color", color_map[cWaveForm], NULL);
818 AudioRegionView::set_frame_color ()
820 if (region.opaque()) {
826 TimeAxisViewItem::set_frame_color ();
830 AudioRegionView::show_region_editor ()
833 editor = new AudioRegionEditor (trackview.session(), region, *this);
834 // GTK2FIX : how to ensure float without realizing
835 // editor->realize ();
836 // trackview.editor.ensure_float (*editor);
840 editor->get_window()->raise();
844 AudioRegionView::hide_region_editor()
852 AudioRegionView::region_renamed ()
856 if (region.locked()) {
858 str += region.name();
864 if (region.muted()) {
865 str = string ("!") + str;
868 set_item_name (region.name(), this);
873 AudioRegionView::region_sync_changed ()
876 jack_nframes_t sync_offset;
878 sync_offset = region.sync_offset (sync_dir);
880 /* this has to handle both a genuine change of position, a change of samples_per_unit,
881 and a change in the bounds of the region.
884 if (sync_offset == 0) {
886 /* no sync mark - its the start of the region */
892 if ((sync_dir < 0) || ((sync_dir > 0) && (sync_offset > region.length()))) {
894 /* no sync mark - its out of the bounds of the region */
903 GnomeCanvasPoints* points;
905 args[0].name = X_("points");
907 sync_mark->get (X_("points"), &points);
909 double offset = sync_offset / samples_per_unit;
911 points->coords[0] = offset - ((sync_mark_width-1)/2);
912 points->coords[1] = 1;
914 points->coords[2] = offset + (sync_mark_width-1)/2;
915 points->coords[3] = 1;
917 points->coords[4] = offset;
918 points->coords[5] = sync_mark_width - 1;
920 points->coords[6] = offset - ((sync_mark_width-1)/2);
921 points->coords[7] = 1;
924 sync_mark->set_property ("points", points);
926 gnome_canvas_points_unref (points);
932 AudioRegionView::set_waveform_visible (bool yn)
934 if (((_flags & WaveformVisible) != yn)) {
936 for (uint32_t n=0; n < waves.size(); ++n) {
937 gnome_canvas_item_show (waves[n]);
939 _flags |= WaveformVisible;
941 for (uint32_t n=0; n < waves.size(); ++n) {
942 gnome_canvas_item_hide (waves[n]);
944 _flags &= ~WaveformVisible;
951 AudioRegionView::temporarily_hide_envelope ()
957 AudioRegionView::unhide_envelope ()
959 if (_flags & EnvelopeVisible) {
965 AudioRegionView::set_envelope_visible (bool yn)
967 if ((_flags & EnvelopeVisible) != yn) {
970 _flags |= EnvelopeVisible;
973 _flags &= ~EnvelopeVisible;
980 AudioRegionView::create_waves ()
982 bool create_zero_line = true;
984 AudioTimeAxisView& atv (*(dynamic_cast<AudioTimeAxisView*>(&trackview))); // ick
986 if (!atv.get_diskstream()) {
990 uint32_t nchans = atv.get_diskstream()->n_channels();
992 // if (wait_for_waves) {
993 /* in tmp_waves, set up null pointers for each channel so the vector is allocated */
994 for (uint32_t n = 0; n < nchans; ++n) {
995 tmp_waves.push_back (0);
999 for (uint32_t n = 0; n < nchans; ++n) {
1001 if (n >= region.n_channels()) {
1005 wave_caches.push_back (gnome_canvas_waveview_cache_new ());
1007 if (wait_for_waves) {
1008 if (region.source(n).peaks_ready (bind (mem_fun(*this, &AudioRegionView::peaks_ready_handler), n))) {
1009 create_one_wave (n, true);
1011 create_zero_line = false;
1014 create_one_wave (n, true);
1018 if (create_zero_line) {
1019 zero_line = new Gnome::Canvas::Line (*group);
1020 zero_line->set_property ("x1", (gdouble) 1.0);
1021 zero_line->set_property ("x2", (gdouble) (region.length() / samples_per_unit) - 1.0);
1022 zero_line->set_property ("color_rgba", (guint) color_map[cZeroLine]);
1023 manage_zero_line ();
1028 AudioRegionView::create_one_wave (uint32_t which, bool direct)
1030 AudioTimeAxisView& atv (*(dynamic_cast<AudioTimeAxisView*>(&trackview))); // ick
1031 uint32_t nchans = atv.get_diskstream()->n_channels();
1033 uint32_t nwaves = std::min (nchans, region.n_channels());
1036 if (trackview.height < NAME_HIGHLIGHT_SIZE) {
1037 ht = ((trackview.height) / (double) nchans);
1039 ht = ((trackview.height - NAME_HIGHLIGHT_SIZE) / (double) nchans);
1041 gdouble yoff = which * ht;
1043 GnomeCanvasItem *wave = gnome_canvas_item_new (GNOME_CANVAS_GROUP(group),
1044 gnome_canvas_waveview_get_type (),
1045 "data_src", (gpointer) ®ion,
1046 "cache", wave_caches[which],
1047 "cache_updater", (gboolean) true,
1048 "channel", (guint32) which,
1049 "length_function", (gpointer) region_length_from_c,
1050 "sourcefile_length_function",(gpointer) sourcefile_length_from_c,
1051 "peak_function", (gpointer) region_read_peaks_from_c,
1054 "height", (double) ht,
1055 "samples_per_unit", samples_per_unit,
1056 "amplitude_above_axis", _amplitude_above_axis,
1057 "wave_color", (guint32) (region.muted() ? color_map[cMutedWaveForm] : color_map[cWaveForm]),
1058 "region_start",(guint32) region.start(),
1061 if (!(_flags & WaveformVisible)) {
1062 gnome_canvas_item_hide (wave);
1065 /* note: calling this function is serialized by the lock
1066 held in the peak building thread that signals that
1067 peaks are ready for use *or* by the fact that it is
1068 called one by one from the GUI thread.
1071 if (which < nchans) {
1072 tmp_waves[which] = (wave);
1074 /* n-channel track, >n-channel source */
1077 /* see if we're all ready */
1079 for (n = 0; n < nchans; ++n) {
1080 if (tmp_waves[n] == 0) {
1086 /* all waves are ready */
1087 tmp_waves.resize(nwaves);
1092 zero_line = new Gnome::Canvas::Line (*group);
1093 zero_line->set_property ("x1", (gdouble) 1.0);
1094 zero_line->set_property ("x2", (gdouble) (region.length() / samples_per_unit) - 1.0);
1095 zero_line->set_property ("color_rgba", (guint) color_map[cZeroLine]);
1096 manage_zero_line ();
1102 AudioRegionView::peaks_ready_handler (uint32_t which)
1104 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &AudioRegionView::create_one_wave), which, false));
1108 AudioRegionView::add_gain_point_event (Gnome::Canvas::Item *item, GdkEvent *ev)
1112 /* don't create points that can't be seen */
1114 set_envelope_visible (true);
1121 jack_nframes_t fx = trackview.editor.pixel_to_frame (x);
1123 if (fx > region.length()) {
1127 /* compute vertical fractional position */
1129 y = 1.0 - (y / (trackview.height - NAME_HIGHLIGHT_SIZE));
1131 /* map using gain line */
1133 gain_line->view_to_model_y (y);
1135 trackview.session().begin_reversible_command (_("add gain control point"));
1136 trackview.session().add_undo (region.envelope().get_memento());
1139 if (!region.envelope_active()) {
1140 trackview.session().add_undo( bind( mem_fun(region, &AudioRegion::set_envelope_active), false) );
1141 region.set_envelope_active(true);
1142 trackview.session().add_redo( bind( mem_fun(region, &AudioRegion::set_envelope_active), true) );
1145 region.envelope().add (fx, y);
1147 trackview.session().add_redo_no_execute (region.envelope().get_memento());
1148 trackview.session().commit_reversible_command ();
1152 AudioRegionView::remove_gain_point_event (Gnome::Canvas::Item *item, GdkEvent *ev)
1154 ControlPoint *cp = reinterpret_cast<ControlPoint *> (item->get_data ("control_point"));
1155 region.envelope().erase (cp->model);
1159 AudioRegionView::store_flags()
1161 XMLNode *node = new XMLNode ("GUI");
1163 node->add_property ("waveform-visible", (_flags & WaveformVisible) ? "yes" : "no");
1164 node->add_property ("envelope-visible", (_flags & EnvelopeVisible) ? "yes" : "no");
1166 region.add_extra_xml (*node);
1170 AudioRegionView::set_flags (XMLNode* node)
1174 if ((prop = node->property ("waveform-visible")) != 0) {
1175 if (prop->value() == "yes") {
1176 _flags |= WaveformVisible;
1180 if ((prop = node->property ("envelope-visible")) != 0) {
1181 if (prop->value() == "yes") {
1182 _flags |= EnvelopeVisible;
1188 AudioRegionView::set_waveform_shape (WaveformShape shape)
1192 /* this slightly odd approach is to leave the door open to
1193 other "shapes" such as spectral displays, etc.
1206 if (yn != (bool) (_flags & WaveformRectified)) {
1207 for (vector<GnomeCanvasItem *>::iterator wave = waves.begin(); wave != waves.end() ; ++wave) {
1208 gnome_canvas_item_set ((*wave), "rectified", (gboolean) yn, NULL);
1220 _flags |= WaveformRectified;
1222 _flags &= ~WaveformRectified;
1228 AudioRegionView::get_item_name ()
1230 return region.name();
1234 AudioRegionView::move (double x_delta, double y_delta)
1236 if (region.locked() || (x_delta == 0 && y_delta == 0)) {
1240 get_canvas_group()->move (x_delta, y_delta);
1242 /* note: ghosts never leave their tracks so y_delta for them is always zero */
1244 for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
1245 (*i)->group->move (x_delta, 0.0);
1250 AudioRegionView::add_ghost (AutomationTimeAxisView& atv)
1252 AudioTimeAxisView& myatv (*(dynamic_cast<AudioTimeAxisView*>(&trackview))); // ick
1253 double unit_position = region.position () / samples_per_unit;
1254 GhostRegion* ghost = new GhostRegion (atv, unit_position);
1257 nchans = myatv.get_diskstream()->n_channels();
1259 for (uint32_t n = 0; n < nchans; ++n) {
1261 if (n >= region.n_channels()) {
1265 GnomeCanvasItem *wave = gnome_canvas_item_new (GNOME_CANVAS_GROUP(ghost->group),
1266 gnome_canvas_waveview_get_type (),
1267 "data_src", (gpointer) ®ion,
1268 "cache", wave_caches[n],
1269 "cache_updater", (gboolean) false,
1270 "channel", (guint32) n,
1271 "length_function", (gpointer) region_length_from_c,
1272 "sourcefile_length_function",(gpointer) sourcefile_length_from_c,
1273 "peak_function", (gpointer) region_read_peaks_from_c,
1275 "samples_per_unit", samples_per_unit,
1276 "amplitude_above_axis", _amplitude_above_axis,
1277 "wave_color", color_map[cGhostTrackWave],
1278 "region_start", (guint32) region.start(),
1282 ghost->waves.push_back(wave);
1285 ghost->set_height ();
1286 ghost->set_duration (region.length() / samples_per_unit);
1287 ghosts.push_back (ghost);
1289 ghost->GoingAway.connect (mem_fun(*this, &AudioRegionView::remove_ghost));
1295 AudioRegionView::remove_ghost (GhostRegion* ghost)
1297 if (in_destructor) {
1301 for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
1310 AudioRegionView::get_fill_color ()
1316 AudioRegionView::entered ()
1318 if (_flags & EnvelopeVisible) {
1319 gain_line->show_all_control_points ();
1323 UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
1326 fade_in_handle->set_property ("fill_color_rgba", RGBA_TO_UINT(r,g,b,a));
1327 fade_out_handle->set_property ("fill_color_rgba", RGBA_TO_UINT(r,g,b,a));
1331 AudioRegionView::exited ()
1333 gain_line->hide_all_but_selected_control_points ();
1336 UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
1339 fade_in_handle->set_property ("fill_color_rgba", RGBA_TO_UINT(r,g,b,a));
1340 fade_out_handle->set_property ("fill_color_rgba", RGBA_TO_UINT(r,g,b,a));
1344 AudioRegionView::envelope_active_changed ()
1346 gain_line->set_line_color (region.envelope_active() ? color_map[cGainLine] : color_map[cGainLineInactive]);
1350 AudioRegionView::set_waveview_data_src()
1353 double unit_length= region.length() / samples_per_unit;
1355 for (uint32_t n = 0; n < waves.size(); ++n) {
1356 // TODO: something else to let it know the channel
1357 gnome_canvas_item_set (waves[n], "data_src", ®ion, NULL);
1360 for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
1362 (*i)->set_duration (unit_length);
1364 for (vector<GnomeCanvasItem*>::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) {
1365 gnome_canvas_item_set ((*w), "data_src", ®ion, NULL);