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 (_("ardour: x-fade edit")),
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_position (Gtk::WIN_POS_MOUSE);
103 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
105 RadioButtonGroup sel_but_group = select_in_button.get_group();
106 select_out_button.set_group (sel_but_group);
107 select_out_button.set_mode (false);
108 select_in_button.set_mode (false);
110 if (fade_in_presets == 0) {
114 point_grabbed = false;
117 canvas = new ArdourCanvas::CanvasAA ();
118 canvas->signal_size_allocate().connect (mem_fun(*this, &CrossfadeEditor::canvas_allocation));
119 canvas->set_size_request (425, 200);
121 toplevel = new ArdourCanvas::SimpleRect (*(canvas->root()));
122 toplevel->property_x1() = 0.0;
123 toplevel->property_y1() = 0.0;
124 toplevel->property_x2() = 10.0;
125 toplevel->property_y2() = 10.0;
126 toplevel->property_fill() = true;
127 toplevel->property_fill_color_rgba() = (guint32) color_map[cCrossfadeEditorBase];
128 toplevel->property_outline_pixels() = 0;
129 toplevel->signal_event().connect (mem_fun (*this, &CrossfadeEditor::canvas_event));
131 fade[Out].line = new ArdourCanvas::Line (*(canvas->root()));
132 fade[Out].line->property_width_pixels() = 1;
133 fade[Out].line->property_fill_color_rgba() = color_map[cCrossfadeEditorLine];
135 fade[Out].shading = new ArdourCanvas::Polygon (*(canvas->root()));
136 fade[Out].shading->property_fill_color_rgba() = color_map[cCrossfadeEditorLineShading];
138 fade[In].line = new ArdourCanvas::Line (*(canvas->root()));
139 fade[In].line->property_width_pixels() = 1;
140 fade[In].line->property_fill_color_rgba() = color_map[cCrossfadeEditorLine];
142 fade[In].shading = new ArdourCanvas::Polygon (*(canvas->root()));
143 fade[In].shading->property_fill_color_rgba() = color_map[cCrossfadeEditorLineShading];
145 fade[In].shading->signal_event().connect (mem_fun (*this, &CrossfadeEditor::canvas_event));
146 fade[In].line->signal_event().connect (mem_fun (*this, &CrossfadeEditor::curve_event));
147 fade[Out].shading->signal_event().connect (mem_fun (*this, &CrossfadeEditor::canvas_event));
148 fade[Out].line->signal_event().connect (mem_fun (*this, &CrossfadeEditor::curve_event));
150 select_in_button.set_name (X_("CrossfadeEditCurveButton"));
151 select_out_button.set_name (X_("CrossfadeEditCurveButton"));
153 select_in_button.signal_clicked().connect (bind (mem_fun (*this, &CrossfadeEditor::curve_select_clicked), In));
154 select_out_button.signal_clicked().connect (bind (mem_fun (*this, &CrossfadeEditor::curve_select_clicked), Out));
156 HBox* acbox = manage (new HBox);
158 audition_box.set_border_width (7);
159 audition_box.set_spacing (5);
160 audition_box.set_homogeneous (false);
161 audition_box.pack_start (audition_left_dry_button, false, false);
162 audition_box.pack_start (audition_left_button, false, false);
163 audition_box.pack_start (audition_both_button, false, false);
164 audition_box.pack_start (audition_right_button, false, false);
165 audition_box.pack_start (audition_right_dry_button, false, false);
167 Frame* audition_frame = manage (new Frame (_("Audition")));
169 audition_frame->set_name (X_("CrossfadeEditFrame"));
170 audition_frame->add (audition_box);
172 acbox->pack_start (*audition_frame, true, false);
174 Frame* canvas_frame = manage (new Frame);
175 canvas_frame->add (*canvas);
176 canvas_frame->set_shadow_type (Gtk::SHADOW_IN);
178 fade_in_table.attach (select_in_button, 0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND);
179 fade_out_table.attach (select_out_button, 0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND);
189 for (list<Preset*>::iterator i = fade_in_presets->begin(); i != fade_in_presets->end(); ++i) {
191 pxmap = manage (new Image (Gdk::Pixbuf::create_from_xpm_data((*i)->xpm)));
192 pbutton = manage (new Button);
193 pbutton->add (*pxmap);
194 pbutton->set_name ("CrossfadeEditButton");
195 pbutton->signal_clicked().connect (bind (mem_fun(*this, &CrossfadeEditor::apply_preset), *i));
196 fade_in_table.attach (*pbutton, col, col+1, row, row+1);
197 fade_in_buttons.push_back (pbutton);
210 for (list<Preset*>::iterator i = fade_out_presets->begin(); i != fade_out_presets->end(); ++i) {
212 pxmap = manage (new Image (Gdk::Pixbuf::create_from_xpm_data((*i)->xpm)));
213 pbutton = manage (new Button);
214 pbutton->add (*pxmap);
215 pbutton->set_name ("CrossfadeEditButton");
216 pbutton->signal_clicked().connect (bind (mem_fun(*this, &CrossfadeEditor::apply_preset), *i));
217 fade_out_table.attach (*pbutton, col, col+1, row, row+1);
218 fade_out_buttons.push_back (pbutton);
228 clear_button.set_name ("CrossfadeEditButton");
229 revert_button.set_name ("CrossfadeEditButton");
230 ok_button.set_name ("CrossfadeEditButton");
231 cancel_button.set_name ("CrossfadeEditButton");
232 preroll_button.set_name ("CrossfadeEditButton");
233 postroll_button.set_name ("CrossfadeEditButton");
234 audition_both_button.set_name ("CrossfadeEditAuditionButton");
235 audition_left_dry_button.set_name ("CrossfadeEditAuditionButton");
236 audition_left_button.set_name ("CrossfadeEditAuditionButton");
237 audition_right_dry_button.set_name ("CrossfadeEditAuditionButton");
238 audition_right_button.set_name ("CrossfadeEditAuditionButton");
240 clear_button.signal_clicked().connect (mem_fun(*this, &CrossfadeEditor::clear));
241 revert_button.signal_clicked().connect (mem_fun(*this, &CrossfadeEditor::reset));
242 audition_both_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_toggled));
243 audition_right_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_right_toggled));
244 audition_right_dry_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_right_dry_toggled));
245 audition_left_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_left_toggled));
246 audition_left_dry_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_left_dry_toggled));
248 action_box.set_border_width (7);
249 action_box.set_spacing (5);
250 action_box.set_homogeneous (false);
251 action_box.pack_end (cancel_button, false, false);
252 action_box.pack_end (ok_button, false, false);
253 action_box.pack_end (revert_button, false, false);
254 action_box.pack_end (clear_button, false, false);
256 Frame* edit_frame = manage (new Frame (_("Edit")));
257 edit_frame->set_name (X_("CrossfadeEditFrame"));
258 edit_frame->add (action_box);
260 Gtk::HBox* action_center_box = manage (new HBox);
261 action_center_box->pack_start (*edit_frame, true, false);
263 roll_box.pack_start (preroll_button, false, false);
264 roll_box.pack_start (postroll_button, false, false);
266 Gtk::HBox* rcenter_box = manage (new HBox);
267 rcenter_box->pack_start (roll_box, true, false);
269 VBox* vpacker2 = manage (new (VBox));
271 vpacker2->set_border_width (12);
272 vpacker2->set_spacing (7);
273 vpacker2->pack_start (*acbox, false, false);
274 vpacker2->pack_start (*rcenter_box, false, false);
275 vpacker2->pack_start (*action_center_box, false, false);
277 curve_button_box.set_spacing (7);
278 curve_button_box.pack_start (fade_out_table, false, false, 12);
279 curve_button_box.pack_start (*vpacker2, false, false, 12);
280 curve_button_box.pack_start (fade_in_table, false, false, 12);
282 get_vbox()->pack_start (*canvas_frame, true, true);
283 get_vbox()->pack_start (curve_button_box, false, false);
285 /* button to allow hackers to check the actual curve values */
287 // Button* foobut = manage (new Button ("dump"));
288 // foobut-.signal_clicked().connect (mem_fun(*this, &CrossfadeEditor::dump));
289 // vpacker.pack_start (*foobut, false, false);
292 set (xfade.fade_in(), In);
295 set (xfade.fade_out(), Out);
297 curve_select_clicked (In);
299 xfade.StateChanged.connect (mem_fun(*this, &CrossfadeEditor::xfade_changed));
301 session.AuditionActive.connect (mem_fun(*this, &CrossfadeEditor::audition_state_changed));
304 CrossfadeEditor::~CrossfadeEditor()
306 /* most objects will be destroyed when the toplevel window is. */
308 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
312 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
318 CrossfadeEditor::dump ()
320 for (AutomationList::iterator i = fade[Out].normative_curve.begin(); i != fade[Out].normative_curve.end(); ++i) {
321 cerr << (*i)->when << ' ' << (*i)->value << endl;
326 CrossfadeEditor::audition_state_changed (bool yn)
328 ENSURE_GUI_THREAD (bind (mem_fun(*this, &CrossfadeEditor::audition_state_changed), yn));
331 audition_both_button.set_active (false);
332 audition_left_button.set_active (false);
333 audition_right_button.set_active (false);
334 audition_left_dry_button.set_active (false);
335 audition_right_dry_button.set_active (false);
340 CrossfadeEditor::set (const ARDOUR::Curve& curve, WhichFade which)
343 ARDOUR::Curve::const_iterator the_end;
345 for (list<Point*>::iterator i = fade[which].points.begin(); i != fade[which].points.end(); ++i) {
349 fade[which].points.clear ();
350 fade[which].gain_curve.clear ();
351 fade[which].normative_curve.clear ();
357 the_end = curve.const_end();
360 firstx = (*curve.const_begin())->when;
361 endx = (*the_end)->when;
363 for (ARDOUR::Curve::const_iterator i = curve.const_begin(); i != curve.const_end(); ++i) {
365 double xfract = ((*i)->when - firstx) / (endx - firstx);
366 double yfract = ((*i)->value - miny) / (maxy - miny);
368 Point* p = make_point ();
370 p->move_to (x_coordinate (xfract), y_coordinate (yfract),
373 fade[which].points.push_back (p);
376 /* no need to sort because curve is already time-ordered */
380 swap (which, current);
382 swap (which, current);
386 CrossfadeEditor::curve_event (GdkEvent* event)
388 /* treat it like a toplevel event */
390 return canvas_event (event);
394 CrossfadeEditor::point_event (GdkEvent* event, Point* point)
397 if (point->curve != fade[current].line) {
401 switch (event->type) {
402 case GDK_BUTTON_PRESS:
403 point_grabbed = true;
405 case GDK_BUTTON_RELEASE:
406 point_grabbed = false;
408 if (Keyboard::is_delete_event (&event->button)) {
409 fade[current].points.remove (point);
416 case GDK_MOTION_NOTIFY:
420 /* can't drag first or last points horizontally */
422 if (point == fade[current].points.front() || point == fade[current].points.back()) {
425 new_x = (event->motion.x - canvas_border)/effective_width();
428 new_y = 1.0 - ((event->motion.y - canvas_border)/effective_height());
429 point->move_to (x_coordinate (new_x), y_coordinate (new_y),
441 CrossfadeEditor::canvas_event (GdkEvent* event)
443 switch (event->type) {
444 case GDK_BUTTON_PRESS:
445 add_control_point ((event->button.x - canvas_border)/effective_width(),
446 1.0 - ((event->button.y - canvas_border)/effective_height()));
455 CrossfadeEditor::Point::~Point()
460 CrossfadeEditor::Point*
461 CrossfadeEditor::make_point ()
463 Point* p = new Point;
465 p->box = new ArdourCanvas::SimpleRect (*(canvas->root()));
466 p->box->property_fill() = true;
467 p->box->property_fill_color_rgba() = color_map[cCrossfadeEditorPointFill];
468 p->box->property_outline_color_rgba() = color_map[cCrossfadeEditorPointOutline];
469 p->box->property_outline_pixels() = 1;
471 p->curve = fade[current].line;
473 p->box->signal_event().connect (bind (mem_fun (*this, &CrossfadeEditor::point_event), p));
479 CrossfadeEditor::add_control_point (double x, double y)
483 /* enforce end point x location */
485 if (fade[current].points.empty()) {
487 } else if (fade[current].points.size() == 1) {
491 Point* p = make_point ();
493 p->move_to (x_coordinate (x), y_coordinate (y), x, y);
495 fade[current].points.push_back (p);
496 fade[current].points.sort (cmp);
502 CrossfadeEditor::Point::move_to (double nx, double ny, double xfract, double yfract)
504 const double half_size = rint(size/2.0);
505 double x1 = nx - half_size;
506 double x2 = nx + half_size;
508 box->property_x1() = x1;
509 box->property_x2() = x2;
511 box->property_y1() = ny - half_size;
512 box->property_y2() = ny + half_size;
519 CrossfadeEditor::canvas_allocation (Gtk::Allocation& alloc)
522 toplevel->property_x1() = 0.0;
523 toplevel->property_y1() = 0.0;
524 toplevel->property_x2() = (double) canvas->get_allocation().get_width() + canvas_border;
525 toplevel->property_y2() = (double) canvas->get_allocation().get_height() + canvas_border;
528 canvas->set_scroll_region (0.0, 0.0,
529 canvas->get_allocation().get_width(),
530 canvas->get_allocation().get_height());
532 Point* end = make_point ();
535 if (fade[In].points.size() > 1) {
536 Point* old_end = fade[In].points.back();
537 fade[In].points.pop_back ();
538 end->move_to (x_coordinate (old_end->x),
539 y_coordinate (old_end->y),
540 old_end->x, old_end->y);
545 end->move_to (x_coordinate (x), y_coordinate (y), x, y);
549 fade[In].points.push_back (end);
550 fade[In].points.sort (cmp);
552 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
553 (*i)->move_to (x_coordinate((*i)->x), y_coordinate((*i)->y),
559 if (fade[Out].points.size() > 1) {
560 Point* old_end = fade[Out].points.back();
561 fade[Out].points.pop_back ();
562 end->move_to (x_coordinate (old_end->x),
563 y_coordinate (old_end->y),
564 old_end->x, old_end->y);
569 end->move_to (x_coordinate (x), y_coordinate (y), x, y);
573 fade[Out].points.push_back (end);
574 fade[Out].points.sort (cmp);
576 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
577 (*i)->move_to (x_coordinate ((*i)->x),
578 y_coordinate ((*i)->y),
582 WhichFade old_current = current;
587 current = old_current;
589 double spu = xfade.length() / (double) effective_width();
591 if (fade[In].waves.empty()) {
592 make_waves (xfade.in(), In);
595 if (fade[Out].waves.empty()) {
596 make_waves (xfade.out(), Out);
600 vector<ArdourCanvas::WaveView*>::iterator i;
603 ht = canvas->get_allocation().get_height() / xfade.in().n_channels();
605 for (n = 0, i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i, ++n) {
610 (*i)->property_y() = yoff;
611 (*i)->property_height() = ht;
612 (*i)->property_samples_per_unit() = spu;
615 ht = canvas->get_allocation().get_height() / xfade.out().n_channels();
617 for (n = 0, i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i, ++n) {
622 (*i)->property_y() = yoff;
623 (*i)->property_height() = ht;
624 (*i)->property_samples_per_unit() = spu;
631 CrossfadeEditor::xfade_changed (Change ignored)
633 set (xfade.fade_in(), In);
634 set (xfade.fade_out(), Out);
638 CrossfadeEditor::redraw ()
640 if (canvas->get_allocation().get_width() < 2) {
644 jack_nframes_t len = xfade.length ();
646 fade[current].normative_curve.clear ();
647 fade[current].gain_curve.clear ();
649 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
650 fade[current].normative_curve.add ((*i)->x, (*i)->y);
651 fade[current].gain_curve.add (((*i)->x * len), (*i)->y);
654 size_t npoints = (size_t) effective_width();
657 fade[current].normative_curve.get_vector (0, 1.0, vec, npoints);
659 ArdourCanvas::Points pts;
660 ArdourCanvas::Points spts;
662 while (pts.size() < npoints) {
663 pts.push_back (Gnome::Art::Point (0,0));
666 while (spts.size() < npoints + 3) {
667 spts.push_back (Gnome::Art::Point (0,0));
670 /* the shade coordinates *MUST* be in anti-clockwise order.
677 spts[0].set_x (canvas_border);
678 spts[0].set_y (effective_height() + canvas_border);
682 spts[1].set_x (effective_width() + canvas_border);
683 spts[1].set_y (effective_height() + canvas_border);
687 spts[2].set_x (effective_width() + canvas_border);
688 spts[2].set_y (canvas_border);
695 spts[0].set_x (canvas_border);
696 spts[0].set_y (canvas_border);
700 spts[1].set_x (canvas_border);
701 spts[1].set_y (effective_height() + canvas_border);
705 spts[2].set_x (effective_width() + canvas_border);
706 spts[2].set_y (effective_height() + canvas_border);
710 // GTK2FIX some odd math to fix up here
712 size_t last_spt = (npoints + 3) - 1;
714 for (size_t i = 0; i < npoints; ++i) {
718 pts[i].set_x (canvas_border + i);
719 pts[i].set_y (y_coordinate (y));
721 spts[last_spt - i].set_x (canvas_border + i);
722 spts[last_spt - i].set_y (pts[i].get_y());
725 fade[current].line->property_points() = pts;
726 fade[current].shading->property_points() = spts;
728 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[current].waves.begin(); i != fade[current].waves.end(); ++i) {
729 (*i)->property_gain_src() = &fade[current].gain_curve;
734 CrossfadeEditor::apply_preset (Preset *preset)
736 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
740 fade[current].points.clear ();
742 for (Preset::iterator i = preset->begin(); i != preset->end(); ++i) {
743 Point* p = make_point ();
744 p->move_to (x_coordinate ((*i).x), y_coordinate ((*i).y),
746 fade[current].points.push_back (p);
753 CrossfadeEditor::apply ()
759 CrossfadeEditor::_apply_to (Crossfade* xf)
761 ARDOUR::Curve& in (xf->fade_in());
762 ARDOUR::Curve& out (xf->fade_out());
767 ARDOUR::Curve::const_iterator the_end = in.const_end();
770 double firstx = (*in.begin())->when;
771 double endx = (*the_end)->when;
772 double miny = in.get_min_y ();
773 double maxy = in.get_max_y ();
778 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
780 double when = firstx + ((*i)->x * (endx - firstx));
781 double value = (*i)->y; // miny + ((*i)->y * (maxy - miny));
782 in.add (when, value);
787 the_end = out.const_end();
790 firstx = (*out.begin())->when;
791 endx = (*the_end)->when;
792 miny = out.get_min_y ();
793 maxy = out.get_max_y ();
798 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
800 double when = firstx + ((*i)->x * (endx - firstx));
801 double value = (*i)->y; // miny + ((*i)->y * (maxy - miny));
802 out.add (when, value);
810 CrossfadeEditor::setup (Crossfade* xfade)
813 xfade->set_active (true);
814 xfade->fade_in().solve ();
815 xfade->fade_out().solve ();
819 CrossfadeEditor::clear ()
821 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
825 fade[current].points.clear ();
831 CrossfadeEditor::reset ()
833 set (xfade.fade_in(), In);
834 set (xfade.fade_out(), Out);
838 CrossfadeEditor::build_presets ()
842 fade_in_presets = new Presets;
843 fade_out_presets = new Presets;
847 p = new Preset (hiin_xpm);
848 p->push_back (PresetPoint (0, 0));
849 p->push_back (PresetPoint (0.0207373, 0.197222));
850 p->push_back (PresetPoint (0.0645161, 0.525));
851 p->push_back (PresetPoint (0.152074, 0.802778));
852 p->push_back (PresetPoint (0.276498, 0.919444));
853 p->push_back (PresetPoint (0.481567, 0.980556));
854 p->push_back (PresetPoint (0.767281, 1));
855 p->push_back (PresetPoint (1, 1));
856 fade_in_presets->push_back (p);
858 p = new Preset (loin_xpm);
859 p->push_back (PresetPoint (0, 0));
860 p->push_back (PresetPoint (0.389401, 0.0333333));
861 p->push_back (PresetPoint (0.629032, 0.0861111));
862 p->push_back (PresetPoint (0.829493, 0.233333));
863 p->push_back (PresetPoint (0.9447, 0.483333));
864 p->push_back (PresetPoint (0.976959, 0.697222));
865 p->push_back (PresetPoint (1, 1));
866 fade_in_presets->push_back (p);
868 p = new Preset (regin_xpm);
869 p->push_back (PresetPoint (0, 0));
870 p->push_back (PresetPoint (0.0737327, 0.308333));
871 p->push_back (PresetPoint (0.246544, 0.658333));
872 p->push_back (PresetPoint (0.470046, 0.886111));
873 p->push_back (PresetPoint (0.652074, 0.972222));
874 p->push_back (PresetPoint (0.771889, 0.988889));
875 p->push_back (PresetPoint (1, 1));
876 fade_in_presets->push_back (p);
878 p = new Preset (regin2_xpm);
879 p->push_back (PresetPoint (0, 0));
880 p->push_back (PresetPoint (0.304147, 0.0694444));
881 p->push_back (PresetPoint (0.529954, 0.152778));
882 p->push_back (PresetPoint (0.725806, 0.333333));
883 p->push_back (PresetPoint (0.847926, 0.558333));
884 p->push_back (PresetPoint (0.919355, 0.730556));
885 p->push_back (PresetPoint (1, 1));
886 fade_in_presets->push_back (p);
888 p = new Preset (linin_xpm);
889 p->push_back (PresetPoint (0, 0));
890 p->push_back (PresetPoint (1, 1));
891 fade_in_presets->push_back (p);
895 p = new Preset (hiout_xpm);
896 p->push_back (PresetPoint (0, 1));
897 p->push_back (PresetPoint (0.305556, 1));
898 p->push_back (PresetPoint (0.548611, 0.991736));
899 p->push_back (PresetPoint (0.759259, 0.931129));
900 p->push_back (PresetPoint (0.918981, 0.68595));
901 p->push_back (PresetPoint (0.976852, 0.22865));
902 p->push_back (PresetPoint (1, 0));
903 fade_out_presets->push_back (p);
905 p = new Preset (regout_xpm);
906 p->push_back (PresetPoint (0, 1));
907 p->push_back (PresetPoint (0.228111, 0.988889));
908 p->push_back (PresetPoint (0.347926, 0.972222));
909 p->push_back (PresetPoint (0.529954, 0.886111));
910 p->push_back (PresetPoint (0.753456, 0.658333));
911 p->push_back (PresetPoint (0.9262673, 0.308333));
912 p->push_back (PresetPoint (1, 0));
913 fade_out_presets->push_back (p);
915 p = new Preset (loout_xpm);
916 p->push_back (PresetPoint (0, 1));
917 p->push_back (PresetPoint (0.023041, 0.697222));
918 p->push_back (PresetPoint (0.0553, 0.483333));
919 p->push_back (PresetPoint (0.170507, 0.233333));
920 p->push_back (PresetPoint (0.370968, 0.0861111));
921 p->push_back (PresetPoint (0.610599, 0.0333333));
922 p->push_back (PresetPoint (1, 0));
923 fade_out_presets->push_back (p);
925 p = new Preset (regout2_xpm);
926 p->push_back (PresetPoint (0, 1));
927 p->push_back (PresetPoint (0.080645, 0.730556));
928 p->push_back (PresetPoint (0.277778, 0.289256));
929 p->push_back (PresetPoint (0.470046, 0.152778));
930 p->push_back (PresetPoint (0.695853, 0.0694444));
931 p->push_back (PresetPoint (1, 0));
932 fade_out_presets->push_back (p);
934 p = new Preset (linout_xpm);
935 p->push_back (PresetPoint (0, 1));
936 p->push_back (PresetPoint (1, 0));
937 fade_out_presets->push_back (p);
941 CrossfadeEditor::curve_select_clicked (WhichFade wf)
947 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) {
948 (*i)->property_wave_color() = color_map[cSelectedCrossfadeEditorWave];
951 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) {
952 (*i)->property_wave_color() = color_map[cCrossfadeEditorWave];
955 fade[In].line->property_fill_color_rgba() = color_map[cSelectedCrossfadeEditorLine];
956 fade[Out].line->property_fill_color_rgba() = color_map[cCrossfadeEditorLine];
957 fade[Out].shading->hide();
958 fade[In].shading->show();
960 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
964 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
968 for (vector<Button*>::iterator i = fade_out_buttons.begin(); i != fade_out_buttons.end(); ++i) {
969 (*i)->set_sensitive (false);
972 for (vector<Button*>::iterator i = fade_in_buttons.begin(); i != fade_in_buttons.end(); ++i) {
973 (*i)->set_sensitive (true);
978 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) {
979 (*i)->property_wave_color() = color_map[cCrossfadeEditorWave];
982 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) {
983 (*i)->property_wave_color() = color_map[cSelectedCrossfadeEditorWave];
986 fade[Out].line->property_fill_color_rgba() = color_map[cSelectedCrossfadeEditorLine];
987 fade[In].line->property_fill_color_rgba() = color_map[cCrossfadeEditorLine];
988 fade[In].shading->hide();
989 fade[Out].shading->show();
991 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
995 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
999 for (vector<Button*>::iterator i = fade_out_buttons.begin(); i != fade_out_buttons.end(); ++i) {
1000 (*i)->set_sensitive (true);
1003 for (vector<Button*>::iterator i = fade_in_buttons.begin(); i != fade_in_buttons.end(); ++i) {
1004 (*i)->set_sensitive (false);
1011 CrossfadeEditor::x_coordinate (double& xfract) const
1013 xfract = min (1.0, xfract);
1014 xfract = max (0.0, xfract);
1016 return canvas_border + (xfract * effective_width());
1020 CrossfadeEditor::y_coordinate (double& yfract) const
1022 yfract = min (1.0, yfract);
1023 yfract = max (0.0, yfract);
1025 return (canvas->get_allocation().get_height() - (canvas_border)) - (yfract * effective_height());
1029 CrossfadeEditor::make_waves (AudioRegion& region, WhichFade which)
1032 uint32_t nchans = region.n_channels();
1037 color = color_map[cSelectedCrossfadeEditorWave];
1039 color = color_map[cCrossfadeEditorWave];
1042 ht = canvas->get_allocation().get_height() / (double) nchans;
1043 spu = xfade.length() / (double) effective_width();
1045 for (uint32_t n = 0; n < nchans; ++n) {
1047 gdouble yoff = n * ht;
1049 if (region.source(n).peaks_ready (bind (mem_fun(*this, &CrossfadeEditor::peaks_ready), ®ion, which))) {
1051 WaveView* waveview = new WaveView (*(canvas->root()));
1053 waveview->property_data_src() = ®ion;
1054 waveview->property_cache_updater() = true;
1055 waveview->property_cache() = WaveView::create_cache();
1056 waveview->property_channel() = n;
1057 waveview->property_length_function() = (void*) region_length_from_c;
1058 waveview->property_sourcefile_length_function() = (void*) sourcefile_length_from_c;
1059 waveview->property_peak_function() = (void*) region_read_peaks_from_c;
1060 waveview->property_gain_function() = (void*) curve_get_vector_from_c;
1061 waveview->property_gain_src() = &fade[which].gain_curve;
1062 waveview->property_x() = canvas_border;
1063 waveview->property_y() = yoff;
1064 waveview->property_height() = ht;
1065 waveview->property_samples_per_unit() = spu;
1066 waveview->property_amplitude_above_axis() = 2.0;
1067 waveview->property_wave_color() = color;
1069 waveview->lower_to_bottom();
1070 fade[which].waves.push_back (waveview);
1074 toplevel->lower_to_bottom();
1078 CrossfadeEditor::peaks_ready (AudioRegion* r, WhichFade which)
1080 /* this should never be called, because the peak files for an xfade
1081 will be ready by the time we want them. but our API forces us
1082 to provide this, so ..
1085 make_waves (*r, which);
1089 CrossfadeEditor::audition_both ()
1091 AudioPlaylist& pl (session.the_auditioner().prepare_playlist());
1092 jack_nframes_t preroll;
1093 jack_nframes_t postroll;
1094 jack_nframes_t length;
1095 jack_nframes_t left_start_offset;
1096 jack_nframes_t right_length;
1097 jack_nframes_t left_length;
1099 if (preroll_button.get_active()) {
1100 preroll = ARDOUR_UI::instance()->preroll_clock.current_duration ();
1105 if (postroll_button.get_active()) {
1106 postroll = ARDOUR_UI::instance()->postroll_clock.current_duration ();
1111 if ((left_start_offset = xfade.out().length() - xfade.length()) >= preroll) {
1112 left_start_offset -= preroll;
1117 if ((left_length = xfade.length()) < xfade.out().length() - left_start_offset) {
1121 right_length = xfade.length();
1123 if (xfade.in().length() - right_length < postroll) {
1124 right_length += postroll;
1127 AudioRegion* left = new AudioRegion (xfade.out(), left_start_offset, left_length, "xfade out",
1128 0, Region::DefaultFlags, false);
1129 AudioRegion* right = new AudioRegion (xfade.in(), 0, right_length, "xfade in",
1130 0, Region::DefaultFlags, false);
1132 pl.add_region (*left, 0);
1133 pl.add_region (*right, 1+preroll);
1135 /* there is only one ... */
1137 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1139 session.audition_playlist ();
1143 CrossfadeEditor::audition_left_dry ()
1145 AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade left",
1146 0, Region::DefaultFlags, false);
1148 session.audition_region (*left);
1152 CrossfadeEditor::audition_left ()
1154 AudioPlaylist& pl (session.the_auditioner().prepare_playlist());
1156 AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade left",
1157 0, Region::DefaultFlags, false);
1158 AudioRegion* right = new AudioRegion (xfade.in(), 0, xfade.length(), "xfade in",
1159 0, Region::DefaultFlags, false);
1161 pl.add_region (*left, 0);
1162 pl.add_region (*right, 1);
1164 right->set_muted (true);
1166 /* there is only one ... */
1168 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1170 session.audition_playlist ();
1172 /* memory leak for regions */
1176 CrossfadeEditor::audition_right_dry ()
1178 AudioRegion* right = new AudioRegion (xfade.in(), 0, xfade.length(), "xfade in",
1179 0, Region::DefaultFlags, false);
1180 session.audition_region (*right);
1184 CrossfadeEditor::audition_right ()
1186 AudioPlaylist& pl (session.the_auditioner().prepare_playlist());
1188 AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade out",
1189 0, Region::DefaultFlags, false);
1190 AudioRegion* right = new AudioRegion (xfade.out(), 0, xfade.length(), "xfade out",
1191 0, Region::DefaultFlags, false);
1193 pl.add_region (*left, 0);
1194 pl.add_region (*right, 1);
1196 left->set_muted (true);
1198 /* there is only one ... */
1200 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1202 session.audition_playlist ();
1206 CrossfadeEditor::cancel_audition ()
1208 session.cancel_audition ();
1212 CrossfadeEditor::audition_toggled ()
1216 if ((x = audition_both_button.get_active ()) != session.is_auditioning()) {
1227 CrossfadeEditor::audition_right_toggled ()
1231 if ((x = audition_right_button.get_active ()) != session.is_auditioning()) {
1242 CrossfadeEditor::audition_right_dry_toggled ()
1246 if ((x = audition_right_dry_button.get_active ()) != session.is_auditioning()) {
1249 audition_right_dry ();
1257 CrossfadeEditor::audition_left_toggled ()
1261 if ((x = audition_left_button.get_active ()) != session.is_auditioning()) {
1272 CrossfadeEditor::audition_left_dry_toggled ()
1276 if ((x = audition_left_dry_button.get_active ()) != session.is_auditioning()) {
1279 audition_left_dry ();