2 Copyright (C) 2004 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.
23 #include <sigc++/bind.h>
25 #include <gtkmm/frame.h>
26 #include <gtkmm/image.h>
27 #include <gtkmm/scrolledwindow.h>
29 #include <libgnomecanvasmm/line.h>
31 #include <ardour/automation_event.h>
32 #include <ardour/curve.h>
33 #include <ardour/crossfade.h>
34 #include <ardour/session.h>
35 #include <ardour/auditioner.h>
36 #include <ardour/audioplaylist.h>
37 #include <ardour/playlist_templates.h>
39 #include <gtkmm2ext/gtk_ui.h>
41 #include "ardour_ui.h"
42 #include "crossfade_edit.h"
43 #include "rgb_macros.h"
46 #include "gui_thread.h"
47 #include "canvas_impl.h"
48 #include "simplerect.h"
52 using namespace ARDOUR;
55 using namespace Editing;
59 const int32_t CrossfadeEditor::Point::size = 7;
60 const double CrossfadeEditor::canvas_border = 10;
61 CrossfadeEditor::Presets* CrossfadeEditor::fade_in_presets = 0;
62 CrossfadeEditor::Presets* CrossfadeEditor::fade_out_presets = 0;
64 #include "crossfade_xpms.h"
66 CrossfadeEditor::Half::Half ()
68 normative_curve (0.0, 1.0, 1.0, true),
69 gain_curve (0.0, 2.0, 1.0, true)
73 CrossfadeEditor::CrossfadeEditor (Session& s, Crossfade& xf, double my, double mxy)
74 : ArdourDialog (_("crossfade editor")),
75 cancel_button (_("Cancel")),
79 clear_button (_("Clear")),
80 revert_button (_("Reset")),
81 audition_both_button (_("Fade")),
82 audition_left_dry_button (_("Out (dry)")),
83 audition_left_button (_("Out")),
84 audition_right_dry_button (_("In (dry)")),
85 audition_right_button (_("In")),
87 preroll_button (_("With Pre-roll")),
88 postroll_button (_("With Post-roll")),
94 fade_out_table (3, 3),
96 select_in_button (_("Fade In")),
97 select_out_button (_("Fade Out"))
99 set_wmclass ("ardour_automationedit", "Ardour");
100 set_name ("CrossfadeEditWindow");
101 set_title (_("ardour: x-fade edit"));
102 set_position (Gtk::WIN_POS_MOUSE);
105 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
107 RadioButtonGroup sel_but_group = select_in_button.get_group();
108 select_out_button.set_group (sel_but_group);
109 select_out_button.set_mode (false);
110 select_in_button.set_mode (false);
112 if (fade_in_presets == 0) {
116 point_grabbed = false;
119 canvas = new ArdourCanvas::CanvasAA ();
120 canvas->signal_size_allocate().connect (mem_fun(*this, &CrossfadeEditor::canvas_allocation));
121 canvas->set_size_request (425, 200);
123 toplevel = new ArdourCanvas::SimpleRect (*(canvas->root()));
124 toplevel->property_x1() = 0.0;
125 toplevel->property_y1() = 0.0;
126 toplevel->property_x2() = 10.0;
127 toplevel->property_y2() = 10.0;
128 toplevel->property_fill() = true;
129 toplevel->property_fill_color_rgba() = (guint32) color_map[cCrossfadeEditorBase];
130 toplevel->property_outline_pixels() = 0;
131 toplevel->signal_event().connect (mem_fun (*this, &CrossfadeEditor::canvas_event));
133 fade[Out].line = new ArdourCanvas::Line (*(canvas->root()));
134 fade[Out].line->property_width_pixels() = 1;
135 fade[Out].line->property_fill_color_rgba() = color_map[cCrossfadeEditorLine];
137 fade[Out].shading = new ArdourCanvas::Polygon (*(canvas->root()));
138 fade[Out].shading->property_fill_color_rgba() = color_map[cCrossfadeEditorLineShading];
140 fade[In].line = new ArdourCanvas::Line (*(canvas->root()));
141 fade[In].line->property_width_pixels() = 1;
142 fade[In].line->property_fill_color_rgba() = color_map[cCrossfadeEditorLine];
144 fade[In].shading = new ArdourCanvas::Polygon (*(canvas->root()));
145 fade[In].shading->property_fill_color_rgba() = color_map[cCrossfadeEditorLineShading];
147 fade[In].shading->signal_event().connect (mem_fun (*this, &CrossfadeEditor::canvas_event));
148 fade[In].line->signal_event().connect (mem_fun (*this, &CrossfadeEditor::curve_event));
149 fade[Out].shading->signal_event().connect (mem_fun (*this, &CrossfadeEditor::canvas_event));
150 fade[Out].line->signal_event().connect (mem_fun (*this, &CrossfadeEditor::curve_event));
152 select_in_button.set_name (X_("CrossfadeEditCurveButton"));
153 select_out_button.set_name (X_("CrossfadeEditCurveButton"));
155 select_in_button.signal_clicked().connect (bind (mem_fun (*this, &CrossfadeEditor::curve_select_clicked), In));
156 select_out_button.signal_clicked().connect (bind (mem_fun (*this, &CrossfadeEditor::curve_select_clicked), Out));
158 HBox* acbox = manage (new HBox);
160 audition_box.set_border_width (7);
161 audition_box.set_spacing (5);
162 audition_box.set_homogeneous (false);
163 audition_box.pack_start (audition_left_dry_button, false, false);
164 audition_box.pack_start (audition_left_button, false, false);
165 audition_box.pack_start (audition_both_button, false, false);
166 audition_box.pack_start (audition_right_button, false, false);
167 audition_box.pack_start (audition_right_dry_button, false, false);
169 Frame* audition_frame = manage (new Frame (_("Audition")));
171 audition_frame->set_name (X_("CrossfadeEditFrame"));
172 audition_frame->add (audition_box);
174 acbox->pack_start (*audition_frame, true, false);
176 Frame* canvas_frame = manage (new Frame);
177 canvas_frame->add (*canvas);
178 canvas_frame->set_shadow_type (Gtk::SHADOW_IN);
180 fade_in_table.attach (select_in_button, 0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND);
181 fade_out_table.attach (select_out_button, 0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND);
191 for (list<Preset*>::iterator i = fade_in_presets->begin(); i != fade_in_presets->end(); ++i) {
193 pxmap = manage (new Image (Gdk::Pixbuf::create_from_xpm_data((*i)->xpm)));
194 pbutton = manage (new Button);
195 pbutton->add (*pxmap);
196 pbutton->set_name ("CrossfadeEditButton");
197 pbutton->signal_clicked().connect (bind (mem_fun(*this, &CrossfadeEditor::apply_preset), *i));
198 fade_in_table.attach (*pbutton, col, col+1, row, row+1);
199 fade_in_buttons.push_back (pbutton);
212 for (list<Preset*>::iterator i = fade_out_presets->begin(); i != fade_out_presets->end(); ++i) {
214 pxmap = manage (new Image (Gdk::Pixbuf::create_from_xpm_data((*i)->xpm)));
215 pbutton = manage (new Button);
216 pbutton->add (*pxmap);
217 pbutton->set_name ("CrossfadeEditButton");
218 pbutton->signal_clicked().connect (bind (mem_fun(*this, &CrossfadeEditor::apply_preset), *i));
219 fade_out_table.attach (*pbutton, col, col+1, row, row+1);
220 fade_out_buttons.push_back (pbutton);
230 clear_button.set_name ("CrossfadeEditButton");
231 revert_button.set_name ("CrossfadeEditButton");
232 ok_button.set_name ("CrossfadeEditButton");
233 cancel_button.set_name ("CrossfadeEditButton");
234 preroll_button.set_name ("CrossfadeEditButton");
235 postroll_button.set_name ("CrossfadeEditButton");
236 audition_both_button.set_name ("CrossfadeEditAuditionButton");
237 audition_left_dry_button.set_name ("CrossfadeEditAuditionButton");
238 audition_left_button.set_name ("CrossfadeEditAuditionButton");
239 audition_right_dry_button.set_name ("CrossfadeEditAuditionButton");
240 audition_right_button.set_name ("CrossfadeEditAuditionButton");
242 clear_button.signal_clicked().connect (mem_fun(*this, &CrossfadeEditor::clear));
243 revert_button.signal_clicked().connect (mem_fun(*this, &CrossfadeEditor::reset));
244 audition_both_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_toggled));
245 audition_right_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_right_toggled));
246 audition_right_dry_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_right_dry_toggled));
247 audition_left_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_left_toggled));
248 audition_left_dry_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_left_dry_toggled));
250 action_box.set_border_width (7);
251 action_box.set_spacing (5);
252 action_box.set_homogeneous (false);
253 action_box.pack_end (cancel_button, false, false);
254 action_box.pack_end (ok_button, false, false);
255 action_box.pack_end (revert_button, false, false);
256 action_box.pack_end (clear_button, false, false);
258 Frame* edit_frame = manage (new Frame (_("Edit")));
259 edit_frame->set_name (X_("CrossfadeEditFrame"));
260 edit_frame->add (action_box);
262 Gtk::HBox* action_center_box = manage (new HBox);
263 action_center_box->pack_start (*edit_frame, true, false);
265 roll_box.pack_start (preroll_button, false, false);
266 roll_box.pack_start (postroll_button, false, false);
268 Gtk::HBox* rcenter_box = manage (new HBox);
269 rcenter_box->pack_start (roll_box, true, false);
271 VBox* vpacker2 = manage (new (VBox));
273 vpacker2->set_border_width (12);
274 vpacker2->set_spacing (7);
275 vpacker2->pack_start (*acbox, false, false);
276 vpacker2->pack_start (*rcenter_box, false, false);
277 vpacker2->pack_start (*action_center_box, false, false);
279 curve_button_box.set_spacing (7);
280 curve_button_box.pack_start (fade_out_table, false, false, 12);
281 curve_button_box.pack_start (*vpacker2, false, false, 12);
282 curve_button_box.pack_start (fade_in_table, false, false, 12);
284 vpacker.set_border_width (12);
285 vpacker.set_spacing (5);
286 vpacker.pack_start (*canvas_frame, true, true);
287 vpacker.pack_start (curve_button_box, false, false);
289 /* button to allow hackers to check the actual curve values */
291 // Button* foobut = manage (new Button ("dump"));
292 // foobut-.signal_clicked().connect (mem_fun(*this, &CrossfadeEditor::dump));
293 // vpacker.pack_start (*foobut, false, false);
296 set (xfade.fade_in(), In);
299 set (xfade.fade_out(), Out);
301 curve_select_clicked (In);
303 xfade.StateChanged.connect (mem_fun(*this, &CrossfadeEditor::xfade_changed));
305 session.AuditionActive.connect (mem_fun(*this, &CrossfadeEditor::audition_state_changed));
308 CrossfadeEditor::~CrossfadeEditor()
310 /* most objects will be destroyed when the toplevel window is. */
312 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
316 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
322 CrossfadeEditor::dump ()
324 for (AutomationList::iterator i = fade[Out].normative_curve.begin(); i != fade[Out].normative_curve.end(); ++i) {
325 cerr << (*i)->when << ' ' << (*i)->value << endl;
330 CrossfadeEditor::audition_state_changed (bool yn)
332 ENSURE_GUI_THREAD (bind (mem_fun(*this, &CrossfadeEditor::audition_state_changed), yn));
335 audition_both_button.set_active (false);
336 audition_left_button.set_active (false);
337 audition_right_button.set_active (false);
338 audition_left_dry_button.set_active (false);
339 audition_right_dry_button.set_active (false);
344 CrossfadeEditor::set (const ARDOUR::Curve& curve, WhichFade which)
347 ARDOUR::Curve::const_iterator the_end;
349 for (list<Point*>::iterator i = fade[which].points.begin(); i != fade[which].points.end(); ++i) {
353 fade[which].points.clear ();
354 fade[which].gain_curve.clear ();
355 fade[which].normative_curve.clear ();
361 the_end = curve.const_end();
364 firstx = (*curve.const_begin())->when;
365 endx = (*the_end)->when;
367 for (ARDOUR::Curve::const_iterator i = curve.const_begin(); i != curve.const_end(); ++i) {
369 double xfract = ((*i)->when - firstx) / (endx - firstx);
370 double yfract = ((*i)->value - miny) / (maxy - miny);
372 Point* p = make_point ();
374 p->move_to (x_coordinate (xfract), y_coordinate (yfract),
377 fade[which].points.push_back (p);
380 /* no need to sort because curve is already time-ordered */
384 swap (which, current);
386 swap (which, current);
390 CrossfadeEditor::curve_event (GdkEvent* event)
392 /* treat it like a toplevel event */
394 return canvas_event (event);
398 CrossfadeEditor::point_event (GdkEvent* event, Point* point)
401 if (point->curve != fade[current].line) {
405 switch (event->type) {
406 case GDK_BUTTON_PRESS:
407 point_grabbed = true;
409 case GDK_BUTTON_RELEASE:
410 point_grabbed = false;
412 if (Keyboard::is_delete_event (&event->button)) {
413 fade[current].points.remove (point);
420 case GDK_MOTION_NOTIFY:
424 /* can't drag first or last points horizontally */
426 if (point == fade[current].points.front() || point == fade[current].points.back()) {
429 new_x = (event->motion.x - canvas_border)/effective_width();
432 new_y = 1.0 - ((event->motion.y - canvas_border)/effective_height());
433 point->move_to (x_coordinate (new_x), y_coordinate (new_y),
445 CrossfadeEditor::canvas_event (GdkEvent* event)
447 switch (event->type) {
448 case GDK_BUTTON_PRESS:
449 add_control_point ((event->button.x - canvas_border)/effective_width(),
450 1.0 - ((event->button.y - canvas_border)/effective_height()));
459 CrossfadeEditor::Point::~Point()
461 gtk_object_destroy (GTK_OBJECT(box));
464 CrossfadeEditor::Point*
465 CrossfadeEditor::make_point ()
467 Point* p = new Point;
469 p->box = new ArdourCanvas::SimpleRect (*(canvas->root()));
470 p->box->property_fill() = true;
471 p->box->property_fill_color_rgba() = color_map[cCrossfadeEditorPointFill];
472 p->box->property_outline_color_rgba() = color_map[cCrossfadeEditorPointOutline];
473 p->box->property_outline_pixels() = 1;
475 p->curve = fade[current].line;
477 p->box->signal_event().connect (bind (mem_fun (*this, &CrossfadeEditor::point_event), p));
483 CrossfadeEditor::add_control_point (double x, double y)
487 /* enforce end point x location */
489 if (fade[current].points.empty()) {
491 } else if (fade[current].points.size() == 1) {
495 Point* p = make_point ();
497 p->move_to (x_coordinate (x), y_coordinate (y), x, y);
499 fade[current].points.push_back (p);
500 fade[current].points.sort (cmp);
506 CrossfadeEditor::Point::move_to (double nx, double ny, double xfract, double yfract)
508 const double half_size = rint(size/2.0);
509 double x1 = nx - half_size;
510 double x2 = nx + half_size;
512 box->property_x1() = x1;
513 box->property_x2() = x2;
515 box->property_y1() = ny - half_size;
516 box->property_y2() = ny + half_size;
523 CrossfadeEditor::canvas_allocation (Gtk::Allocation& alloc)
526 toplevel->property_x1() = 0.0;
527 toplevel->property_y1() = 0.0;
528 toplevel->property_x2() = (double) canvas->get_allocation().get_width() + canvas_border;
529 toplevel->property_y2() = (double) canvas->get_allocation().get_height() + canvas_border;
532 canvas->set_scroll_region (0.0, 0.0,
533 canvas->get_allocation().get_width(),
534 canvas->get_allocation().get_height());
536 Point* end = make_point ();
539 if (fade[In].points.size() > 1) {
540 Point* old_end = fade[In].points.back();
541 fade[In].points.pop_back ();
542 end->move_to (x_coordinate (old_end->x),
543 y_coordinate (old_end->y),
544 old_end->x, old_end->y);
549 end->move_to (x_coordinate (x), y_coordinate (y), x, y);
553 fade[In].points.push_back (end);
554 fade[In].points.sort (cmp);
556 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
557 (*i)->move_to (x_coordinate((*i)->x), y_coordinate((*i)->y),
563 if (fade[Out].points.size() > 1) {
564 Point* old_end = fade[Out].points.back();
565 fade[Out].points.pop_back ();
566 end->move_to (x_coordinate (old_end->x),
567 y_coordinate (old_end->y),
568 old_end->x, old_end->y);
573 end->move_to (x_coordinate (x), y_coordinate (y), x, y);
577 fade[Out].points.push_back (end);
578 fade[Out].points.sort (cmp);
580 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
581 (*i)->move_to (x_coordinate ((*i)->x),
582 y_coordinate ((*i)->y),
586 WhichFade old_current = current;
591 current = old_current;
593 double spu = xfade.length() / (double) effective_width();
595 if (fade[In].waves.empty()) {
596 make_waves (xfade.in(), In);
599 if (fade[Out].waves.empty()) {
600 make_waves (xfade.out(), Out);
604 vector<ArdourCanvas::WaveView*>::iterator i;
607 ht = canvas->get_allocation().get_height() / xfade.in().n_channels();
609 for (n = 0, i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i, ++n) {
614 (*i)->property_y() = yoff;
615 (*i)->property_height() = ht;
616 (*i)->property_samples_per_unit() = spu;
619 ht = canvas->get_allocation().get_height() / xfade.out().n_channels();
621 for (n = 0, i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i, ++n) {
626 (*i)->property_y() = yoff;
627 (*i)->property_height() = ht;
628 (*i)->property_samples_per_unit() = spu;
635 CrossfadeEditor::xfade_changed (Change ignored)
637 set (xfade.fade_in(), In);
638 set (xfade.fade_out(), Out);
642 CrossfadeEditor::redraw ()
644 if (canvas->get_allocation().get_width() < 2) {
648 jack_nframes_t len = xfade.length ();
650 fade[current].normative_curve.clear ();
651 fade[current].gain_curve.clear ();
653 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
654 fade[current].normative_curve.add ((*i)->x, (*i)->y);
655 fade[current].gain_curve.add (((*i)->x * len), (*i)->y);
658 size_t npoints = (size_t) effective_width();
661 fade[current].normative_curve.get_vector (0, 1.0, vec, npoints);
663 Gnome::Canvas::Points pts;
664 Gnome::Canvas::Points spts;
666 while (pts.size() < npoints) {
667 pts.push_back (Gnome::Art::Point (0,0));
670 while (spts.size() < npoints + 3) {
671 spts.push_back (Gnome::Art::Point (0,0));
674 /* the shade coordinates *MUST* be in anti-clockwise order.
681 spts[0].set_x (canvas_border);
682 spts[0].set_y (effective_height() + canvas_border);
686 spts[1].set_x (effective_width() + canvas_border);
687 spts[1].set_y (effective_height() + canvas_border);
691 spts[2].set_x (effective_width() + canvas_border);
692 spts[2].set_y (canvas_border);
699 spts[0].set_x (canvas_border);
700 spts[0].set_y (canvas_border);
704 spts[1].set_x (canvas_border);
705 spts[1].set_y (effective_height() + canvas_border);
709 spts[2].set_x (effective_width() + canvas_border);
710 spts[2].set_y (effective_height() + canvas_border);
714 // GTK2FIX some odd math to fix up here
716 size_t last_spt = (npoints + 3) - 1;
718 for (size_t i = 0; i < npoints; ++i) {
722 pts[i].set_x (canvas_border + i);
723 pts[i].set_y (y_coordinate (y));
725 spts[last_spt - i].set_x (canvas_border + i);
726 spts[last_spt - i].set_y (pts[i].get_y());
729 fade[current].line->property_points() = pts;
730 fade[current].shading->property_points() = spts;
732 for (vector<Gnome::Canvas::WaveView*>::iterator i = fade[current].waves.begin(); i != fade[current].waves.end(); ++i) {
733 (*i)->property_gain_src() = &fade[current].gain_curve;
738 CrossfadeEditor::apply_preset (Preset *preset)
740 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
744 fade[current].points.clear ();
746 for (Preset::iterator i = preset->begin(); i != preset->end(); ++i) {
747 Point* p = make_point ();
748 p->move_to (x_coordinate ((*i).x), y_coordinate ((*i).y),
750 fade[current].points.push_back (p);
757 CrossfadeEditor::apply ()
763 CrossfadeEditor::_apply_to (Crossfade* xf)
765 ARDOUR::Curve& in (xf->fade_in());
766 ARDOUR::Curve& out (xf->fade_out());
771 ARDOUR::Curve::const_iterator the_end = in.const_end();
774 double firstx = (*in.begin())->when;
775 double endx = (*the_end)->when;
776 double miny = in.get_min_y ();
777 double maxy = in.get_max_y ();
782 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
784 double when = firstx + ((*i)->x * (endx - firstx));
785 double value = (*i)->y; // miny + ((*i)->y * (maxy - miny));
786 in.add (when, value);
791 the_end = out.const_end();
794 firstx = (*out.begin())->when;
795 endx = (*the_end)->when;
796 miny = out.get_min_y ();
797 maxy = out.get_max_y ();
802 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
804 double when = firstx + ((*i)->x * (endx - firstx));
805 double value = (*i)->y; // miny + ((*i)->y * (maxy - miny));
806 out.add (when, value);
814 CrossfadeEditor::setup (Crossfade* xfade)
817 xfade->set_active (true);
818 xfade->fade_in().solve ();
819 xfade->fade_out().solve ();
823 CrossfadeEditor::clear ()
825 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
829 fade[current].points.clear ();
835 CrossfadeEditor::reset ()
837 set (xfade.fade_in(), In);
838 set (xfade.fade_out(), Out);
842 CrossfadeEditor::build_presets ()
846 fade_in_presets = new Presets;
847 fade_out_presets = new Presets;
851 p = new Preset (hiin_xpm);
852 p->push_back (PresetPoint (0, 0));
853 p->push_back (PresetPoint (0.0207373, 0.197222));
854 p->push_back (PresetPoint (0.0645161, 0.525));
855 p->push_back (PresetPoint (0.152074, 0.802778));
856 p->push_back (PresetPoint (0.276498, 0.919444));
857 p->push_back (PresetPoint (0.481567, 0.980556));
858 p->push_back (PresetPoint (0.767281, 1));
859 p->push_back (PresetPoint (1, 1));
860 fade_in_presets->push_back (p);
862 p = new Preset (loin_xpm);
863 p->push_back (PresetPoint (0, 0));
864 p->push_back (PresetPoint (0.389401, 0.0333333));
865 p->push_back (PresetPoint (0.629032, 0.0861111));
866 p->push_back (PresetPoint (0.829493, 0.233333));
867 p->push_back (PresetPoint (0.9447, 0.483333));
868 p->push_back (PresetPoint (0.976959, 0.697222));
869 p->push_back (PresetPoint (1, 1));
870 fade_in_presets->push_back (p);
872 p = new Preset (regin_xpm);
873 p->push_back (PresetPoint (0, 0));
874 p->push_back (PresetPoint (0.0737327, 0.308333));
875 p->push_back (PresetPoint (0.246544, 0.658333));
876 p->push_back (PresetPoint (0.470046, 0.886111));
877 p->push_back (PresetPoint (0.652074, 0.972222));
878 p->push_back (PresetPoint (0.771889, 0.988889));
879 p->push_back (PresetPoint (1, 1));
880 fade_in_presets->push_back (p);
882 p = new Preset (regin2_xpm);
883 p->push_back (PresetPoint (0, 0));
884 p->push_back (PresetPoint (0.304147, 0.0694444));
885 p->push_back (PresetPoint (0.529954, 0.152778));
886 p->push_back (PresetPoint (0.725806, 0.333333));
887 p->push_back (PresetPoint (0.847926, 0.558333));
888 p->push_back (PresetPoint (0.919355, 0.730556));
889 p->push_back (PresetPoint (1, 1));
890 fade_in_presets->push_back (p);
892 p = new Preset (linin_xpm);
893 p->push_back (PresetPoint (0, 0));
894 p->push_back (PresetPoint (1, 1));
895 fade_in_presets->push_back (p);
899 p = new Preset (hiout_xpm);
900 p->push_back (PresetPoint (0, 1));
901 p->push_back (PresetPoint (0.305556, 1));
902 p->push_back (PresetPoint (0.548611, 0.991736));
903 p->push_back (PresetPoint (0.759259, 0.931129));
904 p->push_back (PresetPoint (0.918981, 0.68595));
905 p->push_back (PresetPoint (0.976852, 0.22865));
906 p->push_back (PresetPoint (1, 0));
907 fade_out_presets->push_back (p);
909 p = new Preset (regout_xpm);
910 p->push_back (PresetPoint (0, 1));
911 p->push_back (PresetPoint (0.228111, 0.988889));
912 p->push_back (PresetPoint (0.347926, 0.972222));
913 p->push_back (PresetPoint (0.529954, 0.886111));
914 p->push_back (PresetPoint (0.753456, 0.658333));
915 p->push_back (PresetPoint (0.9262673, 0.308333));
916 p->push_back (PresetPoint (1, 0));
917 fade_out_presets->push_back (p);
919 p = new Preset (loout_xpm);
920 p->push_back (PresetPoint (0, 1));
921 p->push_back (PresetPoint (0.023041, 0.697222));
922 p->push_back (PresetPoint (0.0553, 0.483333));
923 p->push_back (PresetPoint (0.170507, 0.233333));
924 p->push_back (PresetPoint (0.370968, 0.0861111));
925 p->push_back (PresetPoint (0.610599, 0.0333333));
926 p->push_back (PresetPoint (1, 0));
927 fade_out_presets->push_back (p);
929 p = new Preset (regout2_xpm);
930 p->push_back (PresetPoint (0, 1));
931 p->push_back (PresetPoint (0.080645, 0.730556));
932 p->push_back (PresetPoint (0.277778, 0.289256));
933 p->push_back (PresetPoint (0.470046, 0.152778));
934 p->push_back (PresetPoint (0.695853, 0.0694444));
935 p->push_back (PresetPoint (1, 0));
936 fade_out_presets->push_back (p);
938 p = new Preset (linout_xpm);
939 p->push_back (PresetPoint (0, 1));
940 p->push_back (PresetPoint (1, 0));
941 fade_out_presets->push_back (p);
945 CrossfadeEditor::curve_select_clicked (WhichFade wf)
951 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) {
952 (*i)->property_wave_color() = color_map[cSelectedCrossfadeEditorWave];
955 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) {
956 (*i)->property_wave_color() = color_map[cCrossfadeEditorWave];
959 fade[In].line->property_fill_color_rgba() = color_map[cSelectedCrossfadeEditorLine];
960 fade[Out].line->property_fill_color_rgba() = color_map[cCrossfadeEditorLine];
961 fade[Out].shading->hide();
962 fade[In].shading->show();
964 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
968 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
972 for (vector<Button*>::iterator i = fade_out_buttons.begin(); i != fade_out_buttons.end(); ++i) {
973 (*i)->set_sensitive (false);
976 for (vector<Button*>::iterator i = fade_in_buttons.begin(); i != fade_in_buttons.end(); ++i) {
977 (*i)->set_sensitive (true);
982 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) {
983 (*i)->property_wave_color() = color_map[cCrossfadeEditorWave];
986 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) {
987 (*i)->property_wave_color() = color_map[cSelectedCrossfadeEditorWave];
990 fade[Out].line->property_fill_color_rgba() = color_map[cSelectedCrossfadeEditorLine];
991 fade[In].line->property_fill_color_rgba() = color_map[cCrossfadeEditorLine];
992 fade[In].shading->hide();
993 fade[Out].shading->show();
995 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
999 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
1003 for (vector<Button*>::iterator i = fade_out_buttons.begin(); i != fade_out_buttons.end(); ++i) {
1004 (*i)->set_sensitive (true);
1007 for (vector<Button*>::iterator i = fade_in_buttons.begin(); i != fade_in_buttons.end(); ++i) {
1008 (*i)->set_sensitive (false);
1015 CrossfadeEditor::x_coordinate (double& xfract) const
1017 xfract = min (1.0, xfract);
1018 xfract = max (0.0, xfract);
1020 return canvas_border + (xfract * effective_width());
1024 CrossfadeEditor::y_coordinate (double& yfract) const
1026 yfract = min (1.0, yfract);
1027 yfract = max (0.0, yfract);
1029 return (canvas->get_allocation().get_height() - (canvas_border)) - (yfract * effective_height());
1033 CrossfadeEditor::make_waves (AudioRegion& region, WhichFade which)
1036 uint32_t nchans = region.n_channels();
1041 color = color_map[cSelectedCrossfadeEditorWave];
1043 color = color_map[cCrossfadeEditorWave];
1046 ht = canvas->get_allocation().get_height() / (double) nchans;
1047 spu = xfade.length() / (double) effective_width();
1049 for (uint32_t n = 0; n < nchans; ++n) {
1051 gdouble yoff = n * ht;
1053 if (region.source(n).peaks_ready (bind (mem_fun(*this, &CrossfadeEditor::peaks_ready), ®ion, which))) {
1055 WaveView* waveview = new WaveView (*(canvas->root()));
1057 waveview->property_data_src() = ®ion;
1058 waveview->property_cache_updater() = true;
1059 waveview->property_cache() = WaveView::create_cache();
1060 waveview->property_channel() = n;
1061 waveview->property_length_function() = (void*) region_length_from_c;
1062 waveview->property_sourcefile_length_function() = (void*) sourcefile_length_from_c;
1063 waveview->property_peak_function() = (void*) region_read_peaks_from_c;
1064 waveview->property_gain_function() = (void*) curve_get_vector_from_c;
1065 waveview->property_gain_src() = &fade[which].gain_curve;
1066 waveview->property_x() = canvas_border;
1067 waveview->property_y() = yoff;
1068 waveview->property_height() = ht;
1069 waveview->property_samples_per_unit() = spu;
1070 waveview->property_amplitude_above_axis() = 2.0;
1071 waveview->property_wave_color() = color;
1073 waveview->lower_to_bottom();
1074 fade[which].waves.push_back (waveview);
1078 toplevel->lower_to_bottom();
1082 CrossfadeEditor::peaks_ready (AudioRegion* r, WhichFade which)
1084 /* this should never be called, because the peak files for an xfade
1085 will be ready by the time we want them. but our API forces us
1086 to provide this, so ..
1089 make_waves (*r, which);
1093 CrossfadeEditor::audition_both ()
1095 AudioPlaylist& pl (session.the_auditioner().prepare_playlist());
1096 jack_nframes_t preroll;
1097 jack_nframes_t postroll;
1098 jack_nframes_t length;
1099 jack_nframes_t left_start_offset;
1100 jack_nframes_t right_length;
1101 jack_nframes_t left_length;
1103 if (preroll_button.get_active()) {
1104 preroll = ARDOUR_UI::instance()->preroll_clock.current_duration ();
1109 if (postroll_button.get_active()) {
1110 postroll = ARDOUR_UI::instance()->postroll_clock.current_duration ();
1115 if ((left_start_offset = xfade.out().length() - xfade.length()) >= preroll) {
1116 left_start_offset -= preroll;
1121 if ((left_length = xfade.length()) < xfade.out().length() - left_start_offset) {
1125 right_length = xfade.length();
1127 if (xfade.in().length() - right_length < postroll) {
1128 right_length += postroll;
1131 AudioRegion* left = new AudioRegion (xfade.out(), left_start_offset, left_length, "xfade out",
1132 0, Region::DefaultFlags, false);
1133 AudioRegion* right = new AudioRegion (xfade.in(), 0, right_length, "xfade in",
1134 0, Region::DefaultFlags, false);
1136 pl.add_region (*left, 0);
1137 pl.add_region (*right, 1+preroll);
1139 /* there is only one ... */
1141 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1143 session.audition_playlist ();
1147 CrossfadeEditor::audition_left_dry ()
1149 AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade left",
1150 0, Region::DefaultFlags, false);
1152 session.audition_region (*left);
1156 CrossfadeEditor::audition_left ()
1158 AudioPlaylist& pl (session.the_auditioner().prepare_playlist());
1160 AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade left",
1161 0, Region::DefaultFlags, false);
1162 AudioRegion* right = new AudioRegion (xfade.in(), 0, xfade.length(), "xfade in",
1163 0, Region::DefaultFlags, false);
1165 pl.add_region (*left, 0);
1166 pl.add_region (*right, 1);
1168 right->set_muted (true);
1170 /* there is only one ... */
1172 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1174 session.audition_playlist ();
1176 /* memory leak for regions */
1180 CrossfadeEditor::audition_right_dry ()
1182 AudioRegion* right = new AudioRegion (xfade.in(), 0, xfade.length(), "xfade in",
1183 0, Region::DefaultFlags, false);
1184 session.audition_region (*right);
1188 CrossfadeEditor::audition_right ()
1190 AudioPlaylist& pl (session.the_auditioner().prepare_playlist());
1192 AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade out",
1193 0, Region::DefaultFlags, false);
1194 AudioRegion* right = new AudioRegion (xfade.out(), 0, xfade.length(), "xfade out",
1195 0, Region::DefaultFlags, false);
1197 pl.add_region (*left, 0);
1198 pl.add_region (*right, 1);
1200 left->set_muted (true);
1202 /* there is only one ... */
1204 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1206 session.audition_playlist ();
1210 CrossfadeEditor::cancel_audition ()
1212 session.cancel_audition ();
1216 CrossfadeEditor::audition_toggled ()
1220 if ((x = audition_both_button.get_active ()) != session.is_auditioning()) {
1231 CrossfadeEditor::audition_right_toggled ()
1235 if ((x = audition_right_button.get_active ()) != session.is_auditioning()) {
1246 CrossfadeEditor::audition_right_dry_toggled ()
1250 if ((x = audition_right_dry_button.get_active ()) != session.is_auditioning()) {
1253 audition_right_dry ();
1261 CrossfadeEditor::audition_left_toggled ()
1265 if ((x = audition_left_button.get_active ()) != session.is_auditioning()) {
1276 CrossfadeEditor::audition_left_dry_toggled ()
1280 if ((x = audition_left_dry_button.get_active ()) != session.is_auditioning()) {
1283 audition_left_dry ();