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, boost::shared_ptr<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 (X_("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 size_t last_spt = (npoints + 3) - 1;
703 for (size_t i = 0; i < npoints; ++i) {
707 pts[i].set_x (canvas_border + i);
708 pts[i].set_y (y_coordinate (y));
710 spts[last_spt - i].set_x (canvas_border + i);
711 spts[last_spt - i].set_y (pts[i].get_y());
714 fade[current].line->property_points() = pts;
715 fade[current].shading->property_points() = spts;
717 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[current].waves.begin(); i != fade[current].waves.end(); ++i) {
718 (*i)->property_gain_src() = &fade[current].gain_curve;
723 CrossfadeEditor::apply_preset (Preset *preset)
725 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
729 fade[current].points.clear ();
731 for (Preset::iterator i = preset->begin(); i != preset->end(); ++i) {
732 Point* p = make_point ();
733 p->move_to (x_coordinate ((*i).x), y_coordinate ((*i).y),
735 fade[current].points.push_back (p);
742 CrossfadeEditor::apply ()
748 CrossfadeEditor::_apply_to (boost::shared_ptr<Crossfade> xf)
750 ARDOUR::Curve& in (xf->fade_in());
751 ARDOUR::Curve& out (xf->fade_out());
756 ARDOUR::Curve::const_iterator the_end = in.const_end();
759 double firstx = (*in.begin())->when;
760 double endx = (*the_end)->when;
761 double miny = in.get_min_y ();
762 double maxy = in.get_max_y ();
767 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
769 double when = firstx + ((*i)->x * (endx - firstx));
770 double value = (*i)->y; // miny + ((*i)->y * (maxy - miny));
771 in.add (when, value);
776 the_end = out.const_end();
779 firstx = (*out.begin())->when;
780 endx = (*the_end)->when;
781 miny = out.get_min_y ();
782 maxy = out.get_max_y ();
787 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
789 double when = firstx + ((*i)->x * (endx - firstx));
790 double value = (*i)->y; // miny + ((*i)->y * (maxy - miny));
791 out.add (when, value);
799 CrossfadeEditor::setup (boost::shared_ptr<Crossfade> xfade)
802 xfade->set_active (true);
803 xfade->fade_in().solve ();
804 xfade->fade_out().solve ();
808 CrossfadeEditor::clear ()
810 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
814 fade[current].points.clear ();
820 CrossfadeEditor::reset ()
822 set (xfade->fade_in(), In);
823 set (xfade->fade_out(), Out);
827 CrossfadeEditor::build_presets ()
831 fade_in_presets = new Presets;
832 fade_out_presets = new Presets;
835 p = new Preset ("hiin.xpm");
836 p->push_back (PresetPoint (0, 0));
837 p->push_back (PresetPoint (0.0207373, 0.197222));
838 p->push_back (PresetPoint (0.0645161, 0.525));
839 p->push_back (PresetPoint (0.152074, 0.802778));
840 p->push_back (PresetPoint (0.276498, 0.919444));
841 p->push_back (PresetPoint (0.481567, 0.980556));
842 p->push_back (PresetPoint (0.767281, 1));
843 p->push_back (PresetPoint (1, 1));
844 fade_in_presets->push_back (p);
846 p = new Preset ("loin.xpm");
847 p->push_back (PresetPoint (0, 0));
848 p->push_back (PresetPoint (0.389401, 0.0333333));
849 p->push_back (PresetPoint (0.629032, 0.0861111));
850 p->push_back (PresetPoint (0.829493, 0.233333));
851 p->push_back (PresetPoint (0.9447, 0.483333));
852 p->push_back (PresetPoint (0.976959, 0.697222));
853 p->push_back (PresetPoint (1, 1));
854 fade_in_presets->push_back (p);
856 p = new Preset ("regin.xpm");
857 p->push_back (PresetPoint (0, 0));
858 p->push_back (PresetPoint (0.0737327, 0.308333));
859 p->push_back (PresetPoint (0.246544, 0.658333));
860 p->push_back (PresetPoint (0.470046, 0.886111));
861 p->push_back (PresetPoint (0.652074, 0.972222));
862 p->push_back (PresetPoint (0.771889, 0.988889));
863 p->push_back (PresetPoint (1, 1));
864 fade_in_presets->push_back (p);
866 p = new Preset ("regin2.xpm");
867 p->push_back (PresetPoint (0, 0));
868 p->push_back (PresetPoint (0.304147, 0.0694444));
869 p->push_back (PresetPoint (0.529954, 0.152778));
870 p->push_back (PresetPoint (0.725806, 0.333333));
871 p->push_back (PresetPoint (0.847926, 0.558333));
872 p->push_back (PresetPoint (0.919355, 0.730556));
873 p->push_back (PresetPoint (1, 1));
874 fade_in_presets->push_back (p);
876 p = new Preset ("linin.xpm");
877 p->push_back (PresetPoint (0, 0));
878 p->push_back (PresetPoint (1, 1));
879 fade_in_presets->push_back (p);
883 p = new Preset ("hiout.xpm");
884 p->push_back (PresetPoint (0, 1));
885 p->push_back (PresetPoint (0.305556, 1));
886 p->push_back (PresetPoint (0.548611, 0.991736));
887 p->push_back (PresetPoint (0.759259, 0.931129));
888 p->push_back (PresetPoint (0.918981, 0.68595));
889 p->push_back (PresetPoint (0.976852, 0.22865));
890 p->push_back (PresetPoint (1, 0));
891 fade_out_presets->push_back (p);
893 p = new Preset ("regout.xpm");
894 p->push_back (PresetPoint (0, 1));
895 p->push_back (PresetPoint (0.228111, 0.988889));
896 p->push_back (PresetPoint (0.347926, 0.972222));
897 p->push_back (PresetPoint (0.529954, 0.886111));
898 p->push_back (PresetPoint (0.753456, 0.658333));
899 p->push_back (PresetPoint (0.9262673, 0.308333));
900 p->push_back (PresetPoint (1, 0));
901 fade_out_presets->push_back (p);
903 p = new Preset ("loout.xpm");
904 p->push_back (PresetPoint (0, 1));
905 p->push_back (PresetPoint (0.023041, 0.697222));
906 p->push_back (PresetPoint (0.0553, 0.483333));
907 p->push_back (PresetPoint (0.170507, 0.233333));
908 p->push_back (PresetPoint (0.370968, 0.0861111));
909 p->push_back (PresetPoint (0.610599, 0.0333333));
910 p->push_back (PresetPoint (1, 0));
911 fade_out_presets->push_back (p);
913 p = new Preset ("regout2.xpm");
914 p->push_back (PresetPoint (0, 1));
915 p->push_back (PresetPoint (0.080645, 0.730556));
916 p->push_back (PresetPoint (0.277778, 0.289256));
917 p->push_back (PresetPoint (0.470046, 0.152778));
918 p->push_back (PresetPoint (0.695853, 0.0694444));
919 p->push_back (PresetPoint (1, 0));
920 fade_out_presets->push_back (p);
922 p = new Preset ("linout.xpm");
923 p->push_back (PresetPoint (0, 1));
924 p->push_back (PresetPoint (1, 0));
925 fade_out_presets->push_back (p);
929 CrossfadeEditor::curve_select_clicked (WhichFade wf)
935 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) {
936 (*i)->property_wave_color() = color_map[cSelectedCrossfadeEditorWave];
939 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) {
940 (*i)->property_wave_color() = color_map[cCrossfadeEditorWave];
943 fade[In].line->property_fill_color_rgba() = color_map[cSelectedCrossfadeEditorLine];
944 fade[Out].line->property_fill_color_rgba() = color_map[cCrossfadeEditorLine];
945 fade[Out].shading->hide();
946 fade[In].shading->show();
948 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
952 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
956 for (vector<Button*>::iterator i = fade_out_buttons.begin(); i != fade_out_buttons.end(); ++i) {
957 (*i)->set_sensitive (false);
960 for (vector<Button*>::iterator i = fade_in_buttons.begin(); i != fade_in_buttons.end(); ++i) {
961 (*i)->set_sensitive (true);
966 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) {
967 (*i)->property_wave_color() = color_map[cCrossfadeEditorWave];
970 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) {
971 (*i)->property_wave_color() = color_map[cSelectedCrossfadeEditorWave];
974 fade[Out].line->property_fill_color_rgba() = color_map[cSelectedCrossfadeEditorLine];
975 fade[In].line->property_fill_color_rgba() = color_map[cCrossfadeEditorLine];
976 fade[In].shading->hide();
977 fade[Out].shading->show();
979 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
983 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
987 for (vector<Button*>::iterator i = fade_out_buttons.begin(); i != fade_out_buttons.end(); ++i) {
988 (*i)->set_sensitive (true);
991 for (vector<Button*>::iterator i = fade_in_buttons.begin(); i != fade_in_buttons.end(); ++i) {
992 (*i)->set_sensitive (false);
999 CrossfadeEditor::x_coordinate (double& xfract) const
1001 xfract = min (1.0, xfract);
1002 xfract = max (0.0, xfract);
1004 return canvas_border + (xfract * effective_width());
1008 CrossfadeEditor::y_coordinate (double& yfract) const
1010 yfract = min (1.0, yfract);
1011 yfract = max (0.0, yfract);
1013 return (canvas->get_allocation().get_height() - (canvas_border)) - (yfract * effective_height());
1017 CrossfadeEditor::make_waves (boost::shared_ptr<AudioRegion> region, WhichFade which)
1020 uint32_t nchans = region->n_channels();
1025 color = color_map[cSelectedCrossfadeEditorWave];
1027 color = color_map[cCrossfadeEditorWave];
1030 ht = canvas->get_allocation().get_height() / (double) nchans;
1031 spu = xfade->length() / (double) effective_width();
1033 for (uint32_t n = 0; n < nchans; ++n) {
1035 gdouble yoff = n * ht;
1037 if (region->audio_source(n)->peaks_ready (bind (mem_fun(*this, &CrossfadeEditor::peaks_ready), region, which), peaks_ready_connection)) {
1038 WaveView* waveview = new WaveView (*(canvas->root()));
1040 waveview->property_data_src() = region.get();
1041 waveview->property_cache_updater() = true;
1042 waveview->property_cache() = WaveView::create_cache();
1043 waveview->property_channel() = n;
1044 waveview->property_length_function() = (void*) region_length_from_c;
1045 waveview->property_sourcefile_length_function() = (void*) sourcefile_length_from_c;
1046 waveview->property_peak_function() = (void*) region_read_peaks_from_c;
1047 waveview->property_gain_function() = (void*) curve_get_vector_from_c;
1048 waveview->property_gain_src() = &fade[which].gain_curve;
1049 waveview->property_x() = canvas_border;
1050 waveview->property_y() = yoff;
1051 waveview->property_height() = ht;
1052 waveview->property_samples_per_unit() = spu;
1053 waveview->property_amplitude_above_axis() = 2.0;
1054 waveview->property_wave_color() = color;
1056 waveview->lower_to_bottom();
1057 fade[which].waves.push_back (waveview);
1061 toplevel->lower_to_bottom();
1065 CrossfadeEditor::peaks_ready (boost::shared_ptr<AudioRegion> r, WhichFade which)
1067 /* this should never be called, because the peak files for an xfade
1068 will be ready by the time we want them. but our API forces us
1069 to provide this, so ..
1071 peaks_ready_connection.disconnect ();
1072 make_waves (r, which);
1076 CrossfadeEditor::audition_both ()
1078 AudioPlaylist& pl (session.the_auditioner()->prepare_playlist());
1082 nframes_t left_start_offset;
1083 nframes_t right_length;
1084 nframes_t left_length;
1086 if (preroll_button.get_active()) {
1087 preroll = ARDOUR_UI::instance()->preroll_clock.current_duration ();
1092 if (postroll_button.get_active()) {
1093 postroll = ARDOUR_UI::instance()->postroll_clock.current_duration ();
1098 if ((left_start_offset = xfade->out()->length() - xfade->length()) >= preroll) {
1099 left_start_offset -= preroll;
1104 if ((left_length = xfade->length()) < xfade->out()->length() - left_start_offset) {
1108 right_length = xfade->length();
1110 if (xfade->in()->length() - right_length < postroll) {
1111 right_length += postroll;
1114 boost::shared_ptr<AudioRegion> left (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade->out(), left_start_offset, left_length, "xfade out",
1115 0, Region::DefaultFlags, false)));
1116 boost::shared_ptr<AudioRegion> right (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade->in(), 0, right_length, "xfade in",
1117 0, Region::DefaultFlags, false)));
1119 pl.add_region (left, 0);
1120 pl.add_region (right, 1+preroll);
1122 /* there is only one ... */
1124 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1126 session.audition_playlist ();
1130 CrossfadeEditor::audition_left_dry ()
1132 boost::shared_ptr<AudioRegion> left (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade->out(), xfade->out()->length() - xfade->length(), xfade->length(), "xfade left",
1133 0, Region::DefaultFlags, false)));
1135 session.audition_region (left);
1139 CrossfadeEditor::audition_left ()
1141 AudioPlaylist& pl (session.the_auditioner()->prepare_playlist());
1143 boost::shared_ptr<AudioRegion> left (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade->out(), xfade->out()->length() - xfade->length(), xfade->length(), "xfade left",
1144 0, Region::DefaultFlags, false)));
1145 boost::shared_ptr<AudioRegion> right (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade->in(), 0, xfade->length(), "xfade in",
1146 0, Region::DefaultFlags, false)));
1148 pl.add_region (left, 0);
1149 pl.add_region (right, 1);
1151 right->set_muted (true);
1153 /* there is only one ... */
1155 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1157 session.audition_playlist ();
1159 /* memory leak for regions */
1163 CrossfadeEditor::audition_right_dry ()
1165 boost::shared_ptr<AudioRegion> right (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade->in(), 0, xfade->length(), "xfade in",
1166 0, Region::DefaultFlags, false)));
1167 session.audition_region (right);
1171 CrossfadeEditor::audition_right ()
1173 AudioPlaylist& pl (session.the_auditioner()->prepare_playlist());
1175 boost::shared_ptr<AudioRegion> left (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade->out(), xfade->out()->length() - xfade->length(), xfade->length(), "xfade out",
1176 0, Region::DefaultFlags, false)));
1177 boost::shared_ptr<AudioRegion> right (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade->out(), 0, xfade->length(), "xfade out",
1178 0, Region::DefaultFlags, false)));
1180 pl.add_region (left, 0);
1181 pl.add_region (right, 1);
1183 left->set_muted (true);
1185 /* there is only one ... */
1187 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1189 session.audition_playlist ();
1193 CrossfadeEditor::cancel_audition ()
1195 session.cancel_audition ();
1199 CrossfadeEditor::audition_toggled ()
1203 if ((x = audition_both_button.get_active ()) != session.is_auditioning()) {
1214 CrossfadeEditor::audition_right_toggled ()
1218 if ((x = audition_right_button.get_active ()) != session.is_auditioning()) {
1229 CrossfadeEditor::audition_right_dry_toggled ()
1233 if ((x = audition_right_dry_button.get_active ()) != session.is_auditioning()) {
1236 audition_right_dry ();
1244 CrossfadeEditor::audition_left_toggled ()
1248 if ((x = audition_left_button.get_active ()) != session.is_auditioning()) {
1259 CrossfadeEditor::audition_left_dry_toggled ()
1263 if ((x = audition_left_dry_button.get_active ()) != session.is_auditioning()) {
1266 audition_left_dry ();