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/audiosource.h>
38 #include <ardour/playlist_templates.h>
39 #include <ardour/region_factory.h>
41 #include <gtkmm2ext/gtk_ui.h>
43 #include "ardour_ui.h"
44 #include "crossfade_edit.h"
45 #include "rgb_macros.h"
48 #include "gui_thread.h"
49 #include "canvas_impl.h"
50 #include "simplerect.h"
55 using namespace ARDOUR;
59 using namespace Editing;
63 const int32_t CrossfadeEditor::Point::size = 7;
64 const double CrossfadeEditor::canvas_border = 10;
65 CrossfadeEditor::Presets* CrossfadeEditor::fade_in_presets = 0;
66 CrossfadeEditor::Presets* CrossfadeEditor::fade_out_presets = 0;
68 CrossfadeEditor::Half::Half ()
70 normative_curve (0.0, 1.0, 1.0, true),
71 gain_curve (0.0, 2.0, 1.0, true)
75 CrossfadeEditor::CrossfadeEditor (Session& s, Crossfade& xf, double my, double mxy)
76 : ArdourDialog (_("ardour: x-fade edit")),
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() = 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 (get_xpm((*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 (get_xpm((*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 roll_box.pack_start (preroll_button, false, false);
255 roll_box.pack_start (postroll_button, false, false);
257 Gtk::HBox* rcenter_box = manage (new HBox);
258 rcenter_box->pack_start (roll_box, true, false);
260 VBox* vpacker2 = manage (new (VBox));
262 vpacker2->set_border_width (12);
263 vpacker2->set_spacing (7);
264 vpacker2->pack_start (*acbox, false, false);
265 vpacker2->pack_start (*rcenter_box, false, false);
267 curve_button_box.set_spacing (7);
268 curve_button_box.pack_start (fade_out_table, false, false, 12);
269 curve_button_box.pack_start (*vpacker2, false, false, 12);
270 curve_button_box.pack_start (fade_in_table, false, false, 12);
272 get_vbox()->pack_start (*canvas_frame, true, true);
273 get_vbox()->pack_start (curve_button_box, false, false);
275 /* button to allow hackers to check the actual curve values */
277 // Button* foobut = manage (new Button ("dump"));
278 // foobut-.signal_clicked().connect (mem_fun(*this, &CrossfadeEditor::dump));
279 // vpacker.pack_start (*foobut, false, false);
282 set (xfade.fade_in(), In);
285 set (xfade.fade_out(), Out);
287 curve_select_clicked (In);
289 xfade.StateChanged.connect (mem_fun(*this, &CrossfadeEditor::xfade_changed));
291 session.AuditionActive.connect (mem_fun(*this, &CrossfadeEditor::audition_state_changed));
295 CrossfadeEditor::~CrossfadeEditor()
297 /* most objects will be destroyed when the toplevel window is. */
299 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
303 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
309 CrossfadeEditor::dump ()
311 for (AutomationList::iterator i = fade[Out].normative_curve.begin(); i != fade[Out].normative_curve.end(); ++i) {
312 cerr << (*i)->when << ' ' << (*i)->value << endl;
317 CrossfadeEditor::audition_state_changed (bool yn)
319 ENSURE_GUI_THREAD (bind (mem_fun(*this, &CrossfadeEditor::audition_state_changed), yn));
322 audition_both_button.set_active (false);
323 audition_left_button.set_active (false);
324 audition_right_button.set_active (false);
325 audition_left_dry_button.set_active (false);
326 audition_right_dry_button.set_active (false);
331 CrossfadeEditor::set (const ARDOUR::Curve& curve, WhichFade which)
334 ARDOUR::Curve::const_iterator the_end;
336 for (list<Point*>::iterator i = fade[which].points.begin(); i != fade[which].points.end(); ++i) {
340 fade[which].points.clear ();
341 fade[which].gain_curve.clear ();
342 fade[which].normative_curve.clear ();
348 the_end = curve.const_end();
351 firstx = (*curve.const_begin())->when;
352 endx = (*the_end)->when;
354 for (ARDOUR::Curve::const_iterator i = curve.const_begin(); i != curve.const_end(); ++i) {
356 double xfract = ((*i)->when - firstx) / (endx - firstx);
357 double yfract = ((*i)->value - miny) / (maxy - miny);
359 Point* p = make_point ();
361 p->move_to (x_coordinate (xfract), y_coordinate (yfract),
364 fade[which].points.push_back (p);
367 /* no need to sort because curve is already time-ordered */
371 swap (which, current);
373 swap (which, current);
377 CrossfadeEditor::curve_event (GdkEvent* event)
379 /* treat it like a toplevel event */
381 return canvas_event (event);
385 CrossfadeEditor::point_event (GdkEvent* event, Point* point)
388 if (point->curve != fade[current].line) {
392 switch (event->type) {
393 case GDK_BUTTON_PRESS:
394 point_grabbed = true;
396 case GDK_BUTTON_RELEASE:
397 point_grabbed = false;
399 if (Keyboard::is_delete_event (&event->button)) {
400 fade[current].points.remove (point);
407 case GDK_MOTION_NOTIFY:
411 /* can't drag first or last points horizontally */
413 if (point == fade[current].points.front() || point == fade[current].points.back()) {
416 new_x = (event->motion.x - canvas_border)/effective_width();
419 new_y = 1.0 - ((event->motion.y - canvas_border)/effective_height());
420 point->move_to (x_coordinate (new_x), y_coordinate (new_y),
432 CrossfadeEditor::canvas_event (GdkEvent* event)
434 switch (event->type) {
435 case GDK_BUTTON_PRESS:
436 add_control_point ((event->button.x - canvas_border)/effective_width(),
437 1.0 - ((event->button.y - canvas_border)/effective_height()));
446 CrossfadeEditor::Point::~Point()
451 CrossfadeEditor::Point*
452 CrossfadeEditor::make_point ()
454 Point* p = new Point;
456 p->box = new ArdourCanvas::SimpleRect (*(canvas->root()));
457 p->box->property_fill() = true;
458 p->box->property_fill_color_rgba() = color_map[cCrossfadeEditorPointFill];
459 p->box->property_outline_color_rgba() = color_map[cCrossfadeEditorPointOutline];
460 p->box->property_outline_pixels() = 1;
462 p->curve = fade[current].line;
464 p->box->signal_event().connect (bind (mem_fun (*this, &CrossfadeEditor::point_event), p));
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 box->property_x1() = x1;
500 box->property_x2() = x2;
502 box->property_y1() = ny - half_size;
503 box->property_y2() = ny + half_size;
510 CrossfadeEditor::canvas_allocation (Gtk::Allocation& alloc)
513 toplevel->property_x1() = 0.0;
514 toplevel->property_y1() = 0.0;
515 toplevel->property_x2() = (double) canvas->get_allocation().get_width() + canvas_border;
516 toplevel->property_y2() = (double) canvas->get_allocation().get_height() + canvas_border;
519 canvas->set_scroll_region (0.0, 0.0,
520 canvas->get_allocation().get_width(),
521 canvas->get_allocation().get_height());
523 Point* end = make_point ();
526 if (fade[In].points.size() > 1) {
527 Point* old_end = fade[In].points.back();
528 fade[In].points.pop_back ();
529 end->move_to (x_coordinate (old_end->x),
530 y_coordinate (old_end->y),
531 old_end->x, old_end->y);
536 end->move_to (x_coordinate (x), y_coordinate (y), x, y);
540 fade[In].points.push_back (end);
541 fade[In].points.sort (cmp);
543 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
544 (*i)->move_to (x_coordinate((*i)->x), y_coordinate((*i)->y),
550 if (fade[Out].points.size() > 1) {
551 Point* old_end = fade[Out].points.back();
552 fade[Out].points.pop_back ();
553 end->move_to (x_coordinate (old_end->x),
554 y_coordinate (old_end->y),
555 old_end->x, old_end->y);
560 end->move_to (x_coordinate (x), y_coordinate (y), x, y);
564 fade[Out].points.push_back (end);
565 fade[Out].points.sort (cmp);
567 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
568 (*i)->move_to (x_coordinate ((*i)->x),
569 y_coordinate ((*i)->y),
573 WhichFade old_current = current;
578 current = old_current;
580 double spu = xfade.length() / (double) effective_width();
582 if (fade[In].waves.empty()) {
583 make_waves (xfade.in(), In);
586 if (fade[Out].waves.empty()) {
587 make_waves (xfade.out(), Out);
591 vector<ArdourCanvas::WaveView*>::iterator i;
594 ht = canvas->get_allocation().get_height() / xfade.in()->n_channels();
596 for (n = 0, i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i, ++n) {
601 (*i)->property_y() = yoff;
602 (*i)->property_height() = ht;
603 (*i)->property_samples_per_unit() = spu;
606 ht = canvas->get_allocation().get_height() / xfade.out()->n_channels();
608 for (n = 0, i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i, ++n) {
613 (*i)->property_y() = yoff;
614 (*i)->property_height() = ht;
615 (*i)->property_samples_per_unit() = spu;
622 CrossfadeEditor::xfade_changed (Change ignored)
624 set (xfade.fade_in(), In);
625 set (xfade.fade_out(), Out);
629 CrossfadeEditor::redraw ()
631 if (canvas->get_allocation().get_width() < 2) {
635 nframes_t len = xfade.length ();
637 fade[current].normative_curve.clear ();
638 fade[current].gain_curve.clear ();
640 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
641 fade[current].normative_curve.add ((*i)->x, (*i)->y);
642 fade[current].gain_curve.add (((*i)->x * len), (*i)->y);
645 size_t npoints = (size_t) effective_width();
648 fade[current].normative_curve.get_vector (0, 1.0, vec, npoints);
650 ArdourCanvas::Points pts;
651 ArdourCanvas::Points spts;
653 while (pts.size() < npoints) {
654 pts.push_back (Gnome::Art::Point (0,0));
657 while (spts.size() < npoints + 3) {
658 spts.push_back (Gnome::Art::Point (0,0));
661 /* the shade coordinates *MUST* be in anti-clockwise order.
668 spts[0].set_x (canvas_border);
669 spts[0].set_y (effective_height() + canvas_border);
673 spts[1].set_x (effective_width() + canvas_border);
674 spts[1].set_y (effective_height() + canvas_border);
678 spts[2].set_x (effective_width() + canvas_border);
679 spts[2].set_y (canvas_border);
686 spts[0].set_x (canvas_border);
687 spts[0].set_y (canvas_border);
691 spts[1].set_x (canvas_border);
692 spts[1].set_y (effective_height() + canvas_border);
696 spts[2].set_x (effective_width() + canvas_border);
697 spts[2].set_y (effective_height() + canvas_border);
701 // GTK2FIX some odd math to fix up here
703 size_t last_spt = (npoints + 3) - 1;
705 for (size_t i = 0; i < npoints; ++i) {
709 pts[i].set_x (canvas_border + i);
710 pts[i].set_y (y_coordinate (y));
712 spts[last_spt - i].set_x (canvas_border + i);
713 spts[last_spt - i].set_y (pts[i].get_y());
716 fade[current].line->property_points() = pts;
717 fade[current].shading->property_points() = spts;
719 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[current].waves.begin(); i != fade[current].waves.end(); ++i) {
720 (*i)->property_gain_src() = &fade[current].gain_curve;
725 CrossfadeEditor::apply_preset (Preset *preset)
727 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
731 fade[current].points.clear ();
733 for (Preset::iterator i = preset->begin(); i != preset->end(); ++i) {
734 Point* p = make_point ();
735 p->move_to (x_coordinate ((*i).x), y_coordinate ((*i).y),
737 fade[current].points.push_back (p);
744 CrossfadeEditor::apply ()
750 CrossfadeEditor::_apply_to (Crossfade* xf)
752 ARDOUR::Curve& in (xf->fade_in());
753 ARDOUR::Curve& out (xf->fade_out());
758 ARDOUR::Curve::const_iterator the_end = in.const_end();
761 double firstx = (*in.begin())->when;
762 double endx = (*the_end)->when;
763 double miny = in.get_min_y ();
764 double maxy = in.get_max_y ();
769 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
771 double when = firstx + ((*i)->x * (endx - firstx));
772 double value = (*i)->y; // miny + ((*i)->y * (maxy - miny));
773 in.add (when, value);
778 the_end = out.const_end();
781 firstx = (*out.begin())->when;
782 endx = (*the_end)->when;
783 miny = out.get_min_y ();
784 maxy = out.get_max_y ();
789 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
791 double when = firstx + ((*i)->x * (endx - firstx));
792 double value = (*i)->y; // miny + ((*i)->y * (maxy - miny));
793 out.add (when, value);
801 CrossfadeEditor::setup (Crossfade* xfade)
804 xfade->set_active (true);
805 xfade->fade_in().solve ();
806 xfade->fade_out().solve ();
810 CrossfadeEditor::clear ()
812 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
816 fade[current].points.clear ();
822 CrossfadeEditor::reset ()
824 set (xfade.fade_in(), In);
825 set (xfade.fade_out(), Out);
829 CrossfadeEditor::build_presets ()
833 fade_in_presets = new Presets;
834 fade_out_presets = new Presets;
837 p = new Preset ("hiin.xpm");
838 p->push_back (PresetPoint (0, 0));
839 p->push_back (PresetPoint (0.0207373, 0.197222));
840 p->push_back (PresetPoint (0.0645161, 0.525));
841 p->push_back (PresetPoint (0.152074, 0.802778));
842 p->push_back (PresetPoint (0.276498, 0.919444));
843 p->push_back (PresetPoint (0.481567, 0.980556));
844 p->push_back (PresetPoint (0.767281, 1));
845 p->push_back (PresetPoint (1, 1));
846 fade_in_presets->push_back (p);
848 p = new Preset ("loin.xpm");
849 p->push_back (PresetPoint (0, 0));
850 p->push_back (PresetPoint (0.389401, 0.0333333));
851 p->push_back (PresetPoint (0.629032, 0.0861111));
852 p->push_back (PresetPoint (0.829493, 0.233333));
853 p->push_back (PresetPoint (0.9447, 0.483333));
854 p->push_back (PresetPoint (0.976959, 0.697222));
855 p->push_back (PresetPoint (1, 1));
856 fade_in_presets->push_back (p);
858 p = new Preset ("regin.xpm");
859 p->push_back (PresetPoint (0, 0));
860 p->push_back (PresetPoint (0.0737327, 0.308333));
861 p->push_back (PresetPoint (0.246544, 0.658333));
862 p->push_back (PresetPoint (0.470046, 0.886111));
863 p->push_back (PresetPoint (0.652074, 0.972222));
864 p->push_back (PresetPoint (0.771889, 0.988889));
865 p->push_back (PresetPoint (1, 1));
866 fade_in_presets->push_back (p);
868 p = new Preset ("regin2.xpm");
869 p->push_back (PresetPoint (0, 0));
870 p->push_back (PresetPoint (0.304147, 0.0694444));
871 p->push_back (PresetPoint (0.529954, 0.152778));
872 p->push_back (PresetPoint (0.725806, 0.333333));
873 p->push_back (PresetPoint (0.847926, 0.558333));
874 p->push_back (PresetPoint (0.919355, 0.730556));
875 p->push_back (PresetPoint (1, 1));
876 fade_in_presets->push_back (p);
878 p = new Preset ("linin.xpm");
879 p->push_back (PresetPoint (0, 0));
880 p->push_back (PresetPoint (1, 1));
881 fade_in_presets->push_back (p);
885 p = new Preset ("hiout.xpm");
886 p->push_back (PresetPoint (0, 1));
887 p->push_back (PresetPoint (0.305556, 1));
888 p->push_back (PresetPoint (0.548611, 0.991736));
889 p->push_back (PresetPoint (0.759259, 0.931129));
890 p->push_back (PresetPoint (0.918981, 0.68595));
891 p->push_back (PresetPoint (0.976852, 0.22865));
892 p->push_back (PresetPoint (1, 0));
893 fade_out_presets->push_back (p);
895 p = new Preset ("regout.xpm");
896 p->push_back (PresetPoint (0, 1));
897 p->push_back (PresetPoint (0.228111, 0.988889));
898 p->push_back (PresetPoint (0.347926, 0.972222));
899 p->push_back (PresetPoint (0.529954, 0.886111));
900 p->push_back (PresetPoint (0.753456, 0.658333));
901 p->push_back (PresetPoint (0.9262673, 0.308333));
902 p->push_back (PresetPoint (1, 0));
903 fade_out_presets->push_back (p);
905 p = new Preset ("loout.xpm");
906 p->push_back (PresetPoint (0, 1));
907 p->push_back (PresetPoint (0.023041, 0.697222));
908 p->push_back (PresetPoint (0.0553, 0.483333));
909 p->push_back (PresetPoint (0.170507, 0.233333));
910 p->push_back (PresetPoint (0.370968, 0.0861111));
911 p->push_back (PresetPoint (0.610599, 0.0333333));
912 p->push_back (PresetPoint (1, 0));
913 fade_out_presets->push_back (p);
915 p = new Preset ("regout2.xpm");
916 p->push_back (PresetPoint (0, 1));
917 p->push_back (PresetPoint (0.080645, 0.730556));
918 p->push_back (PresetPoint (0.277778, 0.289256));
919 p->push_back (PresetPoint (0.470046, 0.152778));
920 p->push_back (PresetPoint (0.695853, 0.0694444));
921 p->push_back (PresetPoint (1, 0));
922 fade_out_presets->push_back (p);
924 p = new Preset ("linout.xpm");
925 p->push_back (PresetPoint (0, 1));
926 p->push_back (PresetPoint (1, 0));
927 fade_out_presets->push_back (p);
931 CrossfadeEditor::curve_select_clicked (WhichFade wf)
937 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) {
938 (*i)->property_wave_color() = color_map[cSelectedCrossfadeEditorWave];
941 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) {
942 (*i)->property_wave_color() = color_map[cCrossfadeEditorWave];
945 fade[In].line->property_fill_color_rgba() = color_map[cSelectedCrossfadeEditorLine];
946 fade[Out].line->property_fill_color_rgba() = color_map[cCrossfadeEditorLine];
947 fade[Out].shading->hide();
948 fade[In].shading->show();
950 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
954 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
958 for (vector<Button*>::iterator i = fade_out_buttons.begin(); i != fade_out_buttons.end(); ++i) {
959 (*i)->set_sensitive (false);
962 for (vector<Button*>::iterator i = fade_in_buttons.begin(); i != fade_in_buttons.end(); ++i) {
963 (*i)->set_sensitive (true);
968 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) {
969 (*i)->property_wave_color() = color_map[cCrossfadeEditorWave];
972 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) {
973 (*i)->property_wave_color() = color_map[cSelectedCrossfadeEditorWave];
976 fade[Out].line->property_fill_color_rgba() = color_map[cSelectedCrossfadeEditorLine];
977 fade[In].line->property_fill_color_rgba() = color_map[cCrossfadeEditorLine];
978 fade[In].shading->hide();
979 fade[Out].shading->show();
981 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
985 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
989 for (vector<Button*>::iterator i = fade_out_buttons.begin(); i != fade_out_buttons.end(); ++i) {
990 (*i)->set_sensitive (true);
993 for (vector<Button*>::iterator i = fade_in_buttons.begin(); i != fade_in_buttons.end(); ++i) {
994 (*i)->set_sensitive (false);
1001 CrossfadeEditor::x_coordinate (double& xfract) const
1003 xfract = min (1.0, xfract);
1004 xfract = max (0.0, xfract);
1006 return canvas_border + (xfract * effective_width());
1010 CrossfadeEditor::y_coordinate (double& yfract) const
1012 yfract = min (1.0, yfract);
1013 yfract = max (0.0, yfract);
1015 return (canvas->get_allocation().get_height() - (canvas_border)) - (yfract * effective_height());
1019 CrossfadeEditor::make_waves (boost::shared_ptr<AudioRegion> region, WhichFade which)
1022 uint32_t nchans = region->n_channels();
1027 color = color_map[cSelectedCrossfadeEditorWave];
1029 color = color_map[cCrossfadeEditorWave];
1032 ht = canvas->get_allocation().get_height() / (double) nchans;
1033 spu = xfade.length() / (double) effective_width();
1035 for (uint32_t n = 0; n < nchans; ++n) {
1037 gdouble yoff = n * ht;
1039 if (region->source(n)->peaks_ready (bind (mem_fun(*this, &CrossfadeEditor::peaks_ready), region, which), peaks_ready_connection)) {
1041 WaveView* waveview = new WaveView (*(canvas->root()));
1043 waveview->property_data_src() = region.get();
1044 waveview->property_cache_updater() = true;
1045 waveview->property_cache() = WaveView::create_cache();
1046 waveview->property_channel() = n;
1047 waveview->property_length_function() = (void*) region_length_from_c;
1048 waveview->property_sourcefile_length_function() = (void*) sourcefile_length_from_c;
1049 waveview->property_peak_function() = (void*) region_read_peaks_from_c;
1050 waveview->property_gain_function() = (void*) curve_get_vector_from_c;
1051 waveview->property_gain_src() = &fade[which].gain_curve;
1052 waveview->property_x() = canvas_border;
1053 waveview->property_y() = yoff;
1054 waveview->property_height() = ht;
1055 waveview->property_samples_per_unit() = spu;
1056 waveview->property_amplitude_above_axis() = 2.0;
1057 waveview->property_wave_color() = color;
1059 waveview->lower_to_bottom();
1060 fade[which].waves.push_back (waveview);
1064 toplevel->lower_to_bottom();
1068 CrossfadeEditor::peaks_ready (boost::shared_ptr<AudioRegion> r, WhichFade which)
1070 /* this should never be called, because the peak files for an xfade
1071 will be ready by the time we want them. but our API forces us
1072 to provide this, so ..
1074 peaks_ready_connection.disconnect ();
1075 make_waves (r, which);
1079 CrossfadeEditor::audition_both ()
1081 AudioPlaylist& pl (session.the_auditioner()->prepare_playlist());
1085 nframes_t left_start_offset;
1086 nframes_t right_length;
1087 nframes_t left_length;
1089 if (preroll_button.get_active()) {
1090 preroll = ARDOUR_UI::instance()->preroll_clock.current_duration ();
1095 if (postroll_button.get_active()) {
1096 postroll = ARDOUR_UI::instance()->postroll_clock.current_duration ();
1101 if ((left_start_offset = xfade.out()->length() - xfade.length()) >= preroll) {
1102 left_start_offset -= preroll;
1107 if ((left_length = xfade.length()) < xfade.out()->length() - left_start_offset) {
1111 right_length = xfade.length();
1113 if (xfade.in()->length() - right_length < postroll) {
1114 right_length += postroll;
1117 boost::shared_ptr<AudioRegion> left (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade.out(), left_start_offset, left_length, "xfade out",
1118 0, Region::DefaultFlags, false)));
1119 boost::shared_ptr<AudioRegion> right (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade.in(), 0, right_length, "xfade in",
1120 0, Region::DefaultFlags, false)));
1122 pl.add_region (left, 0);
1123 pl.add_region (right, 1+preroll);
1125 /* there is only one ... */
1127 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1129 session.audition_playlist ();
1133 CrossfadeEditor::audition_left_dry ()
1135 boost::shared_ptr<AudioRegion> left (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade.out(), xfade.out()->length() - xfade.length(), xfade.length(), "xfade left",
1136 0, Region::DefaultFlags, false)));
1138 session.audition_region (left);
1142 CrossfadeEditor::audition_left ()
1144 AudioPlaylist& pl (session.the_auditioner()->prepare_playlist());
1146 boost::shared_ptr<AudioRegion> left (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade.out(), xfade.out()->length() - xfade.length(), xfade.length(), "xfade left",
1147 0, Region::DefaultFlags, false)));
1148 boost::shared_ptr<AudioRegion> right (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade.in(), 0, xfade.length(), "xfade in",
1149 0, Region::DefaultFlags, false)));
1151 pl.add_region (left, 0);
1152 pl.add_region (right, 1);
1154 right->set_muted (true);
1156 /* there is only one ... */
1158 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1160 session.audition_playlist ();
1162 /* memory leak for regions */
1166 CrossfadeEditor::audition_right_dry ()
1168 boost::shared_ptr<AudioRegion> right (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade.in(), 0, xfade.length(), "xfade in",
1169 0, Region::DefaultFlags, false)));
1170 session.audition_region (right);
1174 CrossfadeEditor::audition_right ()
1176 AudioPlaylist& pl (session.the_auditioner()->prepare_playlist());
1178 boost::shared_ptr<AudioRegion> left (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade.out(), xfade.out()->length() - xfade.length(), xfade.length(), "xfade out",
1179 0, Region::DefaultFlags, false)));
1180 boost::shared_ptr<AudioRegion> right (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade.out(), 0, xfade.length(), "xfade out",
1181 0, Region::DefaultFlags, false)));
1183 pl.add_region (left, 0);
1184 pl.add_region (right, 1);
1186 left->set_muted (true);
1188 /* there is only one ... */
1190 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1192 session.audition_playlist ();
1196 CrossfadeEditor::cancel_audition ()
1198 session.cancel_audition ();
1202 CrossfadeEditor::audition_toggled ()
1206 if ((x = audition_both_button.get_active ()) != session.is_auditioning()) {
1217 CrossfadeEditor::audition_right_toggled ()
1221 if ((x = audition_right_button.get_active ()) != session.is_auditioning()) {
1232 CrossfadeEditor::audition_right_dry_toggled ()
1236 if ((x = audition_right_dry_button.get_active ()) != session.is_auditioning()) {
1239 audition_right_dry ();
1247 CrossfadeEditor::audition_left_toggled ()
1251 if ((x = audition_left_button.get_active ()) != session.is_auditioning()) {
1262 CrossfadeEditor::audition_left_dry_toggled ()
1266 if ((x = audition_left_dry_button.get_active ()) != session.is_auditioning()) {
1269 audition_left_dry ();