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.
22 #include <sigc++/bind.h>
24 #include <gtkmm/frame.h>
25 #include <gtkmm/image.h>
26 #include <gtkmm/scrolledwindow.h>
28 #include <libgnomecanvasmm/line.h>
30 #include <ardour/automation_event.h>
31 #include <ardour/curve.h>
32 #include <ardour/crossfade.h>
33 #include <ardour/session.h>
34 #include <ardour/auditioner.h>
35 #include <ardour/audioplaylist.h>
36 #include <ardour/audiosource.h>
37 #include <ardour/playlist_templates.h>
38 #include <ardour/region_factory.h>
40 #include <gtkmm2ext/gtk_ui.h>
42 #include "ardour_ui.h"
43 #include "crossfade_edit.h"
44 #include "rgb_macros.h"
47 #include "gui_thread.h"
48 #include "canvas_impl.h"
49 #include "simplerect.h"
54 using namespace ARDOUR;
58 using namespace Editing;
62 const int32_t CrossfadeEditor::Point::size = 7;
63 const double CrossfadeEditor::canvas_border = 10;
64 CrossfadeEditor::Presets* CrossfadeEditor::fade_in_presets = 0;
65 CrossfadeEditor::Presets* CrossfadeEditor::fade_out_presets = 0;
67 CrossfadeEditor::Half::Half ()
69 normative_curve (0.0, 1.0, 1.0, true),
70 gain_curve (0.0, 2.0, 1.0, true)
74 CrossfadeEditor::CrossfadeEditor (Session& s, boost::shared_ptr<Crossfade> xf, double my, double mxy)
75 : ArdourDialog (_("ardour: x-fade edit")),
78 clear_button (_("Clear")),
79 revert_button (_("Reset")),
80 audition_both_button (_("Fade")),
81 audition_left_dry_button (_("Out (dry)")),
82 audition_left_button (_("Out")),
83 audition_right_dry_button (_("In (dry)")),
84 audition_right_button (_("In")),
86 preroll_button (_("With Pre-roll")),
87 postroll_button (_("With Post-roll")),
93 fade_out_table (3, 3),
95 select_in_button (_("Fade In")),
96 select_out_button (_("Fade Out"))
98 set_wmclass (X_("ardour_automationedit"), "Ardour");
99 set_name ("CrossfadeEditWindow");
100 set_position (Gtk::WIN_POS_MOUSE);
102 add_accel_group (ActionManager::ui_manager->get_accel_group());
104 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
106 RadioButtonGroup sel_but_group = select_in_button.get_group();
107 select_out_button.set_group (sel_but_group);
108 select_out_button.set_mode (false);
109 select_in_button.set_mode (false);
111 get_action_area()->set_layout(BUTTONBOX_SPREAD);
112 get_action_area()->pack_start(clear_button);
113 get_action_area()->pack_start(revert_button);
114 cancel_button = add_button ("Cancel", RESPONSE_CANCEL);
115 ok_button = add_button ("OK", RESPONSE_ACCEPT);
117 if (fade_in_presets == 0) {
121 point_grabbed = false;
124 canvas = new ArdourCanvas::CanvasAA ();
125 canvas->signal_size_allocate().connect (mem_fun(*this, &CrossfadeEditor::canvas_allocation));
126 canvas->set_size_request (425, 200);
128 toplevel = new ArdourCanvas::SimpleRect (*(canvas->root()));
129 toplevel->property_x1() = 0.0;
130 toplevel->property_y1() = 0.0;
131 toplevel->property_x2() = 10.0;
132 toplevel->property_y2() = 10.0;
133 toplevel->property_fill() = true;
134 toplevel->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorBase.get();
135 toplevel->property_outline_pixels() = 0;
136 toplevel->signal_event().connect (mem_fun (*this, &CrossfadeEditor::canvas_event));
138 fade[Out].line = new ArdourCanvas::Line (*(canvas->root()));
139 fade[Out].line->property_width_pixels() = 1;
140 fade[Out].line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorLine.get();
142 fade[Out].shading = new ArdourCanvas::Polygon (*(canvas->root()));
143 fade[Out].shading->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorLineShading.get();
145 fade[In].line = new ArdourCanvas::Line (*(canvas->root()));
146 fade[In].line->property_width_pixels() = 1;
147 fade[In].line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorLine.get();
149 fade[In].shading = new ArdourCanvas::Polygon (*(canvas->root()));
150 fade[In].shading->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorLineShading.get();
152 fade[In].shading->signal_event().connect (mem_fun (*this, &CrossfadeEditor::canvas_event));
153 fade[In].line->signal_event().connect (mem_fun (*this, &CrossfadeEditor::curve_event));
154 fade[Out].shading->signal_event().connect (mem_fun (*this, &CrossfadeEditor::canvas_event));
155 fade[Out].line->signal_event().connect (mem_fun (*this, &CrossfadeEditor::curve_event));
157 select_in_button.set_name (X_("CrossfadeEditCurveButton"));
158 select_out_button.set_name (X_("CrossfadeEditCurveButton"));
160 select_in_button.signal_clicked().connect (bind (mem_fun (*this, &CrossfadeEditor::curve_select_clicked), In));
161 select_out_button.signal_clicked().connect (bind (mem_fun (*this, &CrossfadeEditor::curve_select_clicked), Out));
163 HBox* acbox = manage (new HBox);
165 audition_box.set_border_width (7);
166 audition_box.set_spacing (5);
167 audition_box.set_homogeneous (false);
168 audition_box.pack_start (audition_left_dry_button, false, false);
169 audition_box.pack_start (audition_left_button, false, false);
170 audition_box.pack_start (audition_both_button, false, false);
171 audition_box.pack_start (audition_right_button, false, false);
172 audition_box.pack_start (audition_right_dry_button, false, false);
174 Frame* audition_frame = manage (new Frame (_("Audition")));
176 audition_frame->set_name (X_("CrossfadeEditFrame"));
177 audition_frame->add (audition_box);
179 acbox->pack_start (*audition_frame, true, false);
181 Frame* canvas_frame = manage (new Frame);
182 canvas_frame->add (*canvas);
183 canvas_frame->set_shadow_type (Gtk::SHADOW_IN);
185 fade_in_table.attach (select_in_button, 0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND);
186 fade_out_table.attach (select_out_button, 0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND);
196 for (list<Preset*>::iterator i = fade_in_presets->begin(); i != fade_in_presets->end(); ++i) {
198 pxmap = manage (new Image (::get_icon ((*i)->image_name)));
199 pbutton = manage (new Button);
200 pbutton->add (*pxmap);
201 pbutton->set_name ("CrossfadeEditButton");
202 pbutton->signal_clicked().connect (bind (mem_fun(*this, &CrossfadeEditor::apply_preset), *i));
203 fade_in_table.attach (*pbutton, col, col+1, row, row+1);
204 fade_in_buttons.push_back (pbutton);
217 for (list<Preset*>::iterator i = fade_out_presets->begin(); i != fade_out_presets->end(); ++i) {
219 pxmap = manage (new Image (::get_icon ((*i)->image_name)));
220 pbutton = manage (new Button);
221 pbutton->add (*pxmap);
222 pbutton->set_name ("CrossfadeEditButton");
223 pbutton->signal_clicked().connect (bind (mem_fun(*this, &CrossfadeEditor::apply_preset), *i));
224 fade_out_table.attach (*pbutton, col, col+1, row, row+1);
225 fade_out_buttons.push_back (pbutton);
235 clear_button.set_name ("CrossfadeEditButton");
236 revert_button.set_name ("CrossfadeEditButton");
237 ok_button->set_name ("CrossfadeEditButton");
238 cancel_button->set_name ("CrossfadeEditButton");
239 preroll_button.set_name ("CrossfadeEditButton");
240 postroll_button.set_name ("CrossfadeEditButton");
241 audition_both_button.set_name ("CrossfadeEditAuditionButton");
242 audition_left_dry_button.set_name ("CrossfadeEditAuditionButton");
243 audition_left_button.set_name ("CrossfadeEditAuditionButton");
244 audition_right_dry_button.set_name ("CrossfadeEditAuditionButton");
245 audition_right_button.set_name ("CrossfadeEditAuditionButton");
247 clear_button.signal_clicked().connect (mem_fun(*this, &CrossfadeEditor::clear));
248 revert_button.signal_clicked().connect (mem_fun(*this, &CrossfadeEditor::reset));
249 audition_both_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_toggled));
250 audition_right_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_right_toggled));
251 audition_right_dry_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_right_dry_toggled));
252 audition_left_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_left_toggled));
253 audition_left_dry_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_left_dry_toggled));
255 roll_box.pack_start (preroll_button, false, false);
256 roll_box.pack_start (postroll_button, false, false);
258 Gtk::HBox* rcenter_box = manage (new HBox);
259 rcenter_box->pack_start (roll_box, true, false);
261 VBox* vpacker2 = manage (new (VBox));
263 vpacker2->set_border_width (12);
264 vpacker2->set_spacing (7);
265 vpacker2->pack_start (*acbox, false, false);
266 vpacker2->pack_start (*rcenter_box, false, false);
268 curve_button_box.set_spacing (7);
269 curve_button_box.pack_start (fade_out_table, false, false, 12);
270 curve_button_box.pack_start (*vpacker2, false, false, 12);
271 curve_button_box.pack_start (fade_in_table, false, false, 12);
273 get_vbox()->pack_start (*canvas_frame, true, true);
274 get_vbox()->pack_start (curve_button_box, false, false);
276 /* button to allow hackers to check the actual curve values */
278 // Button* foobut = manage (new Button ("dump"));
279 // foobut-.signal_clicked().connect (mem_fun(*this, &CrossfadeEditor::dump));
280 // vpacker.pack_start (*foobut, false, false);
283 set (xfade->fade_in(), In);
286 set (xfade->fade_out(), Out);
288 curve_select_clicked (In);
290 xfade->StateChanged.connect (mem_fun(*this, &CrossfadeEditor::xfade_changed));
292 session.AuditionActive.connect (mem_fun(*this, &CrossfadeEditor::audition_state_changed));
296 CrossfadeEditor::~CrossfadeEditor()
298 /* most objects will be destroyed when the toplevel window is. */
300 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
304 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
310 CrossfadeEditor::dump ()
312 for (AutomationList::iterator i = fade[Out].normative_curve.begin(); i != fade[Out].normative_curve.end(); ++i) {
313 cerr << (*i)->when << ' ' << (*i)->value << endl;
318 CrossfadeEditor::audition_state_changed (bool yn)
320 ENSURE_GUI_THREAD (bind (mem_fun(*this, &CrossfadeEditor::audition_state_changed), yn));
323 audition_both_button.set_active (false);
324 audition_left_button.set_active (false);
325 audition_right_button.set_active (false);
326 audition_left_dry_button.set_active (false);
327 audition_right_dry_button.set_active (false);
332 CrossfadeEditor::set (const ARDOUR::Curve& curve, WhichFade which)
335 ARDOUR::Curve::const_iterator the_end;
337 for (list<Point*>::iterator i = fade[which].points.begin(); i != fade[which].points.end(); ++i) {
341 fade[which].points.clear ();
342 fade[which].gain_curve.clear ();
343 fade[which].normative_curve.clear ();
349 the_end = curve.const_end();
352 firstx = (*curve.const_begin())->when;
353 endx = (*the_end)->when;
355 for (ARDOUR::Curve::const_iterator i = curve.const_begin(); i != curve.const_end(); ++i) {
357 double xfract = ((*i)->when - firstx) / (endx - firstx);
358 double yfract = ((*i)->value - miny) / (maxy - miny);
360 Point* p = make_point ();
362 p->move_to (x_coordinate (xfract), y_coordinate (yfract),
365 fade[which].points.push_back (p);
368 /* no need to sort because curve is already time-ordered */
372 swap (which, current);
374 swap (which, current);
378 CrossfadeEditor::curve_event (GdkEvent* event)
380 /* treat it like a toplevel event */
382 return canvas_event (event);
386 CrossfadeEditor::point_event (GdkEvent* event, Point* point)
389 if (point->curve != fade[current].line) {
393 switch (event->type) {
394 case GDK_BUTTON_PRESS:
395 point_grabbed = true;
397 case GDK_BUTTON_RELEASE:
398 point_grabbed = false;
400 if (Keyboard::is_delete_event (&event->button)) {
401 fade[current].points.remove (point);
408 case GDK_MOTION_NOTIFY:
412 /* can't drag first or last points horizontally */
414 if (point == fade[current].points.front() || point == fade[current].points.back()) {
417 new_x = (event->motion.x - canvas_border)/effective_width();
420 new_y = 1.0 - ((event->motion.y - canvas_border)/effective_height());
421 point->move_to (x_coordinate (new_x), y_coordinate (new_y),
433 CrossfadeEditor::canvas_event (GdkEvent* event)
435 switch (event->type) {
436 case GDK_BUTTON_PRESS:
437 add_control_point ((event->button.x - canvas_border)/effective_width(),
438 1.0 - ((event->button.y - canvas_border)/effective_height()));
447 CrossfadeEditor::Point::~Point()
452 CrossfadeEditor::Point*
453 CrossfadeEditor::make_point ()
455 Point* p = new Point;
457 p->box = new ArdourCanvas::SimpleRect (*(canvas->root()));
458 p->box->property_fill() = true;
459 p->box->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorPointFill.get();
460 p->box->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorPointOutline.get();
461 p->box->property_outline_pixels() = 1;
463 p->curve = fade[current].line;
465 p->box->signal_event().connect (bind (mem_fun (*this, &CrossfadeEditor::point_event), p));
471 CrossfadeEditor::add_control_point (double x, double y)
475 /* enforce end point x location */
477 if (fade[current].points.empty()) {
479 } else if (fade[current].points.size() == 1) {
483 Point* p = make_point ();
485 p->move_to (x_coordinate (x), y_coordinate (y), x, y);
487 fade[current].points.push_back (p);
488 fade[current].points.sort (cmp);
494 CrossfadeEditor::Point::move_to (double nx, double ny, double xfract, double yfract)
496 const double half_size = rint(size/2.0);
497 double x1 = nx - half_size;
498 double x2 = nx + half_size;
500 box->property_x1() = x1;
501 box->property_x2() = x2;
503 box->property_y1() = ny - half_size;
504 box->property_y2() = ny + half_size;
511 CrossfadeEditor::canvas_allocation (Gtk::Allocation& alloc)
514 toplevel->property_x1() = 0.0;
515 toplevel->property_y1() = 0.0;
516 toplevel->property_x2() = (double) canvas->get_allocation().get_width() + canvas_border;
517 toplevel->property_y2() = (double) canvas->get_allocation().get_height() + canvas_border;
520 canvas->set_scroll_region (0.0, 0.0,
521 canvas->get_allocation().get_width(),
522 canvas->get_allocation().get_height());
524 Point* end = make_point ();
527 if (fade[In].points.size() > 1) {
528 Point* old_end = fade[In].points.back();
529 fade[In].points.pop_back ();
530 end->move_to (x_coordinate (old_end->x),
531 y_coordinate (old_end->y),
532 old_end->x, old_end->y);
537 end->move_to (x_coordinate (x), y_coordinate (y), x, y);
541 fade[In].points.push_back (end);
542 fade[In].points.sort (cmp);
544 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
545 (*i)->move_to (x_coordinate((*i)->x), y_coordinate((*i)->y),
551 if (fade[Out].points.size() > 1) {
552 Point* old_end = fade[Out].points.back();
553 fade[Out].points.pop_back ();
554 end->move_to (x_coordinate (old_end->x),
555 y_coordinate (old_end->y),
556 old_end->x, old_end->y);
561 end->move_to (x_coordinate (x), y_coordinate (y), x, y);
565 fade[Out].points.push_back (end);
566 fade[Out].points.sort (cmp);
568 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
569 (*i)->move_to (x_coordinate ((*i)->x),
570 y_coordinate ((*i)->y),
574 WhichFade old_current = current;
579 current = old_current;
581 double spu = xfade->length() / (double) effective_width();
583 if (fade[In].waves.empty()) {
584 make_waves (xfade->in(), In);
587 if (fade[Out].waves.empty()) {
588 make_waves (xfade->out(), Out);
592 vector<ArdourCanvas::WaveView*>::iterator i;
595 ht = canvas->get_allocation().get_height() / xfade->in()->n_channels();
597 for (n = 0, i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i, ++n) {
602 (*i)->property_y() = yoff;
603 (*i)->property_height() = ht;
604 (*i)->property_samples_per_unit() = spu;
607 ht = canvas->get_allocation().get_height() / xfade->out()->n_channels();
609 for (n = 0, i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i, ++n) {
614 (*i)->property_y() = yoff;
615 (*i)->property_height() = ht;
616 (*i)->property_samples_per_unit() = spu;
623 CrossfadeEditor::xfade_changed (Change ignored)
625 set (xfade->fade_in(), In);
626 set (xfade->fade_out(), Out);
630 CrossfadeEditor::redraw ()
632 if (canvas->get_allocation().get_width() < 2) {
636 nframes_t len = xfade->length ();
638 fade[current].normative_curve.clear ();
639 fade[current].gain_curve.clear ();
641 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
642 fade[current].normative_curve.add ((*i)->x, (*i)->y);
645 offset = xfade->in()->start();
647 offset = xfade->out()->start()+xfade->out()->length()-xfade->length();
648 fade[current].gain_curve.add (((*i)->x * len) + offset, (*i)->y);
652 size_t npoints = (size_t) effective_width();
655 fade[current].normative_curve.get_vector (0, 1.0, vec, npoints);
657 ArdourCanvas::Points pts;
658 ArdourCanvas::Points spts;
660 while (pts.size() < npoints) {
661 pts.push_back (Gnome::Art::Point (0,0));
664 while (spts.size() < npoints + 3) {
665 spts.push_back (Gnome::Art::Point (0,0));
668 /* the shade coordinates *MUST* be in anti-clockwise order.
675 spts[0].set_x (canvas_border);
676 spts[0].set_y (effective_height() + canvas_border);
680 spts[1].set_x (effective_width() + canvas_border);
681 spts[1].set_y (effective_height() + canvas_border);
685 spts[2].set_x (effective_width() + canvas_border);
686 spts[2].set_y (canvas_border);
693 spts[0].set_x (canvas_border);
694 spts[0].set_y (canvas_border);
698 spts[1].set_x (canvas_border);
699 spts[1].set_y (effective_height() + canvas_border);
703 spts[2].set_x (effective_width() + canvas_border);
704 spts[2].set_y (effective_height() + canvas_border);
708 size_t last_spt = (npoints + 3) - 1;
710 for (size_t i = 0; i < npoints; ++i) {
714 pts[i].set_x (canvas_border + i);
715 pts[i].set_y (y_coordinate (y));
717 spts[last_spt - i].set_x (canvas_border + i);
718 spts[last_spt - i].set_y (pts[i].get_y());
721 fade[current].line->property_points() = pts;
722 fade[current].shading->property_points() = spts;
724 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[current].waves.begin(); i != fade[current].waves.end(); ++i) {
725 (*i)->property_gain_src() = &fade[current].gain_curve;
730 CrossfadeEditor::apply_preset (Preset *preset)
733 WhichFade wf = find(fade_in_presets->begin(), fade_in_presets->end(), preset) != fade_in_presets->end() ? In : Out;
738 select_in_button.clicked();
740 select_out_button.clicked();
743 curve_select_clicked (wf);
746 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
750 fade[current].points.clear ();
752 for (Preset::iterator i = preset->begin(); i != preset->end(); ++i) {
753 Point* p = make_point ();
754 p->move_to (x_coordinate ((*i).x), y_coordinate ((*i).y),
756 fade[current].points.push_back (p);
763 CrossfadeEditor::apply ()
769 CrossfadeEditor::_apply_to (boost::shared_ptr<Crossfade> xf)
771 ARDOUR::Curve& in (xf->fade_in());
772 ARDOUR::Curve& out (xf->fade_out());
777 ARDOUR::Curve::const_iterator the_end = in.const_end();
780 double firstx = (*in.begin())->when;
781 double endx = (*the_end)->when;
782 double miny = in.get_min_y ();
783 double maxy = in.get_max_y ();
788 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
790 double when = firstx + ((*i)->x * (endx - firstx));
791 double value = (*i)->y; // miny + ((*i)->y * (maxy - miny));
792 in.add (when, value);
797 the_end = out.const_end();
800 firstx = (*out.begin())->when;
801 endx = (*the_end)->when;
802 miny = out.get_min_y ();
803 maxy = out.get_max_y ();
808 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
810 double when = firstx + ((*i)->x * (endx - firstx));
811 double value = (*i)->y; // miny + ((*i)->y * (maxy - miny));
812 out.add (when, value);
820 CrossfadeEditor::setup (boost::shared_ptr<Crossfade> xfade)
823 xfade->set_active (true);
824 xfade->fade_in().solve ();
825 xfade->fade_out().solve ();
829 CrossfadeEditor::clear ()
831 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
835 fade[current].points.clear ();
841 CrossfadeEditor::reset ()
843 set (xfade->fade_in(), In);
844 set (xfade->fade_out(), Out);
846 curve_select_clicked (current);
850 CrossfadeEditor::build_presets ()
854 fade_in_presets = new Presets;
855 fade_out_presets = new Presets;
858 // p = new Preset ("hiin.xpm");
859 p = new Preset ("crossfade_in_fast-cut");
860 p->push_back (PresetPoint (0, 0));
861 p->push_back (PresetPoint (0.0207373, 0.197222));
862 p->push_back (PresetPoint (0.0645161, 0.525));
863 p->push_back (PresetPoint (0.152074, 0.802778));
864 p->push_back (PresetPoint (0.276498, 0.919444));
865 p->push_back (PresetPoint (0.481567, 0.980556));
866 p->push_back (PresetPoint (0.767281, 1));
867 p->push_back (PresetPoint (1, 1));
868 fade_in_presets->push_back (p);
870 // p = new Preset ("loin.xpm");
871 p = new Preset ("crossfade_in_transition");
872 p->push_back (PresetPoint (0, 0));
873 p->push_back (PresetPoint (0.389401, 0.0333333));
874 p->push_back (PresetPoint (0.629032, 0.0861111));
875 p->push_back (PresetPoint (0.829493, 0.233333));
876 p->push_back (PresetPoint (0.9447, 0.483333));
877 p->push_back (PresetPoint (0.976959, 0.697222));
878 p->push_back (PresetPoint (1, 1));
879 fade_in_presets->push_back (p);
881 // p = new Preset ("regin.xpm");
882 p = new Preset ("crossfade_in_constant");
883 p->push_back (PresetPoint (0, 0));
884 p->push_back (PresetPoint (0.0737327, 0.308333));
885 p->push_back (PresetPoint (0.246544, 0.658333));
886 p->push_back (PresetPoint (0.470046, 0.886111));
887 p->push_back (PresetPoint (0.652074, 0.972222));
888 p->push_back (PresetPoint (0.771889, 0.988889));
889 p->push_back (PresetPoint (1, 1));
890 fade_in_presets->push_back (p);
892 // p = new Preset ("regin2.xpm");
893 p = new Preset ("crossfade_in_slow-cut");
894 p->push_back (PresetPoint (0, 0));
895 p->push_back (PresetPoint (0.304147, 0.0694444));
896 p->push_back (PresetPoint (0.529954, 0.152778));
897 p->push_back (PresetPoint (0.725806, 0.333333));
898 p->push_back (PresetPoint (0.847926, 0.558333));
899 p->push_back (PresetPoint (0.919355, 0.730556));
900 p->push_back (PresetPoint (1, 1));
901 fade_in_presets->push_back (p);
903 // p = new Preset ("linin.xpm");
904 p = new Preset ("crossfade_in_dipped");
905 p->push_back (PresetPoint (0, 0));
906 p->push_back (PresetPoint (1, 1));
907 fade_in_presets->push_back (p);
909 p = new Preset ("crossfade_in_default");
910 p->push_back (PresetPoint (0, 0));
911 p->push_back (PresetPoint (0.1, 0.01));
912 p->push_back (PresetPoint (0.2, 0.03));
913 p->push_back (PresetPoint (0.8, 0.97));
914 p->push_back (PresetPoint (0.9, 0.99));
915 p->push_back (PresetPoint (1, 1));
916 fade_in_presets->push_back (p);
920 // p = new Preset ("hiout.xpm");
921 p = new Preset ("crossfade_out_fast-cut");
922 p->push_back (PresetPoint (0, 1));
923 p->push_back (PresetPoint (0.305556, 1));
924 p->push_back (PresetPoint (0.548611, 0.991736));
925 p->push_back (PresetPoint (0.759259, 0.931129));
926 p->push_back (PresetPoint (0.918981, 0.68595));
927 p->push_back (PresetPoint (0.976852, 0.22865));
928 p->push_back (PresetPoint (1, 0));
929 fade_out_presets->push_back (p);
931 // p = new Preset ("loout.xpm");
932 p = new Preset ("crossfade_out_transition");
933 p->push_back (PresetPoint (0, 1));
934 p->push_back (PresetPoint (0.023041, 0.697222));
935 p->push_back (PresetPoint (0.0553, 0.483333));
936 p->push_back (PresetPoint (0.170507, 0.233333));
937 p->push_back (PresetPoint (0.370968, 0.0861111));
938 p->push_back (PresetPoint (0.610599, 0.0333333));
939 p->push_back (PresetPoint (1, 0));
940 fade_out_presets->push_back (p);
942 // p = new Preset ("regout.xpm");
943 p = new Preset ("crossfade_out_constant");
944 p->push_back (PresetPoint (0, 1));
945 p->push_back (PresetPoint (0.228111, 0.988889));
946 p->push_back (PresetPoint (0.347926, 0.972222));
947 p->push_back (PresetPoint (0.529954, 0.886111));
948 p->push_back (PresetPoint (0.753456, 0.658333));
949 p->push_back (PresetPoint (0.9262673, 0.308333));
950 p->push_back (PresetPoint (1, 0));
951 fade_out_presets->push_back (p);
953 // p = new Preset ("regout2.xpm");
954 p = new Preset ("crossfade_out_slow-fade");
955 p->push_back (PresetPoint (0, 1));
956 p->push_back (PresetPoint (0.080645, 0.730556));
957 p->push_back (PresetPoint (0.277778, 0.289256));
958 p->push_back (PresetPoint (0.470046, 0.152778));
959 p->push_back (PresetPoint (0.695853, 0.0694444));
960 p->push_back (PresetPoint (1, 0));
961 fade_out_presets->push_back (p);
963 // p = new Preset ("linout.xpm");
964 p = new Preset ("crossfade_out_dipped");
965 p->push_back (PresetPoint (0, 1));
966 p->push_back (PresetPoint (1, 0));
967 fade_out_presets->push_back (p);
969 p = new Preset ("crossfade_out_default");
970 p->push_back (PresetPoint (0, 1));
971 p->push_back (PresetPoint (0.1, 0.99));
972 p->push_back (PresetPoint (0.2, 0.97));
973 p->push_back (PresetPoint (0.8, 0.03));
974 p->push_back (PresetPoint (0.9, 0.01));
975 p->push_back (PresetPoint (1, 0));
976 fade_out_presets->push_back (p);
980 CrossfadeEditor::curve_select_clicked (WhichFade wf)
986 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) {
987 (*i)->property_wave_color() = ARDOUR_UI::config()->canvasvar_SelectedCrossfadeEditorWave.get();
988 (*i)->property_fill_color() = ARDOUR_UI::config()->canvasvar_SelectedCrossfadeEditorWave.get();
991 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) {
992 (*i)->property_wave_color() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorWave.get();
993 (*i)->property_fill_color() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorWave.get();
996 fade[In].line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_SelectedCrossfadeEditorLine.get();
997 fade[Out].line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorLine.get();
998 fade[Out].shading->hide();
999 fade[In].shading->show();
1001 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
1005 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
1011 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) {
1012 (*i)->property_wave_color() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorWave.get();
1013 (*i)->property_fill_color() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorWave.get();
1016 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) {
1017 (*i)->property_wave_color() = ARDOUR_UI::config()->canvasvar_SelectedCrossfadeEditorWave.get();
1018 (*i)->property_fill_color() = ARDOUR_UI::config()->canvasvar_SelectedCrossfadeEditorWave.get();
1021 fade[Out].line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_SelectedCrossfadeEditorLine.get();
1022 fade[In].line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorLine.get();
1023 fade[In].shading->hide();
1024 fade[Out].shading->show();
1026 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
1030 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
1038 CrossfadeEditor::x_coordinate (double& xfract) const
1040 xfract = min (1.0, xfract);
1041 xfract = max (0.0, xfract);
1043 return canvas_border + (xfract * effective_width());
1047 CrossfadeEditor::y_coordinate (double& yfract) const
1049 yfract = min (1.0, yfract);
1050 yfract = max (0.0, yfract);
1052 return (canvas->get_allocation().get_height() - (canvas_border)) - (yfract * effective_height());
1056 CrossfadeEditor::make_waves (boost::shared_ptr<AudioRegion> region, WhichFade which)
1059 uint32_t nchans = region->n_channels();
1064 color = ARDOUR_UI::config()->canvasvar_SelectedCrossfadeEditorWave.get();
1066 color = ARDOUR_UI::config()->canvasvar_CrossfadeEditorWave.get();
1069 ht = canvas->get_allocation().get_height() / (double) nchans;
1070 spu = xfade->length() / (double) effective_width();
1072 for (uint32_t n = 0; n < nchans; ++n) {
1074 gdouble yoff = n * ht;
1076 if (region->source(n)->peaks_ready (bind (mem_fun(*this, &CrossfadeEditor::peaks_ready), region, which), peaks_ready_connection)) {
1078 WaveView* waveview = new WaveView (*(canvas->root()));
1080 waveview->property_data_src() = region.get();
1081 waveview->property_cache_updater() = true;
1082 waveview->property_cache() = WaveView::create_cache();
1083 waveview->property_channel() = n;
1084 waveview->property_length_function() = (void*) region_length_from_c;
1085 waveview->property_sourcefile_length_function() = (void*) sourcefile_length_from_c;
1086 waveview->property_peak_function() = (void*) region_read_peaks_from_c;
1087 waveview->property_gain_function() = (void*) curve_get_vector_from_c;
1088 waveview->property_gain_src() = &fade[which].gain_curve;
1089 waveview->property_x() = canvas_border;
1090 waveview->property_y() = yoff;
1091 waveview->property_height() = ht;
1092 waveview->property_samples_per_unit() = spu;
1093 waveview->property_amplitude_above_axis() = 2.0;
1094 waveview->property_wave_color() = color;
1095 waveview->property_fill_color() = color;
1098 waveview->property_region_start() = region->start();
1100 waveview->property_region_start() = region->start()+region->length()-xfade->length();
1102 waveview->lower_to_bottom();
1103 fade[which].waves.push_back (waveview);
1107 toplevel->lower_to_bottom();
1111 CrossfadeEditor::peaks_ready (boost::shared_ptr<AudioRegion> r, WhichFade which)
1113 /* this should never be called, because the peak files for an xfade
1114 will be ready by the time we want them. but our API forces us
1115 to provide this, so ..
1117 peaks_ready_connection.disconnect ();
1118 make_waves (r, which);
1122 CrossfadeEditor::audition (Audition which)
1124 AudioPlaylist& pl (session.the_auditioner()->prepare_playlist());
1127 nframes_t left_start_offset;
1128 nframes_t right_length;
1129 nframes_t left_length;
1131 if (which != Right && preroll_button.get_active()) {
1132 preroll = session.frame_rate() * 2; //2 second hardcoded preroll for now
1137 if (which != Left && postroll_button.get_active()) {
1138 postroll = session.frame_rate() * 2; //2 second hardcoded postroll for now
1143 // Is there enough data for the whole preroll?
1144 left_length = xfade->length();
1145 if ((left_start_offset = xfade->out()->length() - xfade->length()) > preroll) {
1146 left_start_offset -= preroll;
1148 preroll = left_start_offset;
1149 left_start_offset = 0;
1151 left_length += preroll;
1153 // Is there enough data for the whole postroll?
1154 right_length = xfade->length();
1155 if ((xfade->in()->length() - right_length) > postroll) {
1156 right_length += postroll;
1158 right_length = xfade->in()->length();
1161 boost::shared_ptr<AudioRegion> left (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade->out(), left_start_offset, left_length, "xfade out",
1162 0, Region::DefaultFlags, false)));
1163 boost::shared_ptr<AudioRegion> right (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade->in(), 0, right_length, "xfade in",
1164 0, Region::DefaultFlags, false)));
1166 //apply a 20ms declicking fade at the start and end of auditioning
1167 left->set_fade_in_active(true);
1168 left->set_fade_in_length(session.frame_rate() / 50);
1169 right->set_fade_out_active(true);
1170 right->set_fade_out_length(session.frame_rate() / 50);
1172 pl.add_region (left, 0);
1173 pl.add_region (right, 1 + preroll);
1175 if (which == Left) {
1176 right->set_scale_amplitude (0.0);
1177 } else if (which == Right) {
1178 left->set_scale_amplitude (0.0);
1181 /* there is only one ... */
1182 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1184 session.audition_playlist ();
1188 CrossfadeEditor::audition_both ()
1194 CrossfadeEditor::audition_left_dry ()
1196 boost::shared_ptr<AudioRegion> left (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade->out(), xfade->out()->length() - xfade->length(), xfade->length(), "xfade left",
1197 0, Region::DefaultFlags, false)));
1199 session.audition_region (left);
1203 CrossfadeEditor::audition_left ()
1209 CrossfadeEditor::audition_right_dry ()
1211 boost::shared_ptr<AudioRegion> right (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade->in(), 0, xfade->length(), "xfade in",
1212 0, Region::DefaultFlags, false)));
1213 session.audition_region (right);
1217 CrossfadeEditor::audition_right ()
1223 CrossfadeEditor::cancel_audition ()
1225 session.cancel_audition ();
1229 CrossfadeEditor::audition_toggled ()
1233 if ((x = audition_both_button.get_active ()) != session.is_auditioning()) {
1244 CrossfadeEditor::audition_right_toggled ()
1248 if ((x = audition_right_button.get_active ()) != session.is_auditioning()) {
1259 CrossfadeEditor::audition_right_dry_toggled ()
1263 if ((x = audition_right_dry_button.get_active ()) != session.is_auditioning()) {
1266 audition_right_dry ();
1274 CrossfadeEditor::audition_left_toggled ()
1278 if ((x = audition_left_button.get_active ()) != session.is_auditioning()) {
1289 CrossfadeEditor::audition_left_dry_toggled ()
1293 if ((x = audition_left_dry_button.get_active ()) != session.is_auditioning()) {
1296 audition_left_dry ();