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 <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 RadioButtonGroup sel_but_group = select_in_button.get_group();
105 select_out_button.set_group (sel_but_group);
106 select_out_button.set_mode (false);
107 select_in_button.set_mode (false);
109 if (fade_in_presets == 0) {
113 point_grabbed = false;
116 _canvas = gnome_canvas_new_aa ();
118 canvas = Glib::wrap (_canvas);
119 canvas->signal_size_allocate().connect (mem_fun(*this, &CrossfadeEditor::canvas_allocation));
120 canvas->set_size_request (425, 200);
122 toplevel = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS(_canvas)),
123 gnome_canvas_simplerect_get_type(),
128 "fill", (gboolean) TRUE,
129 "fill_color_rgba", (guint32) color_map[cCrossfadeEditorBase],
133 gtk_signal_connect (GTK_OBJECT(toplevel),
135 (GtkSignalFunc) _canvas_event,
138 fade[Out].line = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS(_canvas)),
139 gnome_canvas_line_get_type (),
140 "width_pixels", (guint) 1,
141 "fill_color_rgba", color_map[cCrossfadeEditorLine],
144 fade[Out].shading = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS(_canvas)),
145 gnome_canvas_polygon_get_type(),
146 "fill_color_rgba", color_map[cCrossfadeEditorLineShading],
149 fade[In].line = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS(_canvas)),
150 gnome_canvas_line_get_type (),
151 "width_pixels", (guint) 1,
152 "fill_color_rgba", color_map[cCrossfadeEditorLine],
155 fade[In].shading = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS(_canvas)),
156 gnome_canvas_polygon_get_type(),
157 "fill_color_rgba", color_map[cCrossfadeEditorLineShading],
160 gtk_signal_connect (GTK_OBJECT(fade[In].shading),
162 (GtkSignalFunc) _canvas_event,
166 gtk_signal_connect (GTK_OBJECT(fade[Out].shading),
168 (GtkSignalFunc) _canvas_event,
171 gtk_signal_connect (GTK_OBJECT(fade[In].line),
173 (GtkSignalFunc) _curve_event,
176 gtk_signal_connect (GTK_OBJECT(fade[Out].line),
178 (GtkSignalFunc) _curve_event,
182 select_in_button.set_name (X_("CrossfadeEditCurveButton"));
183 select_out_button.set_name (X_("CrossfadeEditCurveButton"));
185 select_in_button.signal_clicked().connect (bind (mem_fun (*this, &CrossfadeEditor::curve_select_clicked), In));
186 select_out_button.signal_clicked().connect (bind (mem_fun (*this, &CrossfadeEditor::curve_select_clicked), Out));
188 HBox* acbox = manage (new HBox);
190 audition_box.set_border_width (7);
191 audition_box.set_spacing (5);
192 audition_box.set_homogeneous (false);
193 audition_box.pack_start (audition_left_dry_button, false, false);
194 audition_box.pack_start (audition_left_button, false, false);
195 audition_box.pack_start (audition_both_button, false, false);
196 audition_box.pack_start (audition_right_button, false, false);
197 audition_box.pack_start (audition_right_dry_button, false, false);
199 Frame* audition_frame = manage (new Frame (_("Audition")));
201 audition_frame->set_name (X_("CrossfadeEditFrame"));
202 audition_frame->add (audition_box);
204 acbox->pack_start (*audition_frame, true, false);
206 Frame* canvas_frame = manage (new Frame);
207 canvas_frame->add (*canvas);
208 canvas_frame->set_shadow_type (Gtk::SHADOW_IN);
210 fade_in_table.attach (select_in_button, 0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND);
211 fade_out_table.attach (select_out_button, 0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND);
221 for (list<Preset*>::iterator i = fade_in_presets->begin(); i != fade_in_presets->end(); ++i) {
223 pxmap = manage (new Image (Gdk::Pixbuf::create_from_xpm_data((*i)->xpm)));
224 pbutton = manage (new Button);
225 pbutton->add (*pxmap);
226 pbutton->set_name ("CrossfadeEditButton");
227 pbutton->signal_clicked().connect (bind (mem_fun(*this, &CrossfadeEditor::apply_preset), *i));
228 fade_in_table.attach (*pbutton, col, col+1, row, row+1);
229 fade_in_buttons.push_back (pbutton);
242 for (list<Preset*>::iterator i = fade_out_presets->begin(); i != fade_out_presets->end(); ++i) {
244 pxmap = manage (new Image (Gdk::Pixbuf::create_from_xpm_data((*i)->xpm)));
245 pbutton = manage (new Button);
246 pbutton->add (*pxmap);
247 pbutton->set_name ("CrossfadeEditButton");
248 pbutton->signal_clicked().connect (bind (mem_fun(*this, &CrossfadeEditor::apply_preset), *i));
249 fade_out_table.attach (*pbutton, col, col+1, row, row+1);
250 fade_out_buttons.push_back (pbutton);
260 clear_button.set_name ("CrossfadeEditButton");
261 revert_button.set_name ("CrossfadeEditButton");
262 ok_button.set_name ("CrossfadeEditButton");
263 cancel_button.set_name ("CrossfadeEditButton");
264 preroll_button.set_name ("CrossfadeEditButton");
265 postroll_button.set_name ("CrossfadeEditButton");
266 audition_both_button.set_name ("CrossfadeEditAuditionButton");
267 audition_left_dry_button.set_name ("CrossfadeEditAuditionButton");
268 audition_left_button.set_name ("CrossfadeEditAuditionButton");
269 audition_right_dry_button.set_name ("CrossfadeEditAuditionButton");
270 audition_right_button.set_name ("CrossfadeEditAuditionButton");
272 clear_button.signal_clicked().connect (mem_fun(*this, &CrossfadeEditor::clear));
273 revert_button.signal_clicked().connect (mem_fun(*this, &CrossfadeEditor::reset));
274 audition_both_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_toggled));
275 audition_right_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_right_toggled));
276 audition_right_dry_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_right_dry_toggled));
277 audition_left_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_left_toggled));
278 audition_left_dry_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_left_dry_toggled));
280 action_box.set_border_width (7);
281 action_box.set_spacing (5);
282 action_box.set_homogeneous (false);
283 action_box.pack_end (cancel_button, false, false);
284 action_box.pack_end (ok_button, false, false);
285 action_box.pack_end (revert_button, false, false);
286 action_box.pack_end (clear_button, false, false);
288 Frame* edit_frame = manage (new Frame (_("Edit")));
289 edit_frame->set_name (X_("CrossfadeEditFrame"));
290 edit_frame->add (action_box);
292 Gtk::HBox* action_center_box = manage (new HBox);
293 action_center_box->pack_start (*edit_frame, true, false);
295 roll_box.pack_start (preroll_button, false, false);
296 roll_box.pack_start (postroll_button, false, false);
298 Gtk::HBox* rcenter_box = manage (new HBox);
299 rcenter_box->pack_start (roll_box, true, false);
301 VBox* vpacker2 = manage (new (VBox));
303 vpacker2->set_border_width (12);
304 vpacker2->set_spacing (7);
305 vpacker2->pack_start (*acbox, false, false);
306 vpacker2->pack_start (*rcenter_box, false, false);
307 vpacker2->pack_start (*action_center_box, false, false);
309 curve_button_box.set_spacing (7);
310 curve_button_box.pack_start (fade_out_table, false, false, 12);
311 curve_button_box.pack_start (*vpacker2, false, false, 12);
312 curve_button_box.pack_start (fade_in_table, false, false, 12);
314 vpacker.set_border_width (12);
315 vpacker.set_spacing (5);
316 vpacker.pack_start (*canvas_frame, true, true);
317 vpacker.pack_start (curve_button_box, false, false);
319 /* button to allow hackers to check the actual curve values */
321 // Button* foobut = manage (new Button ("dump"));
322 // foobut-.signal_clicked().connect (mem_fun(*this, &CrossfadeEditor::dump));
323 // vpacker.pack_start (*foobut, false, false);
326 set (xfade.fade_in(), In);
329 set (xfade.fade_out(), Out);
331 curve_select_clicked (In);
333 xfade.StateChanged.connect (mem_fun(*this, &CrossfadeEditor::xfade_changed));
335 session.AuditionActive.connect (mem_fun(*this, &CrossfadeEditor::audition_state_changed));
338 CrossfadeEditor::~CrossfadeEditor()
340 /* most objects will be destroyed when the toplevel window is. */
342 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
346 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
352 CrossfadeEditor::dump ()
354 for (AutomationList::iterator i = fade[Out].normative_curve.begin(); i != fade[Out].normative_curve.end(); ++i) {
355 cerr << (*i)->when << ' ' << (*i)->value << endl;
360 CrossfadeEditor::audition_state_changed (bool yn)
362 ENSURE_GUI_THREAD (bind (mem_fun(*this, &CrossfadeEditor::audition_state_changed), yn));
365 audition_both_button.set_active (false);
366 audition_left_button.set_active (false);
367 audition_right_button.set_active (false);
368 audition_left_dry_button.set_active (false);
369 audition_right_dry_button.set_active (false);
374 CrossfadeEditor::set (const ARDOUR::Curve& curve, WhichFade which)
377 ARDOUR::Curve::const_iterator the_end;
379 for (list<Point*>::iterator i = fade[which].points.begin(); i != fade[which].points.end(); ++i) {
383 fade[which].points.clear ();
384 fade[which].gain_curve.clear ();
385 fade[which].normative_curve.clear ();
391 the_end = curve.const_end();
394 firstx = (*curve.const_begin())->when;
395 endx = (*the_end)->when;
397 for (ARDOUR::Curve::const_iterator i = curve.const_begin(); i != curve.const_end(); ++i) {
399 double xfract = ((*i)->when - firstx) / (endx - firstx);
400 double yfract = ((*i)->value - miny) / (maxy - miny);
402 Point* p = make_point ();
404 p->move_to (x_coordinate (xfract), y_coordinate (yfract),
407 fade[which].points.push_back (p);
410 /* no need to sort because curve is already time-ordered */
414 swap (which, current);
416 swap (which, current);
420 CrossfadeEditor::_canvas_event (GnomeCanvasItem* item, GdkEvent* event, gpointer data)
422 CrossfadeEditor* ed = static_cast<CrossfadeEditor*> (data);
423 return ed->canvas_event (item, event);
427 CrossfadeEditor::canvas_event (GnomeCanvasItem* item, GdkEvent* event)
429 switch (event->type) {
430 case GDK_BUTTON_PRESS:
431 add_control_point ((event->button.x - canvas_border)/effective_width(),
432 1.0 - ((event->button.y - canvas_border)/effective_height()));
441 CrossfadeEditor::Point::~Point()
443 gtk_object_destroy (GTK_OBJECT(box));
446 CrossfadeEditor::Point*
447 CrossfadeEditor::make_point ()
449 Point* p = new Point;
451 p->box = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS(_canvas)),
452 gnome_canvas_simplerect_get_type(),
453 "fill", (gboolean) TRUE,
454 "fill_color_rgba", color_map[cCrossfadeEditorPointFill],
455 "outline_color_rgba", color_map[cCrossfadeEditorPointOutline],
456 "outline_pixels", (gint) 1,
459 p->curve = fade[current].line;
461 gtk_object_set_data (GTK_OBJECT(p->box), "point", p);
462 gtk_signal_connect (GTK_OBJECT(p->box), "event",
463 (GtkSignalFunc) _point_event,
470 CrossfadeEditor::add_control_point (double x, double y)
474 /* enforce end point x location */
476 if (fade[current].points.empty()) {
478 } else if (fade[current].points.size() == 1) {
482 Point* p = make_point ();
484 p->move_to (x_coordinate (x), y_coordinate (y), x, y);
486 fade[current].points.push_back (p);
487 fade[current].points.sort (cmp);
493 CrossfadeEditor::Point::move_to (double nx, double ny, double xfract, double yfract)
495 const double half_size = rint(size/2.0);
496 double x1 = nx - half_size;
497 double x2 = nx + half_size;
499 gnome_canvas_item_set (box,
502 "y1", ny - half_size,
503 "y2", ny + half_size,
510 CrossfadeEditor::canvas_allocation (GtkAllocation *alloc)
513 gnome_canvas_item_set (toplevel,
516 "x2", (double) _canvas->allocation.width + canvas_border,
517 "y2", (double) _canvas->allocation.height + canvas_border,
521 gnome_canvas_set_scroll_region (GNOME_CANVAS(_canvas), 0.0, 0.0,
522 _canvas->allocation.width,
523 _canvas->allocation.height);
525 Point* end = make_point ();
528 if (fade[In].points.size() > 1) {
529 Point* old_end = fade[In].points.back();
530 fade[In].points.pop_back ();
531 end->move_to (x_coordinate (old_end->x),
532 y_coordinate (old_end->y),
533 old_end->x, old_end->y);
538 end->move_to (x_coordinate (x), y_coordinate (y), x, y);
542 fade[In].points.push_back (end);
543 fade[In].points.sort (cmp);
545 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
546 (*i)->move_to (x_coordinate((*i)->x), y_coordinate((*i)->y),
552 if (fade[Out].points.size() > 1) {
553 Point* old_end = fade[Out].points.back();
554 fade[Out].points.pop_back ();
555 end->move_to (x_coordinate (old_end->x),
556 y_coordinate (old_end->y),
557 old_end->x, old_end->y);
562 end->move_to (x_coordinate (x), y_coordinate (y), x, y);
566 fade[Out].points.push_back (end);
567 fade[Out].points.sort (cmp);
569 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
570 (*i)->move_to (x_coordinate ((*i)->x),
571 y_coordinate ((*i)->y),
575 WhichFade old_current = current;
580 current = old_current;
582 double spu = xfade.length() / (double) effective_width();
584 if (fade[In].waves.empty()) {
585 make_waves (xfade.in(), In);
588 if (fade[Out].waves.empty()) {
589 make_waves (xfade.out(), Out);
593 vector<GnomeCanvasItem*>::iterator i;
596 ht = _canvas->allocation.height / xfade.in().n_channels();
598 for (n = 0, i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i, ++n) {
603 gnome_canvas_item_set ((*i),
606 "samples_per_unit", spu,
610 ht = _canvas->allocation.height / xfade.out().n_channels();
612 for (n = 0, i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i, ++n) {
617 gnome_canvas_item_set ((*i),
620 "samples_per_unit", spu,
627 CrossfadeEditor::_point_event (GnomeCanvasItem* item, GdkEvent* event, gpointer data)
629 CrossfadeEditor* ed = static_cast<CrossfadeEditor*> (data);
630 return ed->point_event (item, event);
634 CrossfadeEditor::point_event (GnomeCanvasItem* item, GdkEvent* event)
636 Point* point = static_cast<Point*> (gtk_object_get_data (GTK_OBJECT (item), "point"));
638 if (point->curve != fade[current].line) {
642 switch (event->type) {
643 case GDK_BUTTON_PRESS:
644 point_grabbed = true;
646 case GDK_BUTTON_RELEASE:
647 point_grabbed = false;
649 if (Keyboard::is_delete_event (&event->button)) {
650 fade[current].points.remove (point);
657 case GDK_MOTION_NOTIFY:
661 /* can't drag first or last points horizontally */
663 if (point == fade[current].points.front() || point == fade[current].points.back()) {
666 new_x = (event->motion.x - canvas_border)/effective_width();
669 new_y = 1.0 - ((event->motion.y - canvas_border)/effective_height());
670 point->move_to (x_coordinate (new_x), y_coordinate (new_y),
682 CrossfadeEditor::_curve_event (GnomeCanvasItem* item, GdkEvent* event, gpointer data)
684 CrossfadeEditor* ed = static_cast<CrossfadeEditor*> (data);
685 return ed->curve_event (item, event);
689 CrossfadeEditor::curve_event (GnomeCanvasItem* item, GdkEvent* event)
691 /* treat it like a toplevel event */
693 return canvas_event (item, event);
697 CrossfadeEditor::xfade_changed (Change ignored)
699 set (xfade.fade_in(), In);
700 set (xfade.fade_out(), Out);
704 CrossfadeEditor::redraw ()
706 if (_canvas->allocation.width < 2) {
710 jack_nframes_t len = xfade.length ();
712 fade[current].normative_curve.clear ();
713 fade[current].gain_curve.clear ();
715 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
716 fade[current].normative_curve.add ((*i)->x, (*i)->y);
717 fade[current].gain_curve.add (((*i)->x * len), (*i)->y);
720 size_t npoints = (size_t) effective_width();
723 fade[current].normative_curve.get_vector (0, 1.0, vec, npoints);
725 GnomeCanvasPoints* pts = get_canvas_points ("xfade edit1", npoints);
726 GnomeCanvasPoints* spts = get_canvas_points ("xfade edit2", npoints + 3);
728 /* the shade coordinates *MUST* be in anti-clockwise order.
735 spts->coords[0] = canvas_border;
736 spts->coords[1] = effective_height() + canvas_border;
740 spts->coords[2] = effective_width() + canvas_border;
741 spts->coords[3] = effective_height() + canvas_border;
745 spts->coords[4] = effective_width() + canvas_border;
746 spts->coords[5] = canvas_border;
753 spts->coords[0] = canvas_border;
754 spts->coords[1] = canvas_border;
758 spts->coords[2] = canvas_border;
759 spts->coords[3] = effective_height() + canvas_border;
763 spts->coords[4] = effective_width() + canvas_border;
764 spts->coords[5] = effective_height() + canvas_border;
768 size_t last_spt = ((npoints + 3) * 2) - 2;
770 for (size_t i = 0; i < npoints; ++i) {
774 pts->coords[i*2] = canvas_border + i;
775 pts->coords[(i*2)+1] = y_coordinate (y);
777 spts->coords[last_spt - (i*2)] = canvas_border + i;
778 spts->coords[last_spt - (i*2) + 1] = pts->coords[(i*2)+1];
781 gnome_canvas_item_set (fade[current].line, "points", pts, NULL);
782 gnome_canvas_item_set (fade[current].shading, "points", spts, NULL);
784 gnome_canvas_points_unref (pts);
785 gnome_canvas_points_unref (spts);
787 for (vector<GnomeCanvasItem*>::iterator i = fade[current].waves.begin(); i != fade[current].waves.end(); ++i) {
788 gnome_canvas_item_set ((*i), "gain_src", &fade[current].gain_curve, NULL);
793 CrossfadeEditor::apply_preset (Preset *preset)
795 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
799 fade[current].points.clear ();
801 for (Preset::iterator i = preset->begin(); i != preset->end(); ++i) {
802 Point* p = make_point ();
803 p->move_to (x_coordinate ((*i).x), y_coordinate ((*i).y),
805 fade[current].points.push_back (p);
812 CrossfadeEditor::apply ()
818 CrossfadeEditor::_apply_to (Crossfade* xf)
820 ARDOUR::Curve& in (xf->fade_in());
821 ARDOUR::Curve& out (xf->fade_out());
826 ARDOUR::Curve::const_iterator the_end = in.const_end();
829 double firstx = (*in.begin())->when;
830 double endx = (*the_end)->when;
831 double miny = in.get_min_y ();
832 double maxy = in.get_max_y ();
837 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
839 double when = firstx + ((*i)->x * (endx - firstx));
840 double value = (*i)->y; // miny + ((*i)->y * (maxy - miny));
841 in.add (when, value);
846 the_end = out.const_end();
849 firstx = (*out.begin())->when;
850 endx = (*the_end)->when;
851 miny = out.get_min_y ();
852 maxy = out.get_max_y ();
857 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
859 double when = firstx + ((*i)->x * (endx - firstx));
860 double value = (*i)->y; // miny + ((*i)->y * (maxy - miny));
861 out.add (when, value);
869 CrossfadeEditor::setup (Crossfade* xfade)
872 xfade->set_active (true);
873 xfade->fade_in().solve ();
874 xfade->fade_out().solve ();
878 CrossfadeEditor::clear ()
880 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
884 fade[current].points.clear ();
890 CrossfadeEditor::reset ()
892 set (xfade.fade_in(), In);
893 set (xfade.fade_out(), Out);
897 CrossfadeEditor::build_presets ()
901 fade_in_presets = new Presets;
902 fade_out_presets = new Presets;
906 p = new Preset (hiin_xpm);
907 p->push_back (PresetPoint (0, 0));
908 p->push_back (PresetPoint (0.0207373, 0.197222));
909 p->push_back (PresetPoint (0.0645161, 0.525));
910 p->push_back (PresetPoint (0.152074, 0.802778));
911 p->push_back (PresetPoint (0.276498, 0.919444));
912 p->push_back (PresetPoint (0.481567, 0.980556));
913 p->push_back (PresetPoint (0.767281, 1));
914 p->push_back (PresetPoint (1, 1));
915 fade_in_presets->push_back (p);
917 p = new Preset (loin_xpm);
918 p->push_back (PresetPoint (0, 0));
919 p->push_back (PresetPoint (0.389401, 0.0333333));
920 p->push_back (PresetPoint (0.629032, 0.0861111));
921 p->push_back (PresetPoint (0.829493, 0.233333));
922 p->push_back (PresetPoint (0.9447, 0.483333));
923 p->push_back (PresetPoint (0.976959, 0.697222));
924 p->push_back (PresetPoint (1, 1));
925 fade_in_presets->push_back (p);
927 p = new Preset (regin_xpm);
928 p->push_back (PresetPoint (0, 0));
929 p->push_back (PresetPoint (0.0737327, 0.308333));
930 p->push_back (PresetPoint (0.246544, 0.658333));
931 p->push_back (PresetPoint (0.470046, 0.886111));
932 p->push_back (PresetPoint (0.652074, 0.972222));
933 p->push_back (PresetPoint (0.771889, 0.988889));
934 p->push_back (PresetPoint (1, 1));
935 fade_in_presets->push_back (p);
937 p = new Preset (regin2_xpm);
938 p->push_back (PresetPoint (0, 0));
939 p->push_back (PresetPoint (0.304147, 0.0694444));
940 p->push_back (PresetPoint (0.529954, 0.152778));
941 p->push_back (PresetPoint (0.725806, 0.333333));
942 p->push_back (PresetPoint (0.847926, 0.558333));
943 p->push_back (PresetPoint (0.919355, 0.730556));
944 p->push_back (PresetPoint (1, 1));
945 fade_in_presets->push_back (p);
947 p = new Preset (linin_xpm);
948 p->push_back (PresetPoint (0, 0));
949 p->push_back (PresetPoint (1, 1));
950 fade_in_presets->push_back (p);
954 p = new Preset (hiout_xpm);
955 p->push_back (PresetPoint (0, 1));
956 p->push_back (PresetPoint (0.305556, 1));
957 p->push_back (PresetPoint (0.548611, 0.991736));
958 p->push_back (PresetPoint (0.759259, 0.931129));
959 p->push_back (PresetPoint (0.918981, 0.68595));
960 p->push_back (PresetPoint (0.976852, 0.22865));
961 p->push_back (PresetPoint (1, 0));
962 fade_out_presets->push_back (p);
964 p = new Preset (regout_xpm);
965 p->push_back (PresetPoint (0, 1));
966 p->push_back (PresetPoint (0.228111, 0.988889));
967 p->push_back (PresetPoint (0.347926, 0.972222));
968 p->push_back (PresetPoint (0.529954, 0.886111));
969 p->push_back (PresetPoint (0.753456, 0.658333));
970 p->push_back (PresetPoint (0.9262673, 0.308333));
971 p->push_back (PresetPoint (1, 0));
972 fade_out_presets->push_back (p);
974 p = new Preset (loout_xpm);
975 p->push_back (PresetPoint (0, 1));
976 p->push_back (PresetPoint (0.023041, 0.697222));
977 p->push_back (PresetPoint (0.0553, 0.483333));
978 p->push_back (PresetPoint (0.170507, 0.233333));
979 p->push_back (PresetPoint (0.370968, 0.0861111));
980 p->push_back (PresetPoint (0.610599, 0.0333333));
981 p->push_back (PresetPoint (1, 0));
982 fade_out_presets->push_back (p);
984 p = new Preset (regout2_xpm);
985 p->push_back (PresetPoint (0, 1));
986 p->push_back (PresetPoint (0.080645, 0.730556));
987 p->push_back (PresetPoint (0.277778, 0.289256));
988 p->push_back (PresetPoint (0.470046, 0.152778));
989 p->push_back (PresetPoint (0.695853, 0.0694444));
990 p->push_back (PresetPoint (1, 0));
991 fade_out_presets->push_back (p);
993 p = new Preset (linout_xpm);
994 p->push_back (PresetPoint (0, 1));
995 p->push_back (PresetPoint (1, 0));
996 fade_out_presets->push_back (p);
1000 CrossfadeEditor::curve_select_clicked (WhichFade wf)
1006 for (vector<GnomeCanvasItem*>::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) {
1007 gnome_canvas_item_set ((*i), "wave_color", color_map[cSelectedCrossfadeEditorWave], NULL);
1010 for (vector<GnomeCanvasItem*>::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) {
1011 gnome_canvas_item_set ((*i), "wave_color", color_map[cCrossfadeEditorWave], NULL);
1014 gnome_canvas_item_set (fade[In].line, "fill_color_rgba", color_map[cSelectedCrossfadeEditorLine], NULL);
1015 gnome_canvas_item_set (fade[Out].line, "fill_color_rgba", color_map[cCrossfadeEditorLine], NULL);
1016 gnome_canvas_item_hide (fade[Out].shading);
1017 gnome_canvas_item_show (fade[In].shading);
1019 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
1020 gnome_canvas_item_hide ((*i)->box);
1023 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
1024 gnome_canvas_item_show ((*i)->box);
1027 for (vector<Button*>::iterator i = fade_out_buttons.begin(); i != fade_out_buttons.end(); ++i) {
1028 (*i)->set_sensitive (false);
1031 for (vector<Button*>::iterator i = fade_in_buttons.begin(); i != fade_in_buttons.end(); ++i) {
1032 (*i)->set_sensitive (true);
1037 for (vector<GnomeCanvasItem*>::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) {
1038 gnome_canvas_item_set ((*i), "wave_color", color_map[cCrossfadeEditorWave], NULL);
1041 for (vector<GnomeCanvasItem*>::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) {
1042 gnome_canvas_item_set ((*i), "wave_color", color_map[cSelectedCrossfadeEditorWave], NULL);
1045 gnome_canvas_item_set (fade[Out].line, "fill_color_rgba", color_map[cSelectedCrossfadeEditorLine], NULL);
1046 gnome_canvas_item_set (fade[In].line, "fill_color_rgba", color_map[cCrossfadeEditorLine], NULL);
1047 gnome_canvas_item_hide (fade[In].shading);
1048 gnome_canvas_item_show (fade[Out].shading);
1050 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
1051 gnome_canvas_item_hide ((*i)->box);
1054 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
1055 gnome_canvas_item_show ((*i)->box);
1058 for (vector<Button*>::iterator i = fade_out_buttons.begin(); i != fade_out_buttons.end(); ++i) {
1059 (*i)->set_sensitive (true);
1062 for (vector<Button*>::iterator i = fade_in_buttons.begin(); i != fade_in_buttons.end(); ++i) {
1063 (*i)->set_sensitive (false);
1070 CrossfadeEditor::x_coordinate (double& xfract) const
1072 xfract = min (1.0, xfract);
1073 xfract = max (0.0, xfract);
1075 return canvas_border + (xfract * effective_width());
1079 CrossfadeEditor::y_coordinate (double& yfract) const
1081 yfract = min (1.0, yfract);
1082 yfract = max (0.0, yfract);
1084 return (_canvas->allocation.height - (canvas_border)) - (yfract * effective_height());
1088 CrossfadeEditor::make_waves (AudioRegion& region, WhichFade which)
1091 uint32_t nchans = region.n_channels();
1096 color = color_map[cSelectedCrossfadeEditorWave];
1098 color = color_map[cCrossfadeEditorWave];
1101 ht = _canvas->allocation.height / (double) nchans;
1102 spu = xfade.length() / (double) effective_width();
1104 for (uint32_t n = 0; n < nchans; ++n) {
1106 gdouble yoff = n * ht;
1108 if (region.source(n).peaks_ready (bind (mem_fun(*this, &CrossfadeEditor::peaks_ready), ®ion, which))) {
1110 GnomeCanvasItem *wave = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS(_canvas)),
1111 gnome_canvas_waveview_get_type (),
1112 "data_src", (gpointer) ®ion,
1113 "cache_updater", (gboolean) TRUE,
1114 "cache", gnome_canvas_waveview_cache_new (),
1115 "channel", (guint32) n,
1116 "length_function", (gpointer) region_length_from_c,
1117 "sourcefile_length_function", (gpointer) sourcefile_length_from_c,
1118 "peak_function", (gpointer) region_read_peaks_from_c,
1119 "gain_function", (gpointer) curve_get_vector_from_c,
1120 "gain_src", &fade[which].gain_curve,
1121 "x", (double) canvas_border,
1124 "samples_per_unit", spu,
1125 "amplitude_above_axis", 2.0,
1126 "wave_color", color,
1129 gnome_canvas_item_lower_to_bottom (wave);
1130 fade[which].waves.push_back (wave);
1134 gnome_canvas_item_lower_to_bottom (toplevel);
1138 CrossfadeEditor::peaks_ready (AudioRegion* r, WhichFade which)
1140 /* this should never be called, because the peak files for an xfade
1141 will be ready by the time we want them. but our API forces us
1142 to provide this, so ..
1145 make_waves (*r, which);
1149 CrossfadeEditor::audition_both ()
1151 AudioPlaylist& pl (session.the_auditioner().prepare_playlist());
1152 jack_nframes_t preroll;
1153 jack_nframes_t postroll;
1154 jack_nframes_t length;
1155 jack_nframes_t left_start_offset;
1156 jack_nframes_t right_length;
1157 jack_nframes_t left_length;
1159 if (preroll_button.get_active()) {
1160 preroll = ARDOUR_UI::instance()->preroll_clock.current_duration ();
1165 if (postroll_button.get_active()) {
1166 postroll = ARDOUR_UI::instance()->postroll_clock.current_duration ();
1171 if ((left_start_offset = xfade.out().length() - xfade.length()) >= preroll) {
1172 left_start_offset -= preroll;
1177 if ((left_length = xfade.length()) < xfade.out().length() - left_start_offset) {
1181 right_length = xfade.length();
1183 if (xfade.in().length() - right_length < postroll) {
1184 right_length += postroll;
1187 AudioRegion* left = new AudioRegion (xfade.out(), left_start_offset, left_length, "xfade out",
1188 0, Region::DefaultFlags, false);
1189 AudioRegion* right = new AudioRegion (xfade.in(), 0, right_length, "xfade in",
1190 0, Region::DefaultFlags, false);
1192 pl.add_region (*left, 0);
1193 pl.add_region (*right, 1+preroll);
1195 /* there is only one ... */
1197 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1199 session.audition_playlist ();
1203 CrossfadeEditor::audition_left_dry ()
1205 AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade left",
1206 0, Region::DefaultFlags, false);
1208 session.audition_region (*left);
1212 CrossfadeEditor::audition_left ()
1214 AudioPlaylist& pl (session.the_auditioner().prepare_playlist());
1216 AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade left",
1217 0, Region::DefaultFlags, false);
1218 AudioRegion* right = new AudioRegion (xfade.in(), 0, xfade.length(), "xfade in",
1219 0, Region::DefaultFlags, false);
1221 pl.add_region (*left, 0);
1222 pl.add_region (*right, 1);
1224 right->set_muted (true);
1226 /* there is only one ... */
1228 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1230 session.audition_playlist ();
1232 /* memory leak for regions */
1236 CrossfadeEditor::audition_right_dry ()
1238 AudioRegion* right = new AudioRegion (xfade.in(), 0, xfade.length(), "xfade in",
1239 0, Region::DefaultFlags, false);
1240 session.audition_region (*right);
1244 CrossfadeEditor::audition_right ()
1246 AudioPlaylist& pl (session.the_auditioner().prepare_playlist());
1248 AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade out",
1249 0, Region::DefaultFlags, false);
1250 AudioRegion* right = new AudioRegion (xfade.out(), 0, xfade.length(), "xfade out",
1251 0, Region::DefaultFlags, false);
1253 pl.add_region (*left, 0);
1254 pl.add_region (*right, 1);
1256 left->set_muted (true);
1258 /* there is only one ... */
1260 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1262 session.audition_playlist ();
1266 CrossfadeEditor::cancel_audition ()
1268 session.cancel_audition ();
1272 CrossfadeEditor::audition_toggled ()
1276 if ((x = audition_both_button.get_active ()) != session.is_auditioning()) {
1287 CrossfadeEditor::audition_right_toggled ()
1291 if ((x = audition_right_button.get_active ()) != session.is_auditioning()) {
1302 CrossfadeEditor::audition_right_dry_toggled ()
1306 if ((x = audition_right_dry_button.get_active ()) != session.is_auditioning()) {
1309 audition_right_dry ();
1317 CrossfadeEditor::audition_left_toggled ()
1321 if ((x = audition_left_button.get_active ()) != session.is_auditioning()) {
1332 CrossfadeEditor::audition_left_dry_toggled ()
1336 if ((x = audition_left_dry_button.get_active ()) != session.is_auditioning()) {
1339 audition_left_dry ();