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"
53 using namespace ARDOUR;
56 using namespace Editing;
60 const int32_t CrossfadeEditor::Point::size = 7;
61 const double CrossfadeEditor::canvas_border = 10;
62 CrossfadeEditor::Presets* CrossfadeEditor::fade_in_presets = 0;
63 CrossfadeEditor::Presets* CrossfadeEditor::fade_out_presets = 0;
65 CrossfadeEditor::Half::Half ()
67 normative_curve (0.0, 1.0, 1.0, true),
68 gain_curve (0.0, 2.0, 1.0, true)
72 CrossfadeEditor::CrossfadeEditor (Session& s, Crossfade& xf, double my, double mxy)
73 : ArdourDialog (_("ardour: x-fade edit")),
76 clear_button (_("Clear")),
77 revert_button (_("Reset")),
78 audition_both_button (_("Fade")),
79 audition_left_dry_button (_("Out (dry)")),
80 audition_left_button (_("Out")),
81 audition_right_dry_button (_("In (dry)")),
82 audition_right_button (_("In")),
84 preroll_button (_("With Pre-roll")),
85 postroll_button (_("With Post-roll")),
91 fade_out_table (3, 3),
93 select_in_button (_("Fade In")),
94 select_out_button (_("Fade Out"))
96 set_wmclass ("ardour_automationedit", "Ardour");
97 set_name ("CrossfadeEditWindow");
98 set_position (Gtk::WIN_POS_MOUSE);
100 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
102 RadioButtonGroup sel_but_group = select_in_button.get_group();
103 select_out_button.set_group (sel_but_group);
104 select_out_button.set_mode (false);
105 select_in_button.set_mode (false);
107 get_action_area()->set_layout(BUTTONBOX_SPREAD);
108 get_action_area()->pack_start(clear_button);
109 get_action_area()->pack_start(revert_button);
110 cancel_button = add_button ("Cancel", RESPONSE_CANCEL);
111 ok_button = add_button ("OK", RESPONSE_ACCEPT);
113 if (fade_in_presets == 0) {
117 point_grabbed = false;
120 canvas = new ArdourCanvas::CanvasAA ();
121 canvas->signal_size_allocate().connect (mem_fun(*this, &CrossfadeEditor::canvas_allocation));
122 canvas->set_size_request (425, 200);
124 toplevel = new ArdourCanvas::SimpleRect (*(canvas->root()));
125 toplevel->property_x1() = 0.0;
126 toplevel->property_y1() = 0.0;
127 toplevel->property_x2() = 10.0;
128 toplevel->property_y2() = 10.0;
129 toplevel->property_fill() = true;
130 toplevel->property_fill_color_rgba() = color_map[cCrossfadeEditorBase];
131 toplevel->property_outline_pixels() = 0;
132 toplevel->signal_event().connect (mem_fun (*this, &CrossfadeEditor::canvas_event));
134 fade[Out].line = new ArdourCanvas::Line (*(canvas->root()));
135 fade[Out].line->property_width_pixels() = 1;
136 fade[Out].line->property_fill_color_rgba() = color_map[cCrossfadeEditorLine];
138 fade[Out].shading = new ArdourCanvas::Polygon (*(canvas->root()));
139 fade[Out].shading->property_fill_color_rgba() = color_map[cCrossfadeEditorLineShading];
141 fade[In].line = new ArdourCanvas::Line (*(canvas->root()));
142 fade[In].line->property_width_pixels() = 1;
143 fade[In].line->property_fill_color_rgba() = color_map[cCrossfadeEditorLine];
145 fade[In].shading = new ArdourCanvas::Polygon (*(canvas->root()));
146 fade[In].shading->property_fill_color_rgba() = color_map[cCrossfadeEditorLineShading];
148 fade[In].shading->signal_event().connect (mem_fun (*this, &CrossfadeEditor::canvas_event));
149 fade[In].line->signal_event().connect (mem_fun (*this, &CrossfadeEditor::curve_event));
150 fade[Out].shading->signal_event().connect (mem_fun (*this, &CrossfadeEditor::canvas_event));
151 fade[Out].line->signal_event().connect (mem_fun (*this, &CrossfadeEditor::curve_event));
153 select_in_button.set_name (X_("CrossfadeEditCurveButton"));
154 select_out_button.set_name (X_("CrossfadeEditCurveButton"));
156 select_in_button.signal_clicked().connect (bind (mem_fun (*this, &CrossfadeEditor::curve_select_clicked), In));
157 select_out_button.signal_clicked().connect (bind (mem_fun (*this, &CrossfadeEditor::curve_select_clicked), Out));
159 HBox* acbox = manage (new HBox);
161 audition_box.set_border_width (7);
162 audition_box.set_spacing (5);
163 audition_box.set_homogeneous (false);
164 audition_box.pack_start (audition_left_dry_button, false, false);
165 audition_box.pack_start (audition_left_button, false, false);
166 audition_box.pack_start (audition_both_button, false, false);
167 audition_box.pack_start (audition_right_button, false, false);
168 audition_box.pack_start (audition_right_dry_button, false, false);
170 Frame* audition_frame = manage (new Frame (_("Audition")));
172 audition_frame->set_name (X_("CrossfadeEditFrame"));
173 audition_frame->add (audition_box);
175 acbox->pack_start (*audition_frame, true, false);
177 Frame* canvas_frame = manage (new Frame);
178 canvas_frame->add (*canvas);
179 canvas_frame->set_shadow_type (Gtk::SHADOW_IN);
181 fade_in_table.attach (select_in_button, 0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND);
182 fade_out_table.attach (select_out_button, 0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND);
192 for (list<Preset*>::iterator i = fade_in_presets->begin(); i != fade_in_presets->end(); ++i) {
194 pxmap = manage (new Image (get_xpm((*i)->xpm)));
195 pbutton = manage (new Button);
196 pbutton->add (*pxmap);
197 pbutton->set_name ("CrossfadeEditButton");
198 pbutton->signal_clicked().connect (bind (mem_fun(*this, &CrossfadeEditor::apply_preset), *i));
199 fade_in_table.attach (*pbutton, col, col+1, row, row+1);
200 fade_in_buttons.push_back (pbutton);
213 for (list<Preset*>::iterator i = fade_out_presets->begin(); i != fade_out_presets->end(); ++i) {
215 pxmap = manage (new Image (get_xpm((*i)->xpm)));
216 pbutton = manage (new Button);
217 pbutton->add (*pxmap);
218 pbutton->set_name ("CrossfadeEditButton");
219 pbutton->signal_clicked().connect (bind (mem_fun(*this, &CrossfadeEditor::apply_preset), *i));
220 fade_out_table.attach (*pbutton, col, col+1, row, row+1);
221 fade_out_buttons.push_back (pbutton);
231 clear_button.set_name ("CrossfadeEditButton");
232 revert_button.set_name ("CrossfadeEditButton");
233 ok_button->set_name ("CrossfadeEditButton");
234 cancel_button->set_name ("CrossfadeEditButton");
235 preroll_button.set_name ("CrossfadeEditButton");
236 postroll_button.set_name ("CrossfadeEditButton");
237 audition_both_button.set_name ("CrossfadeEditAuditionButton");
238 audition_left_dry_button.set_name ("CrossfadeEditAuditionButton");
239 audition_left_button.set_name ("CrossfadeEditAuditionButton");
240 audition_right_dry_button.set_name ("CrossfadeEditAuditionButton");
241 audition_right_button.set_name ("CrossfadeEditAuditionButton");
243 clear_button.signal_clicked().connect (mem_fun(*this, &CrossfadeEditor::clear));
244 revert_button.signal_clicked().connect (mem_fun(*this, &CrossfadeEditor::reset));
245 audition_both_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_toggled));
246 audition_right_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_right_toggled));
247 audition_right_dry_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_right_dry_toggled));
248 audition_left_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_left_toggled));
249 audition_left_dry_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_left_dry_toggled));
251 roll_box.pack_start (preroll_button, false, false);
252 roll_box.pack_start (postroll_button, false, false);
254 Gtk::HBox* rcenter_box = manage (new HBox);
255 rcenter_box->pack_start (roll_box, true, false);
257 VBox* vpacker2 = manage (new (VBox));
259 vpacker2->set_border_width (12);
260 vpacker2->set_spacing (7);
261 vpacker2->pack_start (*acbox, false, false);
262 vpacker2->pack_start (*rcenter_box, false, false);
264 curve_button_box.set_spacing (7);
265 curve_button_box.pack_start (fade_out_table, false, false, 12);
266 curve_button_box.pack_start (*vpacker2, false, false, 12);
267 curve_button_box.pack_start (fade_in_table, false, false, 12);
269 get_vbox()->pack_start (*canvas_frame, true, true);
270 get_vbox()->pack_start (curve_button_box, false, false);
272 /* button to allow hackers to check the actual curve values */
274 // Button* foobut = manage (new Button ("dump"));
275 // foobut-.signal_clicked().connect (mem_fun(*this, &CrossfadeEditor::dump));
276 // vpacker.pack_start (*foobut, false, false);
279 set (xfade.fade_in(), In);
282 set (xfade.fade_out(), Out);
284 curve_select_clicked (In);
286 xfade.StateChanged.connect (mem_fun(*this, &CrossfadeEditor::xfade_changed));
288 session.AuditionActive.connect (mem_fun(*this, &CrossfadeEditor::audition_state_changed));
292 CrossfadeEditor::~CrossfadeEditor()
294 /* most objects will be destroyed when the toplevel window is. */
296 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
300 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
306 CrossfadeEditor::dump ()
308 for (AutomationList::iterator i = fade[Out].normative_curve.begin(); i != fade[Out].normative_curve.end(); ++i) {
309 cerr << (*i)->when << ' ' << (*i)->value << endl;
314 CrossfadeEditor::audition_state_changed (bool yn)
316 ENSURE_GUI_THREAD (bind (mem_fun(*this, &CrossfadeEditor::audition_state_changed), yn));
319 audition_both_button.set_active (false);
320 audition_left_button.set_active (false);
321 audition_right_button.set_active (false);
322 audition_left_dry_button.set_active (false);
323 audition_right_dry_button.set_active (false);
328 CrossfadeEditor::set (const ARDOUR::Curve& curve, WhichFade which)
331 ARDOUR::Curve::const_iterator the_end;
333 for (list<Point*>::iterator i = fade[which].points.begin(); i != fade[which].points.end(); ++i) {
337 fade[which].points.clear ();
338 fade[which].gain_curve.clear ();
339 fade[which].normative_curve.clear ();
345 the_end = curve.const_end();
348 firstx = (*curve.const_begin())->when;
349 endx = (*the_end)->when;
351 for (ARDOUR::Curve::const_iterator i = curve.const_begin(); i != curve.const_end(); ++i) {
353 double xfract = ((*i)->when - firstx) / (endx - firstx);
354 double yfract = ((*i)->value - miny) / (maxy - miny);
356 Point* p = make_point ();
358 p->move_to (x_coordinate (xfract), y_coordinate (yfract),
361 fade[which].points.push_back (p);
364 /* no need to sort because curve is already time-ordered */
368 swap (which, current);
370 swap (which, current);
374 CrossfadeEditor::curve_event (GdkEvent* event)
376 /* treat it like a toplevel event */
378 return canvas_event (event);
382 CrossfadeEditor::point_event (GdkEvent* event, Point* point)
385 if (point->curve != fade[current].line) {
389 switch (event->type) {
390 case GDK_BUTTON_PRESS:
391 point_grabbed = true;
393 case GDK_BUTTON_RELEASE:
394 point_grabbed = false;
396 if (Keyboard::is_delete_event (&event->button)) {
397 fade[current].points.remove (point);
404 case GDK_MOTION_NOTIFY:
408 /* can't drag first or last points horizontally */
410 if (point == fade[current].points.front() || point == fade[current].points.back()) {
413 new_x = (event->motion.x - canvas_border)/effective_width();
416 new_y = 1.0 - ((event->motion.y - canvas_border)/effective_height());
417 point->move_to (x_coordinate (new_x), y_coordinate (new_y),
429 CrossfadeEditor::canvas_event (GdkEvent* event)
431 switch (event->type) {
432 case GDK_BUTTON_PRESS:
433 add_control_point ((event->button.x - canvas_border)/effective_width(),
434 1.0 - ((event->button.y - canvas_border)/effective_height()));
443 CrossfadeEditor::Point::~Point()
448 CrossfadeEditor::Point*
449 CrossfadeEditor::make_point ()
451 Point* p = new Point;
453 p->box = new ArdourCanvas::SimpleRect (*(canvas->root()));
454 p->box->property_fill() = true;
455 p->box->property_fill_color_rgba() = color_map[cCrossfadeEditorPointFill];
456 p->box->property_outline_color_rgba() = color_map[cCrossfadeEditorPointOutline];
457 p->box->property_outline_pixels() = 1;
459 p->curve = fade[current].line;
461 p->box->signal_event().connect (bind (mem_fun (*this, &CrossfadeEditor::point_event), p));
467 CrossfadeEditor::add_control_point (double x, double y)
471 /* enforce end point x location */
473 if (fade[current].points.empty()) {
475 } else if (fade[current].points.size() == 1) {
479 Point* p = make_point ();
481 p->move_to (x_coordinate (x), y_coordinate (y), x, y);
483 fade[current].points.push_back (p);
484 fade[current].points.sort (cmp);
490 CrossfadeEditor::Point::move_to (double nx, double ny, double xfract, double yfract)
492 const double half_size = rint(size/2.0);
493 double x1 = nx - half_size;
494 double x2 = nx + half_size;
496 box->property_x1() = x1;
497 box->property_x2() = x2;
499 box->property_y1() = ny - half_size;
500 box->property_y2() = ny + half_size;
507 CrossfadeEditor::canvas_allocation (Gtk::Allocation& alloc)
510 toplevel->property_x1() = 0.0;
511 toplevel->property_y1() = 0.0;
512 toplevel->property_x2() = (double) canvas->get_allocation().get_width() + canvas_border;
513 toplevel->property_y2() = (double) canvas->get_allocation().get_height() + canvas_border;
516 canvas->set_scroll_region (0.0, 0.0,
517 canvas->get_allocation().get_width(),
518 canvas->get_allocation().get_height());
520 Point* end = make_point ();
523 if (fade[In].points.size() > 1) {
524 Point* old_end = fade[In].points.back();
525 fade[In].points.pop_back ();
526 end->move_to (x_coordinate (old_end->x),
527 y_coordinate (old_end->y),
528 old_end->x, old_end->y);
533 end->move_to (x_coordinate (x), y_coordinate (y), x, y);
537 fade[In].points.push_back (end);
538 fade[In].points.sort (cmp);
540 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
541 (*i)->move_to (x_coordinate((*i)->x), y_coordinate((*i)->y),
547 if (fade[Out].points.size() > 1) {
548 Point* old_end = fade[Out].points.back();
549 fade[Out].points.pop_back ();
550 end->move_to (x_coordinate (old_end->x),
551 y_coordinate (old_end->y),
552 old_end->x, old_end->y);
557 end->move_to (x_coordinate (x), y_coordinate (y), x, y);
561 fade[Out].points.push_back (end);
562 fade[Out].points.sort (cmp);
564 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
565 (*i)->move_to (x_coordinate ((*i)->x),
566 y_coordinate ((*i)->y),
570 WhichFade old_current = current;
575 current = old_current;
577 double spu = xfade.length() / (double) effective_width();
579 if (fade[In].waves.empty()) {
580 make_waves (xfade.in(), In);
583 if (fade[Out].waves.empty()) {
584 make_waves (xfade.out(), Out);
588 vector<ArdourCanvas::WaveView*>::iterator i;
591 ht = canvas->get_allocation().get_height() / xfade.in().n_channels();
593 for (n = 0, i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i, ++n) {
598 (*i)->property_y() = yoff;
599 (*i)->property_height() = ht;
600 (*i)->property_samples_per_unit() = spu;
603 ht = canvas->get_allocation().get_height() / xfade.out().n_channels();
605 for (n = 0, i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i, ++n) {
610 (*i)->property_y() = yoff;
611 (*i)->property_height() = ht;
612 (*i)->property_samples_per_unit() = spu;
619 CrossfadeEditor::xfade_changed (Change ignored)
621 set (xfade.fade_in(), In);
622 set (xfade.fade_out(), Out);
626 CrossfadeEditor::redraw ()
628 if (canvas->get_allocation().get_width() < 2) {
632 jack_nframes_t len = xfade.length ();
634 fade[current].normative_curve.clear ();
635 fade[current].gain_curve.clear ();
637 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
638 fade[current].normative_curve.add ((*i)->x, (*i)->y);
639 fade[current].gain_curve.add (((*i)->x * len), (*i)->y);
642 size_t npoints = (size_t) effective_width();
645 fade[current].normative_curve.get_vector (0, 1.0, vec, npoints);
647 ArdourCanvas::Points pts;
648 ArdourCanvas::Points spts;
650 while (pts.size() < npoints) {
651 pts.push_back (Gnome::Art::Point (0,0));
654 while (spts.size() < npoints + 3) {
655 spts.push_back (Gnome::Art::Point (0,0));
658 /* the shade coordinates *MUST* be in anti-clockwise order.
665 spts[0].set_x (canvas_border);
666 spts[0].set_y (effective_height() + canvas_border);
670 spts[1].set_x (effective_width() + canvas_border);
671 spts[1].set_y (effective_height() + canvas_border);
675 spts[2].set_x (effective_width() + canvas_border);
676 spts[2].set_y (canvas_border);
683 spts[0].set_x (canvas_border);
684 spts[0].set_y (canvas_border);
688 spts[1].set_x (canvas_border);
689 spts[1].set_y (effective_height() + canvas_border);
693 spts[2].set_x (effective_width() + canvas_border);
694 spts[2].set_y (effective_height() + canvas_border);
698 // GTK2FIX some odd math to fix up here
700 size_t last_spt = (npoints + 3) - 1;
702 for (size_t i = 0; i < npoints; ++i) {
706 pts[i].set_x (canvas_border + i);
707 pts[i].set_y (y_coordinate (y));
709 spts[last_spt - i].set_x (canvas_border + i);
710 spts[last_spt - i].set_y (pts[i].get_y());
713 fade[current].line->property_points() = pts;
714 fade[current].shading->property_points() = spts;
716 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[current].waves.begin(); i != fade[current].waves.end(); ++i) {
717 (*i)->property_gain_src() = &fade[current].gain_curve;
722 CrossfadeEditor::apply_preset (Preset *preset)
724 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
728 fade[current].points.clear ();
730 for (Preset::iterator i = preset->begin(); i != preset->end(); ++i) {
731 Point* p = make_point ();
732 p->move_to (x_coordinate ((*i).x), y_coordinate ((*i).y),
734 fade[current].points.push_back (p);
741 CrossfadeEditor::apply ()
747 CrossfadeEditor::_apply_to (Crossfade* xf)
749 ARDOUR::Curve& in (xf->fade_in());
750 ARDOUR::Curve& out (xf->fade_out());
755 ARDOUR::Curve::const_iterator the_end = in.const_end();
758 double firstx = (*in.begin())->when;
759 double endx = (*the_end)->when;
760 double miny = in.get_min_y ();
761 double maxy = in.get_max_y ();
766 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
768 double when = firstx + ((*i)->x * (endx - firstx));
769 double value = (*i)->y; // miny + ((*i)->y * (maxy - miny));
770 in.add (when, value);
775 the_end = out.const_end();
778 firstx = (*out.begin())->when;
779 endx = (*the_end)->when;
780 miny = out.get_min_y ();
781 maxy = out.get_max_y ();
786 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
788 double when = firstx + ((*i)->x * (endx - firstx));
789 double value = (*i)->y; // miny + ((*i)->y * (maxy - miny));
790 out.add (when, value);
798 CrossfadeEditor::setup (Crossfade* xfade)
801 xfade->set_active (true);
802 xfade->fade_in().solve ();
803 xfade->fade_out().solve ();
807 CrossfadeEditor::clear ()
809 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
813 fade[current].points.clear ();
819 CrossfadeEditor::reset ()
821 set (xfade.fade_in(), In);
822 set (xfade.fade_out(), Out);
826 CrossfadeEditor::build_presets ()
830 fade_in_presets = new Presets;
831 fade_out_presets = new Presets;
834 p = new Preset ("hiin.xpm");
835 p->push_back (PresetPoint (0, 0));
836 p->push_back (PresetPoint (0.0207373, 0.197222));
837 p->push_back (PresetPoint (0.0645161, 0.525));
838 p->push_back (PresetPoint (0.152074, 0.802778));
839 p->push_back (PresetPoint (0.276498, 0.919444));
840 p->push_back (PresetPoint (0.481567, 0.980556));
841 p->push_back (PresetPoint (0.767281, 1));
842 p->push_back (PresetPoint (1, 1));
843 fade_in_presets->push_back (p);
845 p = new Preset ("loin.xpm");
846 p->push_back (PresetPoint (0, 0));
847 p->push_back (PresetPoint (0.389401, 0.0333333));
848 p->push_back (PresetPoint (0.629032, 0.0861111));
849 p->push_back (PresetPoint (0.829493, 0.233333));
850 p->push_back (PresetPoint (0.9447, 0.483333));
851 p->push_back (PresetPoint (0.976959, 0.697222));
852 p->push_back (PresetPoint (1, 1));
853 fade_in_presets->push_back (p);
855 p = new Preset ("regin.xpm");
856 p->push_back (PresetPoint (0, 0));
857 p->push_back (PresetPoint (0.0737327, 0.308333));
858 p->push_back (PresetPoint (0.246544, 0.658333));
859 p->push_back (PresetPoint (0.470046, 0.886111));
860 p->push_back (PresetPoint (0.652074, 0.972222));
861 p->push_back (PresetPoint (0.771889, 0.988889));
862 p->push_back (PresetPoint (1, 1));
863 fade_in_presets->push_back (p);
865 p = new Preset ("regin2.xpm");
866 p->push_back (PresetPoint (0, 0));
867 p->push_back (PresetPoint (0.304147, 0.0694444));
868 p->push_back (PresetPoint (0.529954, 0.152778));
869 p->push_back (PresetPoint (0.725806, 0.333333));
870 p->push_back (PresetPoint (0.847926, 0.558333));
871 p->push_back (PresetPoint (0.919355, 0.730556));
872 p->push_back (PresetPoint (1, 1));
873 fade_in_presets->push_back (p);
875 p = new Preset ("linin.xpm");
876 p->push_back (PresetPoint (0, 0));
877 p->push_back (PresetPoint (1, 1));
878 fade_in_presets->push_back (p);
882 p = new Preset ("hiout.xpm");
883 p->push_back (PresetPoint (0, 1));
884 p->push_back (PresetPoint (0.305556, 1));
885 p->push_back (PresetPoint (0.548611, 0.991736));
886 p->push_back (PresetPoint (0.759259, 0.931129));
887 p->push_back (PresetPoint (0.918981, 0.68595));
888 p->push_back (PresetPoint (0.976852, 0.22865));
889 p->push_back (PresetPoint (1, 0));
890 fade_out_presets->push_back (p);
892 p = new Preset ("regout.xpm");
893 p->push_back (PresetPoint (0, 1));
894 p->push_back (PresetPoint (0.228111, 0.988889));
895 p->push_back (PresetPoint (0.347926, 0.972222));
896 p->push_back (PresetPoint (0.529954, 0.886111));
897 p->push_back (PresetPoint (0.753456, 0.658333));
898 p->push_back (PresetPoint (0.9262673, 0.308333));
899 p->push_back (PresetPoint (1, 0));
900 fade_out_presets->push_back (p);
902 p = new Preset ("loout.xpm");
903 p->push_back (PresetPoint (0, 1));
904 p->push_back (PresetPoint (0.023041, 0.697222));
905 p->push_back (PresetPoint (0.0553, 0.483333));
906 p->push_back (PresetPoint (0.170507, 0.233333));
907 p->push_back (PresetPoint (0.370968, 0.0861111));
908 p->push_back (PresetPoint (0.610599, 0.0333333));
909 p->push_back (PresetPoint (1, 0));
910 fade_out_presets->push_back (p);
912 p = new Preset ("regout2.xpm");
913 p->push_back (PresetPoint (0, 1));
914 p->push_back (PresetPoint (0.080645, 0.730556));
915 p->push_back (PresetPoint (0.277778, 0.289256));
916 p->push_back (PresetPoint (0.470046, 0.152778));
917 p->push_back (PresetPoint (0.695853, 0.0694444));
918 p->push_back (PresetPoint (1, 0));
919 fade_out_presets->push_back (p);
921 p = new Preset ("linout.xpm");
922 p->push_back (PresetPoint (0, 1));
923 p->push_back (PresetPoint (1, 0));
924 fade_out_presets->push_back (p);
928 CrossfadeEditor::curve_select_clicked (WhichFade wf)
934 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) {
935 (*i)->property_wave_color() = color_map[cSelectedCrossfadeEditorWave];
938 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) {
939 (*i)->property_wave_color() = color_map[cCrossfadeEditorWave];
942 fade[In].line->property_fill_color_rgba() = color_map[cSelectedCrossfadeEditorLine];
943 fade[Out].line->property_fill_color_rgba() = color_map[cCrossfadeEditorLine];
944 fade[Out].shading->hide();
945 fade[In].shading->show();
947 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
951 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
955 for (vector<Button*>::iterator i = fade_out_buttons.begin(); i != fade_out_buttons.end(); ++i) {
956 (*i)->set_sensitive (false);
959 for (vector<Button*>::iterator i = fade_in_buttons.begin(); i != fade_in_buttons.end(); ++i) {
960 (*i)->set_sensitive (true);
965 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) {
966 (*i)->property_wave_color() = color_map[cCrossfadeEditorWave];
969 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) {
970 (*i)->property_wave_color() = color_map[cSelectedCrossfadeEditorWave];
973 fade[Out].line->property_fill_color_rgba() = color_map[cSelectedCrossfadeEditorLine];
974 fade[In].line->property_fill_color_rgba() = color_map[cCrossfadeEditorLine];
975 fade[In].shading->hide();
976 fade[Out].shading->show();
978 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
982 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
986 for (vector<Button*>::iterator i = fade_out_buttons.begin(); i != fade_out_buttons.end(); ++i) {
987 (*i)->set_sensitive (true);
990 for (vector<Button*>::iterator i = fade_in_buttons.begin(); i != fade_in_buttons.end(); ++i) {
991 (*i)->set_sensitive (false);
998 CrossfadeEditor::x_coordinate (double& xfract) const
1000 xfract = min (1.0, xfract);
1001 xfract = max (0.0, xfract);
1003 return canvas_border + (xfract * effective_width());
1007 CrossfadeEditor::y_coordinate (double& yfract) const
1009 yfract = min (1.0, yfract);
1010 yfract = max (0.0, yfract);
1012 return (canvas->get_allocation().get_height() - (canvas_border)) - (yfract * effective_height());
1016 CrossfadeEditor::make_waves (AudioRegion& region, WhichFade which)
1019 uint32_t nchans = region.n_channels();
1024 color = color_map[cSelectedCrossfadeEditorWave];
1026 color = color_map[cCrossfadeEditorWave];
1029 ht = canvas->get_allocation().get_height() / (double) nchans;
1030 spu = xfade.length() / (double) effective_width();
1032 for (uint32_t n = 0; n < nchans; ++n) {
1034 gdouble yoff = n * ht;
1036 if (region.source(n).peaks_ready (bind (mem_fun(*this, &CrossfadeEditor::peaks_ready), ®ion, which), peaks_ready_connection)) {
1038 WaveView* waveview = new WaveView (*(canvas->root()));
1040 waveview->property_data_src() = ®ion;
1041 waveview->property_cache_updater() = true;
1042 waveview->property_cache() = WaveView::create_cache();
1043 waveview->property_channel() = n;
1044 waveview->property_length_function() = (void*) region_length_from_c;
1045 waveview->property_sourcefile_length_function() = (void*) sourcefile_length_from_c;
1046 waveview->property_peak_function() = (void*) region_read_peaks_from_c;
1047 waveview->property_gain_function() = (void*) curve_get_vector_from_c;
1048 waveview->property_gain_src() = &fade[which].gain_curve;
1049 waveview->property_x() = canvas_border;
1050 waveview->property_y() = yoff;
1051 waveview->property_height() = ht;
1052 waveview->property_samples_per_unit() = spu;
1053 waveview->property_amplitude_above_axis() = 2.0;
1054 waveview->property_wave_color() = color;
1056 waveview->lower_to_bottom();
1057 fade[which].waves.push_back (waveview);
1061 toplevel->lower_to_bottom();
1065 CrossfadeEditor::peaks_ready (AudioRegion* r, WhichFade which)
1067 /* this should never be called, because the peak files for an xfade
1068 will be ready by the time we want them. but our API forces us
1069 to provide this, so ..
1071 peaks_ready_connection.disconnect ();
1072 make_waves (*r, which);
1076 CrossfadeEditor::audition_both ()
1078 AudioPlaylist& pl (session.the_auditioner().prepare_playlist());
1079 jack_nframes_t preroll;
1080 jack_nframes_t postroll;
1081 jack_nframes_t length;
1082 jack_nframes_t left_start_offset;
1083 jack_nframes_t right_length;
1084 jack_nframes_t left_length;
1086 if (preroll_button.get_active()) {
1087 preroll = ARDOUR_UI::instance()->preroll_clock.current_duration ();
1092 if (postroll_button.get_active()) {
1093 postroll = ARDOUR_UI::instance()->postroll_clock.current_duration ();
1098 if ((left_start_offset = xfade.out().length() - xfade.length()) >= preroll) {
1099 left_start_offset -= preroll;
1104 if ((left_length = xfade.length()) < xfade.out().length() - left_start_offset) {
1108 right_length = xfade.length();
1110 if (xfade.in().length() - right_length < postroll) {
1111 right_length += postroll;
1114 AudioRegion* left = new AudioRegion (xfade.out(), left_start_offset, left_length, "xfade out",
1115 0, Region::DefaultFlags, false);
1116 AudioRegion* right = new AudioRegion (xfade.in(), 0, right_length, "xfade in",
1117 0, Region::DefaultFlags, false);
1119 pl.add_region (*left, 0);
1120 pl.add_region (*right, 1+preroll);
1122 /* there is only one ... */
1124 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1126 session.audition_playlist ();
1130 CrossfadeEditor::audition_left_dry ()
1132 AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade left",
1133 0, Region::DefaultFlags, false);
1135 session.audition_region (*left);
1139 CrossfadeEditor::audition_left ()
1141 AudioPlaylist& pl (session.the_auditioner().prepare_playlist());
1143 AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade left",
1144 0, Region::DefaultFlags, false);
1145 AudioRegion* right = new AudioRegion (xfade.in(), 0, xfade.length(), "xfade in",
1146 0, Region::DefaultFlags, false);
1148 pl.add_region (*left, 0);
1149 pl.add_region (*right, 1);
1151 right->set_muted (true);
1153 /* there is only one ... */
1155 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1157 session.audition_playlist ();
1159 /* memory leak for regions */
1163 CrossfadeEditor::audition_right_dry ()
1165 AudioRegion* right = new AudioRegion (xfade.in(), 0, xfade.length(), "xfade in",
1166 0, Region::DefaultFlags, false);
1167 session.audition_region (*right);
1171 CrossfadeEditor::audition_right ()
1173 AudioPlaylist& pl (session.the_auditioner().prepare_playlist());
1175 AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade out",
1176 0, Region::DefaultFlags, false);
1177 AudioRegion* right = new AudioRegion (xfade.out(), 0, xfade.length(), "xfade out",
1178 0, Region::DefaultFlags, false);
1180 pl.add_region (*left, 0);
1181 pl.add_region (*right, 1);
1183 left->set_muted (true);
1185 /* there is only one ... */
1187 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1189 session.audition_playlist ();
1193 CrossfadeEditor::cancel_audition ()
1195 session.cancel_audition ();
1199 CrossfadeEditor::audition_toggled ()
1203 if ((x = audition_both_button.get_active ()) != session.is_auditioning()) {
1214 CrossfadeEditor::audition_right_toggled ()
1218 if ((x = audition_right_button.get_active ()) != session.is_auditioning()) {
1229 CrossfadeEditor::audition_right_dry_toggled ()
1233 if ((x = audition_right_dry_button.get_active ()) != session.is_auditioning()) {
1236 audition_right_dry ();
1244 CrossfadeEditor::audition_left_toggled ()
1248 if ((x = audition_left_button.get_active ()) != session.is_auditioning()) {
1259 CrossfadeEditor::audition_left_dry_toggled ()
1263 if ((x = audition_left_dry_button.get_active ()) != session.is_auditioning()) {
1266 audition_left_dry ();