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")),
76 //ok_button (_("OK")),
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 get_action_area()->set_layout(BUTTONBOX_SPREAD);
111 get_action_area()->pack_start(clear_button);
112 get_action_area()->pack_start(revert_button);
113 cancel_button = add_button ("Cancel", RESPONSE_CANCEL);
114 ok_button = add_button ("OK", RESPONSE_ACCEPT);
116 if (fade_in_presets == 0) {
120 point_grabbed = false;
123 canvas = new ArdourCanvas::CanvasAA ();
124 canvas->signal_size_allocate().connect (mem_fun(*this, &CrossfadeEditor::canvas_allocation));
125 canvas->set_size_request (425, 200);
127 toplevel = new ArdourCanvas::SimpleRect (*(canvas->root()));
128 toplevel->property_x1() = 0.0;
129 toplevel->property_y1() = 0.0;
130 toplevel->property_x2() = 10.0;
131 toplevel->property_y2() = 10.0;
132 toplevel->property_fill() = true;
133 toplevel->property_fill_color_rgba() = (guint32) color_map[cCrossfadeEditorBase];
134 toplevel->property_outline_pixels() = 0;
135 toplevel->signal_event().connect (mem_fun (*this, &CrossfadeEditor::canvas_event));
137 fade[Out].line = new ArdourCanvas::Line (*(canvas->root()));
138 fade[Out].line->property_width_pixels() = 1;
139 fade[Out].line->property_fill_color_rgba() = color_map[cCrossfadeEditorLine];
141 fade[Out].shading = new ArdourCanvas::Polygon (*(canvas->root()));
142 fade[Out].shading->property_fill_color_rgba() = color_map[cCrossfadeEditorLineShading];
144 fade[In].line = new ArdourCanvas::Line (*(canvas->root()));
145 fade[In].line->property_width_pixels() = 1;
146 fade[In].line->property_fill_color_rgba() = color_map[cCrossfadeEditorLine];
148 fade[In].shading = new ArdourCanvas::Polygon (*(canvas->root()));
149 fade[In].shading->property_fill_color_rgba() = color_map[cCrossfadeEditorLineShading];
151 fade[In].shading->signal_event().connect (mem_fun (*this, &CrossfadeEditor::canvas_event));
152 fade[In].line->signal_event().connect (mem_fun (*this, &CrossfadeEditor::curve_event));
153 fade[Out].shading->signal_event().connect (mem_fun (*this, &CrossfadeEditor::canvas_event));
154 fade[Out].line->signal_event().connect (mem_fun (*this, &CrossfadeEditor::curve_event));
156 select_in_button.set_name (X_("CrossfadeEditCurveButton"));
157 select_out_button.set_name (X_("CrossfadeEditCurveButton"));
159 select_in_button.signal_clicked().connect (bind (mem_fun (*this, &CrossfadeEditor::curve_select_clicked), In));
160 select_out_button.signal_clicked().connect (bind (mem_fun (*this, &CrossfadeEditor::curve_select_clicked), Out));
162 HBox* acbox = manage (new HBox);
164 audition_box.set_border_width (7);
165 audition_box.set_spacing (5);
166 audition_box.set_homogeneous (false);
167 audition_box.pack_start (audition_left_dry_button, false, false);
168 audition_box.pack_start (audition_left_button, false, false);
169 audition_box.pack_start (audition_both_button, false, false);
170 audition_box.pack_start (audition_right_button, false, false);
171 audition_box.pack_start (audition_right_dry_button, false, false);
173 Frame* audition_frame = manage (new Frame (_("Audition")));
175 audition_frame->set_name (X_("CrossfadeEditFrame"));
176 audition_frame->add (audition_box);
178 acbox->pack_start (*audition_frame, true, false);
180 Frame* canvas_frame = manage (new Frame);
181 canvas_frame->add (*canvas);
182 canvas_frame->set_shadow_type (Gtk::SHADOW_IN);
184 fade_in_table.attach (select_in_button, 0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND);
185 fade_out_table.attach (select_out_button, 0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND);
195 for (list<Preset*>::iterator i = fade_in_presets->begin(); i != fade_in_presets->end(); ++i) {
197 pxmap = manage (new Image (Gdk::Pixbuf::create_from_xpm_data((*i)->xpm)));
198 pbutton = manage (new Button);
199 pbutton->add (*pxmap);
200 pbutton->set_name ("CrossfadeEditButton");
201 pbutton->signal_clicked().connect (bind (mem_fun(*this, &CrossfadeEditor::apply_preset), *i));
202 fade_in_table.attach (*pbutton, col, col+1, row, row+1);
203 fade_in_buttons.push_back (pbutton);
216 for (list<Preset*>::iterator i = fade_out_presets->begin(); i != fade_out_presets->end(); ++i) {
218 pxmap = manage (new Image (Gdk::Pixbuf::create_from_xpm_data((*i)->xpm)));
219 pbutton = manage (new Button);
220 pbutton->add (*pxmap);
221 pbutton->set_name ("CrossfadeEditButton");
222 pbutton->signal_clicked().connect (bind (mem_fun(*this, &CrossfadeEditor::apply_preset), *i));
223 fade_out_table.attach (*pbutton, col, col+1, row, row+1);
224 fade_out_buttons.push_back (pbutton);
234 clear_button.set_name ("CrossfadeEditButton");
235 revert_button.set_name ("CrossfadeEditButton");
236 ok_button->set_name ("CrossfadeEditButton");
237 cancel_button->set_name ("CrossfadeEditButton");
238 preroll_button.set_name ("CrossfadeEditButton");
239 postroll_button.set_name ("CrossfadeEditButton");
240 audition_both_button.set_name ("CrossfadeEditAuditionButton");
241 audition_left_dry_button.set_name ("CrossfadeEditAuditionButton");
242 audition_left_button.set_name ("CrossfadeEditAuditionButton");
243 audition_right_dry_button.set_name ("CrossfadeEditAuditionButton");
244 audition_right_button.set_name ("CrossfadeEditAuditionButton");
246 clear_button.signal_clicked().connect (mem_fun(*this, &CrossfadeEditor::clear));
247 revert_button.signal_clicked().connect (mem_fun(*this, &CrossfadeEditor::reset));
248 audition_both_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_toggled));
249 audition_right_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_right_toggled));
250 audition_right_dry_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_right_dry_toggled));
251 audition_left_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_left_toggled));
252 audition_left_dry_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_left_dry_toggled));
254 //action_box.set_border_width (7);
255 //action_box.set_spacing (5);
256 //action_box.set_homogeneous (false);
257 //action_box.pack_end (*cancel_button, false, false);
258 //action_box.pack_end (*ok_button, false, false);
259 //action_box.pack_end (*revert_button, false, false);
260 //action_box.pack_end (*clear_button, false, false);
262 //Frame* edit_frame = manage (new Frame (_("Edit")));
263 //edit_frame->set_name (X_("CrossfadeEditFrame"));
264 //edit_frame->add (action_box);
266 //Gtk::HBox* action_center_box = manage (new HBox);
267 //action_center_box->pack_start (*edit_frame, true, false);
269 roll_box.pack_start (preroll_button, false, false);
270 roll_box.pack_start (postroll_button, false, false);
272 Gtk::HBox* rcenter_box = manage (new HBox);
273 rcenter_box->pack_start (roll_box, true, false);
275 VBox* vpacker2 = manage (new (VBox));
277 vpacker2->set_border_width (12);
278 vpacker2->set_spacing (7);
279 vpacker2->pack_start (*acbox, false, false);
280 vpacker2->pack_start (*rcenter_box, false, false);
281 //vpacker2->pack_start (*action_center_box, false, false);
283 curve_button_box.set_spacing (7);
284 curve_button_box.pack_start (fade_out_table, false, false, 12);
285 curve_button_box.pack_start (*vpacker2, false, false, 12);
286 curve_button_box.pack_start (fade_in_table, false, false, 12);
288 get_vbox()->pack_start (*canvas_frame, true, true);
289 get_vbox()->pack_start (curve_button_box, false, false);
291 /* button to allow hackers to check the actual curve values */
293 // Button* foobut = manage (new Button ("dump"));
294 // foobut-.signal_clicked().connect (mem_fun(*this, &CrossfadeEditor::dump));
295 // vpacker.pack_start (*foobut, false, false);
298 set (xfade.fade_in(), In);
301 set (xfade.fade_out(), Out);
303 curve_select_clicked (In);
305 xfade.StateChanged.connect (mem_fun(*this, &CrossfadeEditor::xfade_changed));
307 session.AuditionActive.connect (mem_fun(*this, &CrossfadeEditor::audition_state_changed));
311 CrossfadeEditor::~CrossfadeEditor()
313 /* most objects will be destroyed when the toplevel window is. */
315 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
319 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
325 CrossfadeEditor::dump ()
327 for (AutomationList::iterator i = fade[Out].normative_curve.begin(); i != fade[Out].normative_curve.end(); ++i) {
328 cerr << (*i)->when << ' ' << (*i)->value << endl;
333 CrossfadeEditor::audition_state_changed (bool yn)
335 ENSURE_GUI_THREAD (bind (mem_fun(*this, &CrossfadeEditor::audition_state_changed), yn));
338 audition_both_button.set_active (false);
339 audition_left_button.set_active (false);
340 audition_right_button.set_active (false);
341 audition_left_dry_button.set_active (false);
342 audition_right_dry_button.set_active (false);
347 CrossfadeEditor::set (const ARDOUR::Curve& curve, WhichFade which)
350 ARDOUR::Curve::const_iterator the_end;
352 for (list<Point*>::iterator i = fade[which].points.begin(); i != fade[which].points.end(); ++i) {
356 fade[which].points.clear ();
357 fade[which].gain_curve.clear ();
358 fade[which].normative_curve.clear ();
364 the_end = curve.const_end();
367 firstx = (*curve.const_begin())->when;
368 endx = (*the_end)->when;
370 for (ARDOUR::Curve::const_iterator i = curve.const_begin(); i != curve.const_end(); ++i) {
372 double xfract = ((*i)->when - firstx) / (endx - firstx);
373 double yfract = ((*i)->value - miny) / (maxy - miny);
375 Point* p = make_point ();
377 p->move_to (x_coordinate (xfract), y_coordinate (yfract),
380 fade[which].points.push_back (p);
383 /* no need to sort because curve is already time-ordered */
387 swap (which, current);
389 swap (which, current);
393 CrossfadeEditor::curve_event (GdkEvent* event)
395 /* treat it like a toplevel event */
397 return canvas_event (event);
401 CrossfadeEditor::point_event (GdkEvent* event, Point* point)
404 if (point->curve != fade[current].line) {
408 switch (event->type) {
409 case GDK_BUTTON_PRESS:
410 point_grabbed = true;
412 case GDK_BUTTON_RELEASE:
413 point_grabbed = false;
415 if (Keyboard::is_delete_event (&event->button)) {
416 fade[current].points.remove (point);
423 case GDK_MOTION_NOTIFY:
427 /* can't drag first or last points horizontally */
429 if (point == fade[current].points.front() || point == fade[current].points.back()) {
432 new_x = (event->motion.x - canvas_border)/effective_width();
435 new_y = 1.0 - ((event->motion.y - canvas_border)/effective_height());
436 point->move_to (x_coordinate (new_x), y_coordinate (new_y),
448 CrossfadeEditor::canvas_event (GdkEvent* event)
450 switch (event->type) {
451 case GDK_BUTTON_PRESS:
452 add_control_point ((event->button.x - canvas_border)/effective_width(),
453 1.0 - ((event->button.y - canvas_border)/effective_height()));
462 CrossfadeEditor::Point::~Point()
467 CrossfadeEditor::Point*
468 CrossfadeEditor::make_point ()
470 Point* p = new Point;
472 p->box = new ArdourCanvas::SimpleRect (*(canvas->root()));
473 p->box->property_fill() = true;
474 p->box->property_fill_color_rgba() = color_map[cCrossfadeEditorPointFill];
475 p->box->property_outline_color_rgba() = color_map[cCrossfadeEditorPointOutline];
476 p->box->property_outline_pixels() = 1;
478 p->curve = fade[current].line;
480 p->box->signal_event().connect (bind (mem_fun (*this, &CrossfadeEditor::point_event), p));
486 CrossfadeEditor::add_control_point (double x, double y)
490 /* enforce end point x location */
492 if (fade[current].points.empty()) {
494 } else if (fade[current].points.size() == 1) {
498 Point* p = make_point ();
500 p->move_to (x_coordinate (x), y_coordinate (y), x, y);
502 fade[current].points.push_back (p);
503 fade[current].points.sort (cmp);
509 CrossfadeEditor::Point::move_to (double nx, double ny, double xfract, double yfract)
511 const double half_size = rint(size/2.0);
512 double x1 = nx - half_size;
513 double x2 = nx + half_size;
515 box->property_x1() = x1;
516 box->property_x2() = x2;
518 box->property_y1() = ny - half_size;
519 box->property_y2() = ny + half_size;
526 CrossfadeEditor::canvas_allocation (Gtk::Allocation& alloc)
529 toplevel->property_x1() = 0.0;
530 toplevel->property_y1() = 0.0;
531 toplevel->property_x2() = (double) canvas->get_allocation().get_width() + canvas_border;
532 toplevel->property_y2() = (double) canvas->get_allocation().get_height() + canvas_border;
535 canvas->set_scroll_region (0.0, 0.0,
536 canvas->get_allocation().get_width(),
537 canvas->get_allocation().get_height());
539 Point* end = make_point ();
542 if (fade[In].points.size() > 1) {
543 Point* old_end = fade[In].points.back();
544 fade[In].points.pop_back ();
545 end->move_to (x_coordinate (old_end->x),
546 y_coordinate (old_end->y),
547 old_end->x, old_end->y);
552 end->move_to (x_coordinate (x), y_coordinate (y), x, y);
556 fade[In].points.push_back (end);
557 fade[In].points.sort (cmp);
559 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
560 (*i)->move_to (x_coordinate((*i)->x), y_coordinate((*i)->y),
566 if (fade[Out].points.size() > 1) {
567 Point* old_end = fade[Out].points.back();
568 fade[Out].points.pop_back ();
569 end->move_to (x_coordinate (old_end->x),
570 y_coordinate (old_end->y),
571 old_end->x, old_end->y);
576 end->move_to (x_coordinate (x), y_coordinate (y), x, y);
580 fade[Out].points.push_back (end);
581 fade[Out].points.sort (cmp);
583 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
584 (*i)->move_to (x_coordinate ((*i)->x),
585 y_coordinate ((*i)->y),
589 WhichFade old_current = current;
594 current = old_current;
596 double spu = xfade.length() / (double) effective_width();
598 if (fade[In].waves.empty()) {
599 make_waves (xfade.in(), In);
602 if (fade[Out].waves.empty()) {
603 make_waves (xfade.out(), Out);
607 vector<ArdourCanvas::WaveView*>::iterator i;
610 ht = canvas->get_allocation().get_height() / xfade.in().n_channels();
612 for (n = 0, i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i, ++n) {
617 (*i)->property_y() = yoff;
618 (*i)->property_height() = ht;
619 (*i)->property_samples_per_unit() = spu;
622 ht = canvas->get_allocation().get_height() / xfade.out().n_channels();
624 for (n = 0, i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i, ++n) {
629 (*i)->property_y() = yoff;
630 (*i)->property_height() = ht;
631 (*i)->property_samples_per_unit() = spu;
638 CrossfadeEditor::xfade_changed (Change ignored)
640 set (xfade.fade_in(), In);
641 set (xfade.fade_out(), Out);
645 CrossfadeEditor::redraw ()
647 if (canvas->get_allocation().get_width() < 2) {
651 jack_nframes_t len = xfade.length ();
653 fade[current].normative_curve.clear ();
654 fade[current].gain_curve.clear ();
656 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
657 fade[current].normative_curve.add ((*i)->x, (*i)->y);
658 fade[current].gain_curve.add (((*i)->x * len), (*i)->y);
661 size_t npoints = (size_t) effective_width();
664 fade[current].normative_curve.get_vector (0, 1.0, vec, npoints);
666 ArdourCanvas::Points pts;
667 ArdourCanvas::Points spts;
669 while (pts.size() < npoints) {
670 pts.push_back (Gnome::Art::Point (0,0));
673 while (spts.size() < npoints + 3) {
674 spts.push_back (Gnome::Art::Point (0,0));
677 /* the shade coordinates *MUST* be in anti-clockwise order.
684 spts[0].set_x (canvas_border);
685 spts[0].set_y (effective_height() + canvas_border);
689 spts[1].set_x (effective_width() + canvas_border);
690 spts[1].set_y (effective_height() + canvas_border);
694 spts[2].set_x (effective_width() + canvas_border);
695 spts[2].set_y (canvas_border);
702 spts[0].set_x (canvas_border);
703 spts[0].set_y (canvas_border);
707 spts[1].set_x (canvas_border);
708 spts[1].set_y (effective_height() + canvas_border);
712 spts[2].set_x (effective_width() + canvas_border);
713 spts[2].set_y (effective_height() + canvas_border);
717 // GTK2FIX some odd math to fix up here
719 size_t last_spt = (npoints + 3) - 1;
721 for (size_t i = 0; i < npoints; ++i) {
725 pts[i].set_x (canvas_border + i);
726 pts[i].set_y (y_coordinate (y));
728 spts[last_spt - i].set_x (canvas_border + i);
729 spts[last_spt - i].set_y (pts[i].get_y());
732 fade[current].line->property_points() = pts;
733 fade[current].shading->property_points() = spts;
735 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[current].waves.begin(); i != fade[current].waves.end(); ++i) {
736 (*i)->property_gain_src() = &fade[current].gain_curve;
741 CrossfadeEditor::apply_preset (Preset *preset)
743 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
747 fade[current].points.clear ();
749 for (Preset::iterator i = preset->begin(); i != preset->end(); ++i) {
750 Point* p = make_point ();
751 p->move_to (x_coordinate ((*i).x), y_coordinate ((*i).y),
753 fade[current].points.push_back (p);
760 CrossfadeEditor::apply ()
766 CrossfadeEditor::_apply_to (Crossfade* xf)
768 ARDOUR::Curve& in (xf->fade_in());
769 ARDOUR::Curve& out (xf->fade_out());
774 ARDOUR::Curve::const_iterator the_end = in.const_end();
777 double firstx = (*in.begin())->when;
778 double endx = (*the_end)->when;
779 double miny = in.get_min_y ();
780 double maxy = in.get_max_y ();
785 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
787 double when = firstx + ((*i)->x * (endx - firstx));
788 double value = (*i)->y; // miny + ((*i)->y * (maxy - miny));
789 in.add (when, value);
794 the_end = out.const_end();
797 firstx = (*out.begin())->when;
798 endx = (*the_end)->when;
799 miny = out.get_min_y ();
800 maxy = out.get_max_y ();
805 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
807 double when = firstx + ((*i)->x * (endx - firstx));
808 double value = (*i)->y; // miny + ((*i)->y * (maxy - miny));
809 out.add (when, value);
817 CrossfadeEditor::setup (Crossfade* xfade)
820 xfade->set_active (true);
821 xfade->fade_in().solve ();
822 xfade->fade_out().solve ();
826 CrossfadeEditor::clear ()
828 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
832 fade[current].points.clear ();
838 CrossfadeEditor::reset ()
840 set (xfade.fade_in(), In);
841 set (xfade.fade_out(), Out);
845 CrossfadeEditor::build_presets ()
849 fade_in_presets = new Presets;
850 fade_out_presets = new Presets;
854 p = new Preset (hiin_xpm);
855 p->push_back (PresetPoint (0, 0));
856 p->push_back (PresetPoint (0.0207373, 0.197222));
857 p->push_back (PresetPoint (0.0645161, 0.525));
858 p->push_back (PresetPoint (0.152074, 0.802778));
859 p->push_back (PresetPoint (0.276498, 0.919444));
860 p->push_back (PresetPoint (0.481567, 0.980556));
861 p->push_back (PresetPoint (0.767281, 1));
862 p->push_back (PresetPoint (1, 1));
863 fade_in_presets->push_back (p);
865 p = new Preset (loin_xpm);
866 p->push_back (PresetPoint (0, 0));
867 p->push_back (PresetPoint (0.389401, 0.0333333));
868 p->push_back (PresetPoint (0.629032, 0.0861111));
869 p->push_back (PresetPoint (0.829493, 0.233333));
870 p->push_back (PresetPoint (0.9447, 0.483333));
871 p->push_back (PresetPoint (0.976959, 0.697222));
872 p->push_back (PresetPoint (1, 1));
873 fade_in_presets->push_back (p);
875 p = new Preset (regin_xpm);
876 p->push_back (PresetPoint (0, 0));
877 p->push_back (PresetPoint (0.0737327, 0.308333));
878 p->push_back (PresetPoint (0.246544, 0.658333));
879 p->push_back (PresetPoint (0.470046, 0.886111));
880 p->push_back (PresetPoint (0.652074, 0.972222));
881 p->push_back (PresetPoint (0.771889, 0.988889));
882 p->push_back (PresetPoint (1, 1));
883 fade_in_presets->push_back (p);
885 p = new Preset (regin2_xpm);
886 p->push_back (PresetPoint (0, 0));
887 p->push_back (PresetPoint (0.304147, 0.0694444));
888 p->push_back (PresetPoint (0.529954, 0.152778));
889 p->push_back (PresetPoint (0.725806, 0.333333));
890 p->push_back (PresetPoint (0.847926, 0.558333));
891 p->push_back (PresetPoint (0.919355, 0.730556));
892 p->push_back (PresetPoint (1, 1));
893 fade_in_presets->push_back (p);
895 p = new Preset (linin_xpm);
896 p->push_back (PresetPoint (0, 0));
897 p->push_back (PresetPoint (1, 1));
898 fade_in_presets->push_back (p);
902 p = new Preset (hiout_xpm);
903 p->push_back (PresetPoint (0, 1));
904 p->push_back (PresetPoint (0.305556, 1));
905 p->push_back (PresetPoint (0.548611, 0.991736));
906 p->push_back (PresetPoint (0.759259, 0.931129));
907 p->push_back (PresetPoint (0.918981, 0.68595));
908 p->push_back (PresetPoint (0.976852, 0.22865));
909 p->push_back (PresetPoint (1, 0));
910 fade_out_presets->push_back (p);
912 p = new Preset (regout_xpm);
913 p->push_back (PresetPoint (0, 1));
914 p->push_back (PresetPoint (0.228111, 0.988889));
915 p->push_back (PresetPoint (0.347926, 0.972222));
916 p->push_back (PresetPoint (0.529954, 0.886111));
917 p->push_back (PresetPoint (0.753456, 0.658333));
918 p->push_back (PresetPoint (0.9262673, 0.308333));
919 p->push_back (PresetPoint (1, 0));
920 fade_out_presets->push_back (p);
922 p = new Preset (loout_xpm);
923 p->push_back (PresetPoint (0, 1));
924 p->push_back (PresetPoint (0.023041, 0.697222));
925 p->push_back (PresetPoint (0.0553, 0.483333));
926 p->push_back (PresetPoint (0.170507, 0.233333));
927 p->push_back (PresetPoint (0.370968, 0.0861111));
928 p->push_back (PresetPoint (0.610599, 0.0333333));
929 p->push_back (PresetPoint (1, 0));
930 fade_out_presets->push_back (p);
932 p = new Preset (regout2_xpm);
933 p->push_back (PresetPoint (0, 1));
934 p->push_back (PresetPoint (0.080645, 0.730556));
935 p->push_back (PresetPoint (0.277778, 0.289256));
936 p->push_back (PresetPoint (0.470046, 0.152778));
937 p->push_back (PresetPoint (0.695853, 0.0694444));
938 p->push_back (PresetPoint (1, 0));
939 fade_out_presets->push_back (p);
941 p = new Preset (linout_xpm);
942 p->push_back (PresetPoint (0, 1));
943 p->push_back (PresetPoint (1, 0));
944 fade_out_presets->push_back (p);
948 CrossfadeEditor::curve_select_clicked (WhichFade wf)
954 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) {
955 (*i)->property_wave_color() = color_map[cSelectedCrossfadeEditorWave];
958 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) {
959 (*i)->property_wave_color() = color_map[cCrossfadeEditorWave];
962 fade[In].line->property_fill_color_rgba() = color_map[cSelectedCrossfadeEditorLine];
963 fade[Out].line->property_fill_color_rgba() = color_map[cCrossfadeEditorLine];
964 fade[Out].shading->hide();
965 fade[In].shading->show();
967 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
971 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
975 for (vector<Button*>::iterator i = fade_out_buttons.begin(); i != fade_out_buttons.end(); ++i) {
976 (*i)->set_sensitive (false);
979 for (vector<Button*>::iterator i = fade_in_buttons.begin(); i != fade_in_buttons.end(); ++i) {
980 (*i)->set_sensitive (true);
985 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) {
986 (*i)->property_wave_color() = color_map[cCrossfadeEditorWave];
989 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) {
990 (*i)->property_wave_color() = color_map[cSelectedCrossfadeEditorWave];
993 fade[Out].line->property_fill_color_rgba() = color_map[cSelectedCrossfadeEditorLine];
994 fade[In].line->property_fill_color_rgba() = color_map[cCrossfadeEditorLine];
995 fade[In].shading->hide();
996 fade[Out].shading->show();
998 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
1002 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
1006 for (vector<Button*>::iterator i = fade_out_buttons.begin(); i != fade_out_buttons.end(); ++i) {
1007 (*i)->set_sensitive (true);
1010 for (vector<Button*>::iterator i = fade_in_buttons.begin(); i != fade_in_buttons.end(); ++i) {
1011 (*i)->set_sensitive (false);
1018 CrossfadeEditor::x_coordinate (double& xfract) const
1020 xfract = min (1.0, xfract);
1021 xfract = max (0.0, xfract);
1023 return canvas_border + (xfract * effective_width());
1027 CrossfadeEditor::y_coordinate (double& yfract) const
1029 yfract = min (1.0, yfract);
1030 yfract = max (0.0, yfract);
1032 return (canvas->get_allocation().get_height() - (canvas_border)) - (yfract * effective_height());
1036 CrossfadeEditor::make_waves (AudioRegion& region, WhichFade which)
1039 uint32_t nchans = region.n_channels();
1044 color = color_map[cSelectedCrossfadeEditorWave];
1046 color = color_map[cCrossfadeEditorWave];
1049 ht = canvas->get_allocation().get_height() / (double) nchans;
1050 spu = xfade.length() / (double) effective_width();
1052 for (uint32_t n = 0; n < nchans; ++n) {
1054 gdouble yoff = n * ht;
1056 if (region.source(n).peaks_ready (bind (mem_fun(*this, &CrossfadeEditor::peaks_ready), ®ion, which))) {
1058 WaveView* waveview = new WaveView (*(canvas->root()));
1060 waveview->property_data_src() = ®ion;
1061 waveview->property_cache_updater() = true;
1062 waveview->property_cache() = WaveView::create_cache();
1063 waveview->property_channel() = n;
1064 waveview->property_length_function() = (void*) region_length_from_c;
1065 waveview->property_sourcefile_length_function() = (void*) sourcefile_length_from_c;
1066 waveview->property_peak_function() = (void*) region_read_peaks_from_c;
1067 waveview->property_gain_function() = (void*) curve_get_vector_from_c;
1068 waveview->property_gain_src() = &fade[which].gain_curve;
1069 waveview->property_x() = canvas_border;
1070 waveview->property_y() = yoff;
1071 waveview->property_height() = ht;
1072 waveview->property_samples_per_unit() = spu;
1073 waveview->property_amplitude_above_axis() = 2.0;
1074 waveview->property_wave_color() = color;
1076 waveview->lower_to_bottom();
1077 fade[which].waves.push_back (waveview);
1081 toplevel->lower_to_bottom();
1085 CrossfadeEditor::peaks_ready (AudioRegion* r, WhichFade which)
1087 /* this should never be called, because the peak files for an xfade
1088 will be ready by the time we want them. but our API forces us
1089 to provide this, so ..
1092 make_waves (*r, which);
1096 CrossfadeEditor::audition_both ()
1098 AudioPlaylist& pl (session.the_auditioner().prepare_playlist());
1099 jack_nframes_t preroll;
1100 jack_nframes_t postroll;
1101 jack_nframes_t length;
1102 jack_nframes_t left_start_offset;
1103 jack_nframes_t right_length;
1104 jack_nframes_t left_length;
1106 if (preroll_button.get_active()) {
1107 preroll = ARDOUR_UI::instance()->preroll_clock.current_duration ();
1112 if (postroll_button.get_active()) {
1113 postroll = ARDOUR_UI::instance()->postroll_clock.current_duration ();
1118 if ((left_start_offset = xfade.out().length() - xfade.length()) >= preroll) {
1119 left_start_offset -= preroll;
1124 if ((left_length = xfade.length()) < xfade.out().length() - left_start_offset) {
1128 right_length = xfade.length();
1130 if (xfade.in().length() - right_length < postroll) {
1131 right_length += postroll;
1134 AudioRegion* left = new AudioRegion (xfade.out(), left_start_offset, left_length, "xfade out",
1135 0, Region::DefaultFlags, false);
1136 AudioRegion* right = new AudioRegion (xfade.in(), 0, right_length, "xfade in",
1137 0, Region::DefaultFlags, false);
1139 pl.add_region (*left, 0);
1140 pl.add_region (*right, 1+preroll);
1142 /* there is only one ... */
1144 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1146 session.audition_playlist ();
1150 CrossfadeEditor::audition_left_dry ()
1152 AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade left",
1153 0, Region::DefaultFlags, false);
1155 session.audition_region (*left);
1159 CrossfadeEditor::audition_left ()
1161 AudioPlaylist& pl (session.the_auditioner().prepare_playlist());
1163 AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade left",
1164 0, Region::DefaultFlags, false);
1165 AudioRegion* right = new AudioRegion (xfade.in(), 0, xfade.length(), "xfade in",
1166 0, Region::DefaultFlags, false);
1168 pl.add_region (*left, 0);
1169 pl.add_region (*right, 1);
1171 right->set_muted (true);
1173 /* there is only one ... */
1175 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1177 session.audition_playlist ();
1179 /* memory leak for regions */
1183 CrossfadeEditor::audition_right_dry ()
1185 AudioRegion* right = new AudioRegion (xfade.in(), 0, xfade.length(), "xfade in",
1186 0, Region::DefaultFlags, false);
1187 session.audition_region (*right);
1191 CrossfadeEditor::audition_right ()
1193 AudioPlaylist& pl (session.the_auditioner().prepare_playlist());
1195 AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade out",
1196 0, Region::DefaultFlags, false);
1197 AudioRegion* right = new AudioRegion (xfade.out(), 0, xfade.length(), "xfade out",
1198 0, Region::DefaultFlags, false);
1200 pl.add_region (*left, 0);
1201 pl.add_region (*right, 1);
1203 left->set_muted (true);
1205 /* there is only one ... */
1207 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1209 session.audition_playlist ();
1213 CrossfadeEditor::cancel_audition ()
1215 session.cancel_audition ();
1219 CrossfadeEditor::audition_toggled ()
1223 if ((x = audition_both_button.get_active ()) != session.is_auditioning()) {
1234 CrossfadeEditor::audition_right_toggled ()
1238 if ((x = audition_right_button.get_active ()) != session.is_auditioning()) {
1249 CrossfadeEditor::audition_right_dry_toggled ()
1253 if ((x = audition_right_dry_button.get_active ()) != session.is_auditioning()) {
1256 audition_right_dry ();
1264 CrossfadeEditor::audition_left_toggled ()
1268 if ((x = audition_left_button.get_active ()) != session.is_auditioning()) {
1279 CrossfadeEditor::audition_left_dry_toggled ()
1283 if ((x = audition_left_dry_button.get_active ()) != session.is_auditioning()) {
1286 audition_left_dry ();