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/pixmap.h>
27 #include <gtkmm/scrolledwindow.h>
29 #include <ardour/automation_event.h>
30 #include <ardour/curve.h>
31 #include <ardour/crossfade.h>
32 #include <ardour/session.h>
33 #include <ardour/auditioner.h>
34 #include <ardour/audioplaylist.h>
35 #include <ardour/playlist_templates.h>
37 #include <gtkmm2ext/gtk_ui.h>
39 #include "ardour_ui.h"
40 #include "crossfade_edit.h"
41 #include "rgb_macros.h"
42 #include "canvas-simplerect.h"
43 #include "canvas-waveview.h"
46 #include "gui_thread.h"
49 using namespace ARDOUR;
52 using namespace Editing;
56 const int32_t CrossfadeEditor::Point::size = 7;
57 const double CrossfadeEditor::canvas_border = 10;
58 CrossfadeEditor::Presets* CrossfadeEditor::fade_in_presets = 0;
59 CrossfadeEditor::Presets* CrossfadeEditor::fade_out_presets = 0;
61 #include "crossfade_xpms.h"
63 CrossfadeEditor::Half::Half ()
65 normative_curve (0.0, 1.0, 1.0, true),
66 gain_curve (0.0, 2.0, 1.0, true)
70 CrossfadeEditor::CrossfadeEditor (Session& s, Crossfade& xf, double my, double mxy)
71 : ArdourDialog (_("crossfade editor")),
72 cancel_button (_("Cancel")),
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_title (_("ardour: x-fade edit"));
99 set_position (Gtk::WIN_POS_MOUSE);
102 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
104 select_out_button.set_group (select_in_button.group());
105 select_out_button.set_mode (false);
106 select_in_button.set_mode (false);
108 if (fade_in_presets == 0) {
112 point_grabbed = false;
115 _canvas = gtk_canvas_new_aa ();
117 canvas = wrap (_canvas);
118 canvas->size_allocate.connect (slot (*this, &CrossfadeEditor::canvas_allocation));
119 canvas->set_size_request (425, 200);
121 toplevel = gtk_canvas_item_new (gtk_canvas_root (GTK_CANVAS(_canvas)),
122 gtk_canvas_simplerect_get_type(),
127 "fill", (gboolean) TRUE,
128 "fill_color_rgba", (guint32) color_map[cCrossfadeEditorBase],
132 gtk_signal_connect (GTK_OBJECT(toplevel),
134 (GtkSignalFunc) _canvas_event,
137 fade[Out].line = gtk_canvas_item_new (gtk_canvas_root (GTK_CANVAS(_canvas)),
138 gtk_canvas_line_get_type (),
139 "width_pixels", (guint) 1,
140 "fill_color_rgba", color_map[cCrossfadeEditorLine],
143 fade[Out].shading = gtk_canvas_item_new (gtk_canvas_root (GTK_CANVAS(_canvas)),
144 gtk_canvas_polygon_get_type(),
145 "fill_color_rgba", color_map[cCrossfadeEditorLineShading],
148 fade[In].line = gtk_canvas_item_new (gtk_canvas_root (GTK_CANVAS(_canvas)),
149 gtk_canvas_line_get_type (),
150 "width_pixels", (guint) 1,
151 "fill_color_rgba", color_map[cCrossfadeEditorLine],
154 fade[In].shading = gtk_canvas_item_new (gtk_canvas_root (GTK_CANVAS(_canvas)),
155 gtk_canvas_polygon_get_type(),
156 "fill_color_rgba", color_map[cCrossfadeEditorLineShading],
159 gtk_signal_connect (GTK_OBJECT(fade[In].shading),
161 (GtkSignalFunc) _canvas_event,
165 gtk_signal_connect (GTK_OBJECT(fade[Out].shading),
167 (GtkSignalFunc) _canvas_event,
170 gtk_signal_connect (GTK_OBJECT(fade[In].line),
172 (GtkSignalFunc) _curve_event,
175 gtk_signal_connect (GTK_OBJECT(fade[Out].line),
177 (GtkSignalFunc) _curve_event,
181 select_in_button.set_name (X_("CrossfadeEditCurveButton"));
182 select_out_button.set_name (X_("CrossfadeEditCurveButton"));
184 select_in_button.signal_clicked().connect (bind (slot (this, &CrossfadeEditor::curve_select_clicked), In));
185 select_out_button.signal_clicked().connect (bind (slot (this, &CrossfadeEditor::curve_select_clicked), Out));
187 HBox* acbox = manage (new HBox);
189 audition_box.set_border_width (7);
190 audition_box.set_spacing (5);
191 audition_box.set_homogeneous (false);
192 audition_box.pack_start (audition_left_dry_button, false, false);
193 audition_box.pack_start (audition_left_button, false, false);
194 audition_box.pack_start (audition_both_button, false, false);
195 audition_box.pack_start (audition_right_button, false, false);
196 audition_box.pack_start (audition_right_dry_button, false, false);
198 Frame* audition_frame = manage (new Frame (_("Audition")));
200 audition_frame->set_name (X_("CrossfadeEditFrame"));
201 audition_frame->add (audition_box);
203 acbox->pack_start (*audition_frame, true, false);
205 Frame* canvas_frame = manage (new Frame);
206 canvas_frame->add (*canvas);
207 canvas_frame->set_shadow_type (Gtk::SHADOW_IN);
209 fade_in_table.attach (select_in_button, 0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND);
210 fade_out_table.attach (select_out_button, 0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND);
220 for (list<Preset*>::iterator i = fade_in_presets->begin(); i != fade_in_presets->end(); ++i) {
222 pxmap = manage (new Pixmap ((*i)->xpm));
223 pbutton = manage (new Button);
224 pbutton->add (*pxmap);
225 pbutton->set_name ("CrossfadeEditButton");
226 pbutton-.signal_clicked().connect (bind (slot (*this, &CrossfadeEditor::apply_preset), *i));
227 fade_in_table.attach (*pbutton, col, col+1, row, row+1);
228 fade_in_buttons.push_back (pbutton);
241 for (list<Preset*>::iterator i = fade_out_presets->begin(); i != fade_out_presets->end(); ++i) {
243 pxmap = manage (new Pixmap ((*i)->xpm));
244 pbutton = manage (new Button);
245 pbutton->add (*pxmap);
246 pbutton->set_name ("CrossfadeEditButton");
247 pbutton-.signal_clicked().connect (bind (slot (*this, &CrossfadeEditor::apply_preset), *i));
248 fade_out_table.attach (*pbutton, col, col+1, row, row+1);
249 fade_out_buttons.push_back (pbutton);
259 clear_button.set_name ("CrossfadeEditButton");
260 revert_button.set_name ("CrossfadeEditButton");
261 ok_button.set_name ("CrossfadeEditButton");
262 cancel_button.set_name ("CrossfadeEditButton");
263 preroll_button.set_name ("CrossfadeEditButton");
264 postroll_button.set_name ("CrossfadeEditButton");
265 audition_both_button.set_name ("CrossfadeEditAuditionButton");
266 audition_left_dry_button.set_name ("CrossfadeEditAuditionButton");
267 audition_left_button.set_name ("CrossfadeEditAuditionButton");
268 audition_right_dry_button.set_name ("CrossfadeEditAuditionButton");
269 audition_right_button.set_name ("CrossfadeEditAuditionButton");
271 clear_button.signal_clicked().connect (slot (*this, &CrossfadeEditor::clear));
272 revert_button.signal_clicked().connect (slot (*this, &CrossfadeEditor::reset));
273 audition_both_button.toggled.connect (slot (*this, &CrossfadeEditor::audition_toggled));
274 audition_right_button.toggled.connect (slot (*this, &CrossfadeEditor::audition_right_toggled));
275 audition_right_dry_button.toggled.connect (slot (*this, &CrossfadeEditor::audition_right_dry_toggled));
276 audition_left_button.toggled.connect (slot (*this, &CrossfadeEditor::audition_left_toggled));
277 audition_left_dry_button.toggled.connect (slot (*this, &CrossfadeEditor::audition_left_dry_toggled));
279 action_box.set_border_width (7);
280 action_box.set_spacing (5);
281 action_box.set_homogeneous (false);
282 action_box.pack_end (cancel_button, false, false);
283 action_box.pack_end (ok_button, false, false);
284 action_box.pack_end (revert_button, false, false);
285 action_box.pack_end (clear_button, false, false);
287 Frame* edit_frame = manage (new Frame (_("Edit")));
288 edit_frame->set_name (X_("CrossfadeEditFrame"));
289 edit_frame->add (action_box);
291 Gtk::HBox* action_center_box = manage (new HBox);
292 action_center_box->pack_start (*edit_frame, true, false);
294 roll_box.pack_start (preroll_button, false, false);
295 roll_box.pack_start (postroll_button, false, false);
297 Gtk::HBox* rcenter_box = manage (new HBox);
298 rcenter_box->pack_start (roll_box, true, false);
300 VBox* vpacker2 = manage (new (VBox));
302 vpacker2->set_border_width (12);
303 vpacker2->set_spacing (7);
304 vpacker2->pack_start (*acbox, false, false);
305 vpacker2->pack_start (*rcenter_box, false, false);
306 vpacker2->pack_start (*action_center_box, false, false);
308 curve_button_box.set_spacing (7);
309 curve_button_box.pack_start (fade_out_table, false, false, 12);
310 curve_button_box.pack_start (*vpacker2, false, false, 12);
311 curve_button_box.pack_start (fade_in_table, false, false, 12);
313 vpacker.set_border_width (12);
314 vpacker.set_spacing (5);
315 vpacker.pack_start (*canvas_frame, true, true);
316 vpacker.pack_start (curve_button_box, false, false);
318 /* button to allow hackers to check the actual curve values */
320 // Button* foobut = manage (new Button ("dump"));
321 // foobut-.signal_clicked().connect (slot (*this, &CrossfadeEditor::dump));
322 // vpacker.pack_start (*foobut, false, false);
325 set (xfade.fade_in(), In);
328 set (xfade.fade_out(), Out);
330 curve_select_clicked (In);
332 xfade.StateChanged.connect (slot (*this, &CrossfadeEditor::xfade_changed));
334 session.AuditionActive.connect (slot (*this, &CrossfadeEditor::audition_state_changed));
337 CrossfadeEditor::~CrossfadeEditor()
339 /* most objects will be destroyed when the toplevel window is. */
341 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
345 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
351 CrossfadeEditor::dump ()
353 for (AutomationList::iterator i = fade[Out].normative_curve.begin(); i != fade[Out].normative_curve.end(); ++i) {
354 cerr << (*i)->when << ' ' << (*i)->value << endl;
359 CrossfadeEditor::audition_state_changed (bool yn)
361 ENSURE_GUI_THREAD (bind (slot (*this, &CrossfadeEditor::audition_state_changed), yn));
364 audition_both_button.set_active (false);
365 audition_left_button.set_active (false);
366 audition_right_button.set_active (false);
367 audition_left_dry_button.set_active (false);
368 audition_right_dry_button.set_active (false);
373 CrossfadeEditor::set (const ARDOUR::Curve& curve, WhichFade which)
376 ARDOUR::Curve::const_iterator the_end;
378 for (list<Point*>::iterator i = fade[which].points.begin(); i != fade[which].points.end(); ++i) {
382 fade[which].points.clear ();
383 fade[which].gain_curve.clear ();
384 fade[which].normative_curve.clear ();
390 the_end = curve.const_end();
393 firstx = (*curve.const_begin())->when;
394 endx = (*the_end)->when;
396 for (ARDOUR::Curve::const_iterator i = curve.const_begin(); i != curve.const_end(); ++i) {
398 double xfract = ((*i)->when - firstx) / (endx - firstx);
399 double yfract = ((*i)->value - miny) / (maxy - miny);
401 Point* p = make_point ();
403 p->move_to (x_coordinate (xfract), y_coordinate (yfract),
406 fade[which].points.push_back (p);
409 /* no need to sort because curve is already time-ordered */
413 swap (which, current);
415 swap (which, current);
419 CrossfadeEditor::_canvas_event (GtkCanvasItem* item, GdkEvent* event, gpointer data)
421 CrossfadeEditor* ed = static_cast<CrossfadeEditor*> (data);
422 return ed->canvas_event (item, event);
426 CrossfadeEditor::canvas_event (GtkCanvasItem* item, GdkEvent* event)
428 switch (event->type) {
429 case GDK_BUTTON_PRESS:
430 add_control_point ((event->button.x - canvas_border)/effective_width(),
431 1.0 - ((event->button.y - canvas_border)/effective_height()));
440 CrossfadeEditor::Point::~Point()
442 gtk_object_destroy (GTK_OBJECT(box));
445 CrossfadeEditor::Point*
446 CrossfadeEditor::make_point ()
448 Point* p = new Point;
450 p->box = gtk_canvas_item_new (gtk_canvas_root (GTK_CANVAS(_canvas)),
451 gtk_canvas_simplerect_get_type(),
452 "fill", (gboolean) TRUE,
453 "fill_color_rgba", color_map[cCrossfadeEditorPointFill],
454 "outline_color_rgba", color_map[cCrossfadeEditorPointOutline],
455 "outline_pixels", (gint) 1,
458 p->curve = fade[current].line;
460 gtk_object_set_data (GTK_OBJECT(p->box), "point", p);
461 gtk_signal_connect (GTK_OBJECT(p->box), "event",
462 (GtkSignalFunc) _point_event,
469 CrossfadeEditor::add_control_point (double x, double y)
473 /* enforce end point x location */
475 if (fade[current].points.empty()) {
477 } else if (fade[current].points.size() == 1) {
481 Point* p = make_point ();
483 p->move_to (x_coordinate (x), y_coordinate (y), x, y);
485 fade[current].points.push_back (p);
486 fade[current].points.sort (cmp);
492 CrossfadeEditor::Point::move_to (double nx, double ny, double xfract, double yfract)
494 const double half_size = rint(size/2.0);
495 double x1 = nx - half_size;
496 double x2 = nx + half_size;
498 gtk_canvas_item_set (box,
501 "y1", ny - half_size,
502 "y2", ny + half_size,
509 CrossfadeEditor::canvas_allocation (GtkAllocation *alloc)
512 gtk_canvas_item_set (toplevel,
515 "x2", (double) _canvas->allocation.width + canvas_border,
516 "y2", (double) _canvas->allocation.height + canvas_border,
520 gtk_canvas_set_scroll_region (GTK_CANVAS(_canvas), 0.0, 0.0,
521 _canvas->allocation.width,
522 _canvas->allocation.height);
524 Point* end = make_point ();
527 if (fade[In].points.size() > 1) {
528 Point* old_end = fade[In].points.back();
529 fade[In].points.pop_back ();
530 end->move_to (x_coordinate (old_end->x),
531 y_coordinate (old_end->y),
532 old_end->x, old_end->y);
537 end->move_to (x_coordinate (x), y_coordinate (y), x, y);
541 fade[In].points.push_back (end);
542 fade[In].points.sort (cmp);
544 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
545 (*i)->move_to (x_coordinate((*i)->x), y_coordinate((*i)->y),
551 if (fade[Out].points.size() > 1) {
552 Point* old_end = fade[Out].points.back();
553 fade[Out].points.pop_back ();
554 end->move_to (x_coordinate (old_end->x),
555 y_coordinate (old_end->y),
556 old_end->x, old_end->y);
561 end->move_to (x_coordinate (x), y_coordinate (y), x, y);
565 fade[Out].points.push_back (end);
566 fade[Out].points.sort (cmp);
568 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
569 (*i)->move_to (x_coordinate ((*i)->x),
570 y_coordinate ((*i)->y),
574 WhichFade old_current = current;
579 current = old_current;
581 double spu = xfade.length() / (double) effective_width();
583 if (fade[In].waves.empty()) {
584 make_waves (xfade.in(), In);
587 if (fade[Out].waves.empty()) {
588 make_waves (xfade.out(), Out);
592 vector<GtkCanvasItem*>::iterator i;
595 ht = _canvas->allocation.height / xfade.in().n_channels();
597 for (n = 0, i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i, ++n) {
602 gtk_canvas_item_set ((*i),
605 "samples_per_unit", spu,
609 ht = _canvas->allocation.height / xfade.out().n_channels();
611 for (n = 0, i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i, ++n) {
616 gtk_canvas_item_set ((*i),
619 "samples_per_unit", spu,
626 CrossfadeEditor::_point_event (GtkCanvasItem* item, GdkEvent* event, gpointer data)
628 CrossfadeEditor* ed = static_cast<CrossfadeEditor*> (data);
629 return ed->point_event (item, event);
633 CrossfadeEditor::point_event (GtkCanvasItem* item, GdkEvent* event)
635 Point* point = static_cast<Point*> (gtk_object_get_data (GTK_OBJECT (item), "point"));
637 if (point->curve != fade[current].line) {
641 switch (event->type) {
642 case GDK_BUTTON_PRESS:
643 point_grabbed = true;
645 case GDK_BUTTON_RELEASE:
646 point_grabbed = false;
648 if (Keyboard::is_delete_event (&event->button)) {
649 fade[current].points.remove (point);
656 case GDK_MOTION_NOTIFY:
660 /* can't drag first or last points horizontally */
662 if (point == fade[current].points.front() || point == fade[current].points.back()) {
665 new_x = (event->motion.x - canvas_border)/effective_width();
668 new_y = 1.0 - ((event->motion.y - canvas_border)/effective_height());
669 point->move_to (x_coordinate (new_x), y_coordinate (new_y),
681 CrossfadeEditor::_curve_event (GtkCanvasItem* item, GdkEvent* event, gpointer data)
683 CrossfadeEditor* ed = static_cast<CrossfadeEditor*> (data);
684 return ed->curve_event (item, event);
688 CrossfadeEditor::curve_event (GtkCanvasItem* item, GdkEvent* event)
690 /* treat it like a toplevel event */
692 return canvas_event (item, event);
696 CrossfadeEditor::xfade_changed (Change ignored)
698 set (xfade.fade_in(), In);
699 set (xfade.fade_out(), Out);
703 CrossfadeEditor::redraw ()
705 if (_canvas->allocation.width < 2) {
709 jack_nframes_t len = xfade.length ();
711 fade[current].normative_curve.clear ();
712 fade[current].gain_curve.clear ();
714 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
715 fade[current].normative_curve.add ((*i)->x, (*i)->y);
716 fade[current].gain_curve.add (((*i)->x * len), (*i)->y);
719 size_t npoints = (size_t) effective_width();
722 fade[current].normative_curve.get_vector (0, 1.0, vec, npoints);
724 GtkCanvasPoints* pts = get_canvas_points ("xfade edit1", npoints);
725 GtkCanvasPoints* spts = get_canvas_points ("xfade edit2", npoints + 3);
727 /* the shade coordinates *MUST* be in anti-clockwise order.
734 spts->coords[0] = canvas_border;
735 spts->coords[1] = effective_height() + canvas_border;
739 spts->coords[2] = effective_width() + canvas_border;
740 spts->coords[3] = effective_height() + canvas_border;
744 spts->coords[4] = effective_width() + canvas_border;
745 spts->coords[5] = canvas_border;
752 spts->coords[0] = canvas_border;
753 spts->coords[1] = canvas_border;
757 spts->coords[2] = canvas_border;
758 spts->coords[3] = effective_height() + canvas_border;
762 spts->coords[4] = effective_width() + canvas_border;
763 spts->coords[5] = effective_height() + canvas_border;
767 size_t last_spt = ((npoints + 3) * 2) - 2;
769 for (size_t i = 0; i < npoints; ++i) {
773 pts->coords[i*2] = canvas_border + i;
774 pts->coords[(i*2)+1] = y_coordinate (y);
776 spts->coords[last_spt - (i*2)] = canvas_border + i;
777 spts->coords[last_spt - (i*2) + 1] = pts->coords[(i*2)+1];
780 gtk_canvas_item_set (fade[current].line, "points", pts, NULL);
781 gtk_canvas_item_set (fade[current].shading, "points", spts, NULL);
783 gtk_canvas_points_unref (pts);
784 gtk_canvas_points_unref (spts);
786 for (vector<GtkCanvasItem*>::iterator i = fade[current].waves.begin(); i != fade[current].waves.end(); ++i) {
787 gtk_canvas_item_set ((*i), "gain_src", &fade[current].gain_curve, NULL);
792 CrossfadeEditor::apply_preset (Preset *preset)
794 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
798 fade[current].points.clear ();
800 for (Preset::iterator i = preset->begin(); i != preset->end(); ++i) {
801 Point* p = make_point ();
802 p->move_to (x_coordinate ((*i).x), y_coordinate ((*i).y),
804 fade[current].points.push_back (p);
811 CrossfadeEditor::apply ()
817 CrossfadeEditor::_apply_to (Crossfade* xf)
819 ARDOUR::Curve& in (xf->fade_in());
820 ARDOUR::Curve& out (xf->fade_out());
825 ARDOUR::Curve::const_iterator the_end = in.const_end();
828 double firstx = (*in.begin())->when;
829 double endx = (*the_end)->when;
830 double miny = in.get_min_y ();
831 double maxy = in.get_max_y ();
836 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
838 double when = firstx + ((*i)->x * (endx - firstx));
839 double value = (*i)->y; // miny + ((*i)->y * (maxy - miny));
840 in.add (when, value);
845 the_end = out.const_end();
848 firstx = (*out.begin())->when;
849 endx = (*the_end)->when;
850 miny = out.get_min_y ();
851 maxy = out.get_max_y ();
856 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
858 double when = firstx + ((*i)->x * (endx - firstx));
859 double value = (*i)->y; // miny + ((*i)->y * (maxy - miny));
860 out.add (when, value);
868 CrossfadeEditor::setup (Crossfade* xfade)
871 xfade->set_active (true);
872 xfade->fade_in().solve ();
873 xfade->fade_out().solve ();
877 CrossfadeEditor::clear ()
879 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
883 fade[current].points.clear ();
889 CrossfadeEditor::reset ()
891 set (xfade.fade_in(), In);
892 set (xfade.fade_out(), Out);
896 CrossfadeEditor::build_presets ()
900 fade_in_presets = new Presets;
901 fade_out_presets = new Presets;
905 p = new Preset (hiin_xpm);
906 p->push_back (PresetPoint (0, 0));
907 p->push_back (PresetPoint (0.0207373, 0.197222));
908 p->push_back (PresetPoint (0.0645161, 0.525));
909 p->push_back (PresetPoint (0.152074, 0.802778));
910 p->push_back (PresetPoint (0.276498, 0.919444));
911 p->push_back (PresetPoint (0.481567, 0.980556));
912 p->push_back (PresetPoint (0.767281, 1));
913 p->push_back (PresetPoint (1, 1));
914 fade_in_presets->push_back (p);
916 p = new Preset (loin_xpm);
917 p->push_back (PresetPoint (0, 0));
918 p->push_back (PresetPoint (0.389401, 0.0333333));
919 p->push_back (PresetPoint (0.629032, 0.0861111));
920 p->push_back (PresetPoint (0.829493, 0.233333));
921 p->push_back (PresetPoint (0.9447, 0.483333));
922 p->push_back (PresetPoint (0.976959, 0.697222));
923 p->push_back (PresetPoint (1, 1));
924 fade_in_presets->push_back (p);
926 p = new Preset (regin_xpm);
927 p->push_back (PresetPoint (0, 0));
928 p->push_back (PresetPoint (0.0737327, 0.308333));
929 p->push_back (PresetPoint (0.246544, 0.658333));
930 p->push_back (PresetPoint (0.470046, 0.886111));
931 p->push_back (PresetPoint (0.652074, 0.972222));
932 p->push_back (PresetPoint (0.771889, 0.988889));
933 p->push_back (PresetPoint (1, 1));
934 fade_in_presets->push_back (p);
936 p = new Preset (regin2_xpm);
937 p->push_back (PresetPoint (0, 0));
938 p->push_back (PresetPoint (0.304147, 0.0694444));
939 p->push_back (PresetPoint (0.529954, 0.152778));
940 p->push_back (PresetPoint (0.725806, 0.333333));
941 p->push_back (PresetPoint (0.847926, 0.558333));
942 p->push_back (PresetPoint (0.919355, 0.730556));
943 p->push_back (PresetPoint (1, 1));
944 fade_in_presets->push_back (p);
946 p = new Preset (linin_xpm);
947 p->push_back (PresetPoint (0, 0));
948 p->push_back (PresetPoint (1, 1));
949 fade_in_presets->push_back (p);
953 p = new Preset (hiout_xpm);
954 p->push_back (PresetPoint (0, 1));
955 p->push_back (PresetPoint (0.305556, 1));
956 p->push_back (PresetPoint (0.548611, 0.991736));
957 p->push_back (PresetPoint (0.759259, 0.931129));
958 p->push_back (PresetPoint (0.918981, 0.68595));
959 p->push_back (PresetPoint (0.976852, 0.22865));
960 p->push_back (PresetPoint (1, 0));
961 fade_out_presets->push_back (p);
963 p = new Preset (regout_xpm);
964 p->push_back (PresetPoint (0, 1));
965 p->push_back (PresetPoint (0.228111, 0.988889));
966 p->push_back (PresetPoint (0.347926, 0.972222));
967 p->push_back (PresetPoint (0.529954, 0.886111));
968 p->push_back (PresetPoint (0.753456, 0.658333));
969 p->push_back (PresetPoint (0.9262673, 0.308333));
970 p->push_back (PresetPoint (1, 0));
971 fade_out_presets->push_back (p);
973 p = new Preset (loout_xpm);
974 p->push_back (PresetPoint (0, 1));
975 p->push_back (PresetPoint (0.023041, 0.697222));
976 p->push_back (PresetPoint (0.0553, 0.483333));
977 p->push_back (PresetPoint (0.170507, 0.233333));
978 p->push_back (PresetPoint (0.370968, 0.0861111));
979 p->push_back (PresetPoint (0.610599, 0.0333333));
980 p->push_back (PresetPoint (1, 0));
981 fade_out_presets->push_back (p);
983 p = new Preset (regout2_xpm);
984 p->push_back (PresetPoint (0, 1));
985 p->push_back (PresetPoint (0.080645, 0.730556));
986 p->push_back (PresetPoint (0.277778, 0.289256));
987 p->push_back (PresetPoint (0.470046, 0.152778));
988 p->push_back (PresetPoint (0.695853, 0.0694444));
989 p->push_back (PresetPoint (1, 0));
990 fade_out_presets->push_back (p);
992 p = new Preset (linout_xpm);
993 p->push_back (PresetPoint (0, 1));
994 p->push_back (PresetPoint (1, 0));
995 fade_out_presets->push_back (p);
999 CrossfadeEditor::curve_select_clicked (WhichFade wf)
1005 for (vector<GtkCanvasItem*>::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) {
1006 gtk_canvas_item_set ((*i), "wave_color", color_map[cSelectedCrossfadeEditorWave], NULL);
1009 for (vector<GtkCanvasItem*>::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) {
1010 gtk_canvas_item_set ((*i), "wave_color", color_map[cCrossfadeEditorWave], NULL);
1013 gtk_canvas_item_set (fade[In].line, "fill_color_rgba", color_map[cSelectedCrossfadeEditorLine], NULL);
1014 gtk_canvas_item_set (fade[Out].line, "fill_color_rgba", color_map[cCrossfadeEditorLine], NULL);
1015 gtk_canvas_item_hide (fade[Out].shading);
1016 gtk_canvas_item_show (fade[In].shading);
1018 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
1019 gtk_canvas_item_hide ((*i)->box);
1022 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
1023 gtk_canvas_item_show ((*i)->box);
1026 for (vector<Button*>::iterator i = fade_out_buttons.begin(); i != fade_out_buttons.end(); ++i) {
1027 (*i)->set_sensitive (false);
1030 for (vector<Button*>::iterator i = fade_in_buttons.begin(); i != fade_in_buttons.end(); ++i) {
1031 (*i)->set_sensitive (true);
1036 for (vector<GtkCanvasItem*>::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) {
1037 gtk_canvas_item_set ((*i), "wave_color", color_map[cCrossfadeEditorWave], NULL);
1040 for (vector<GtkCanvasItem*>::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) {
1041 gtk_canvas_item_set ((*i), "wave_color", color_map[cSelectedCrossfadeEditorWave], NULL);
1044 gtk_canvas_item_set (fade[Out].line, "fill_color_rgba", color_map[cSelectedCrossfadeEditorLine], NULL);
1045 gtk_canvas_item_set (fade[In].line, "fill_color_rgba", color_map[cCrossfadeEditorLine], NULL);
1046 gtk_canvas_item_hide (fade[In].shading);
1047 gtk_canvas_item_show (fade[Out].shading);
1049 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
1050 gtk_canvas_item_hide ((*i)->box);
1053 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
1054 gtk_canvas_item_show ((*i)->box);
1057 for (vector<Button*>::iterator i = fade_out_buttons.begin(); i != fade_out_buttons.end(); ++i) {
1058 (*i)->set_sensitive (true);
1061 for (vector<Button*>::iterator i = fade_in_buttons.begin(); i != fade_in_buttons.end(); ++i) {
1062 (*i)->set_sensitive (false);
1069 CrossfadeEditor::x_coordinate (double& xfract) const
1071 xfract = min (1.0, xfract);
1072 xfract = max (0.0, xfract);
1074 return canvas_border + (xfract * effective_width());
1078 CrossfadeEditor::y_coordinate (double& yfract) const
1080 yfract = min (1.0, yfract);
1081 yfract = max (0.0, yfract);
1083 return (_canvas->allocation.height - (canvas_border)) - (yfract * effective_height());
1087 CrossfadeEditor::make_waves (AudioRegion& region, WhichFade which)
1090 uint32_t nchans = region.n_channels();
1095 color = color_map[cSelectedCrossfadeEditorWave];
1097 color = color_map[cCrossfadeEditorWave];
1100 ht = _canvas->allocation.height / (double) nchans;
1101 spu = xfade.length() / (double) effective_width();
1103 for (uint32_t n = 0; n < nchans; ++n) {
1105 gdouble yoff = n * ht;
1107 if (region.source(n).peaks_ready (bind (slot (*this, &CrossfadeEditor::peaks_ready), ®ion, which))) {
1109 GtkCanvasItem *wave = gtk_canvas_item_new (gtk_canvas_root (GTK_CANVAS(_canvas)),
1110 gtk_canvas_waveview_get_type (),
1111 "data_src", (gpointer) ®ion,
1112 "cache_updater", (gboolean) TRUE,
1113 "cache", gtk_canvas_waveview_cache_new (),
1114 "channel", (guint32) n,
1115 "length_function", (gpointer) region_length_from_c,
1116 "sourcefile_length_function", (gpointer) sourcefile_length_from_c,
1117 "peak_function", (gpointer) region_read_peaks_from_c,
1118 "gain_function", (gpointer) curve_get_vector_from_c,
1119 "gain_src", &fade[which].gain_curve,
1120 "x", (double) canvas_border,
1123 "samples_per_unit", spu,
1124 "amplitude_above_axis", 2.0,
1125 "wave_color", color,
1128 gtk_canvas_item_lower_to_bottom (wave);
1129 fade[which].waves.push_back (wave);
1133 gtk_canvas_item_lower_to_bottom (toplevel);
1137 CrossfadeEditor::peaks_ready (AudioRegion* r, WhichFade which)
1139 /* this should never be called, because the peak files for an xfade
1140 will be ready by the time we want them. but our API forces us
1141 to provide this, so ..
1144 make_waves (*r, which);
1148 CrossfadeEditor::audition_both ()
1150 AudioPlaylist& pl (session.the_auditioner().prepare_playlist());
1151 jack_nframes_t preroll;
1152 jack_nframes_t postroll;
1153 jack_nframes_t length;
1154 jack_nframes_t left_start_offset;
1155 jack_nframes_t right_length;
1156 jack_nframes_t left_length;
1158 if (preroll_button.get_active()) {
1159 preroll = ARDOUR_UI::instance()->preroll_clock.current_duration ();
1164 if (postroll_button.get_active()) {
1165 postroll = ARDOUR_UI::instance()->postroll_clock.current_duration ();
1170 if ((left_start_offset = xfade.out().length() - xfade.length()) >= preroll) {
1171 left_start_offset -= preroll;
1176 if ((left_length = xfade.length()) < xfade.out().length() - left_start_offset) {
1180 right_length = xfade.length();
1182 if (xfade.in().length() - right_length < postroll) {
1183 right_length += postroll;
1186 AudioRegion* left = new AudioRegion (xfade.out(), left_start_offset, left_length, "xfade out",
1187 0, Region::DefaultFlags, false);
1188 AudioRegion* right = new AudioRegion (xfade.in(), 0, right_length, "xfade in",
1189 0, Region::DefaultFlags, false);
1191 pl.add_region (*left, 0);
1192 pl.add_region (*right, 1+preroll);
1194 /* there is only one ... */
1196 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1198 session.audition_playlist ();
1202 CrossfadeEditor::audition_left_dry ()
1204 AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade left",
1205 0, Region::DefaultFlags, false);
1207 session.audition_region (*left);
1211 CrossfadeEditor::audition_left ()
1213 AudioPlaylist& pl (session.the_auditioner().prepare_playlist());
1215 AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade left",
1216 0, Region::DefaultFlags, false);
1217 AudioRegion* right = new AudioRegion (xfade.in(), 0, xfade.length(), "xfade in",
1218 0, Region::DefaultFlags, false);
1220 pl.add_region (*left, 0);
1221 pl.add_region (*right, 1);
1223 right->set_muted (true);
1225 /* there is only one ... */
1227 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1229 session.audition_playlist ();
1231 /* memory leak for regions */
1235 CrossfadeEditor::audition_right_dry ()
1237 AudioRegion* right = new AudioRegion (xfade.in(), 0, xfade.length(), "xfade in",
1238 0, Region::DefaultFlags, false);
1239 session.audition_region (*right);
1243 CrossfadeEditor::audition_right ()
1245 AudioPlaylist& pl (session.the_auditioner().prepare_playlist());
1247 AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade out",
1248 0, Region::DefaultFlags, false);
1249 AudioRegion* right = new AudioRegion (xfade.out(), 0, xfade.length(), "xfade out",
1250 0, Region::DefaultFlags, false);
1252 pl.add_region (*left, 0);
1253 pl.add_region (*right, 1);
1255 left->set_muted (true);
1257 /* there is only one ... */
1259 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1261 session.audition_playlist ();
1265 CrossfadeEditor::cancel_audition ()
1267 session.cancel_audition ();
1271 CrossfadeEditor::audition_toggled ()
1275 if ((x = audition_both_button.get_active ()) != session.is_auditioning()) {
1286 CrossfadeEditor::audition_right_toggled ()
1290 if ((x = audition_right_button.get_active ()) != session.is_auditioning()) {
1301 CrossfadeEditor::audition_right_dry_toggled ()
1305 if ((x = audition_right_dry_button.get_active ()) != session.is_auditioning()) {
1308 audition_right_dry ();
1316 CrossfadeEditor::audition_left_toggled ()
1320 if ((x = audition_left_button.get_active ()) != session.is_auditioning()) {
1331 CrossfadeEditor::audition_left_dry_toggled ()
1335 if ((x = audition_left_dry_button.get_active ()) != session.is_auditioning()) {
1338 audition_left_dry ();