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"
53 using namespace ARDOUR;
57 using namespace Editing;
61 const int32_t CrossfadeEditor::Point::size = 7;
62 const double CrossfadeEditor::canvas_border = 10;
63 CrossfadeEditor::Presets* CrossfadeEditor::fade_in_presets = 0;
64 CrossfadeEditor::Presets* CrossfadeEditor::fade_out_presets = 0;
66 CrossfadeEditor::Half::Half ()
68 normative_curve (Parameter(GainAutomation), 0.0, 1.0, 1.0), // FIXME: GainAutomation?
69 gain_curve (Parameter(GainAutomation), 0.0, 2.0, 1.0)
73 CrossfadeEditor::CrossfadeEditor (Session& s, boost::shared_ptr<Crossfade> xf, double my, double mxy)
74 : ArdourDialog (_("ardour: x-fade edit")),
77 clear_button (_("Clear")),
78 revert_button (_("Reset")),
79 audition_both_button (_("Fade")),
80 audition_left_dry_button (_("Out (dry)")),
81 audition_left_button (_("Out")),
82 audition_right_dry_button (_("In (dry)")),
83 audition_right_button (_("In")),
85 preroll_button (_("With Pre-roll")),
86 postroll_button (_("With Post-roll")),
92 fade_out_table (3, 3),
94 select_in_button (_("Fade In")),
95 select_out_button (_("Fade Out"))
97 set_wmclass (X_("ardour_automationedit"), "Ardour");
98 set_name ("CrossfadeEditWindow");
99 set_position (Gtk::WIN_POS_MOUSE);
101 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
103 RadioButtonGroup sel_but_group = select_in_button.get_group();
104 select_out_button.set_group (sel_but_group);
105 select_out_button.set_mode (false);
106 select_in_button.set_mode (false);
108 get_action_area()->set_layout(BUTTONBOX_SPREAD);
109 get_action_area()->pack_start(clear_button);
110 get_action_area()->pack_start(revert_button);
111 cancel_button = add_button ("Cancel", RESPONSE_CANCEL);
112 ok_button = add_button ("OK", RESPONSE_ACCEPT);
114 if (fade_in_presets == 0) {
118 point_grabbed = false;
121 canvas = new ArdourCanvas::CanvasAA ();
122 canvas->signal_size_allocate().connect (mem_fun(*this, &CrossfadeEditor::canvas_allocation));
123 canvas->set_size_request (425, 200);
125 toplevel = new ArdourCanvas::SimpleRect (*(canvas->root()));
126 toplevel->property_x1() = 0.0;
127 toplevel->property_y1() = 0.0;
128 toplevel->property_x2() = 10.0;
129 toplevel->property_y2() = 10.0;
130 toplevel->property_fill() = true;
131 toplevel->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorBase.get();
132 toplevel->property_outline_pixels() = 0;
133 toplevel->signal_event().connect (mem_fun (*this, &CrossfadeEditor::canvas_event));
135 fade[Out].line = new ArdourCanvas::Line (*(canvas->root()));
136 fade[Out].line->property_width_pixels() = 1;
137 fade[Out].line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorLine.get();
139 fade[Out].shading = new ArdourCanvas::Polygon (*(canvas->root()));
140 fade[Out].shading->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorLineShading.get();
142 fade[In].line = new ArdourCanvas::Line (*(canvas->root()));
143 fade[In].line->property_width_pixels() = 1;
144 fade[In].line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorLine.get();
146 fade[In].shading = new ArdourCanvas::Polygon (*(canvas->root()));
147 fade[In].shading->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorLineShading.get();
149 fade[In].shading->signal_event().connect (mem_fun (*this, &CrossfadeEditor::canvas_event));
150 fade[In].line->signal_event().connect (mem_fun (*this, &CrossfadeEditor::curve_event));
151 fade[Out].shading->signal_event().connect (mem_fun (*this, &CrossfadeEditor::canvas_event));
152 fade[Out].line->signal_event().connect (mem_fun (*this, &CrossfadeEditor::curve_event));
154 select_in_button.set_name (X_("CrossfadeEditCurveButton"));
155 select_out_button.set_name (X_("CrossfadeEditCurveButton"));
157 select_in_button.signal_clicked().connect (bind (mem_fun (*this, &CrossfadeEditor::curve_select_clicked), In));
158 select_out_button.signal_clicked().connect (bind (mem_fun (*this, &CrossfadeEditor::curve_select_clicked), Out));
160 HBox* acbox = manage (new HBox);
162 audition_box.set_border_width (7);
163 audition_box.set_spacing (5);
164 audition_box.set_homogeneous (false);
165 audition_box.pack_start (audition_left_dry_button, false, false);
166 audition_box.pack_start (audition_left_button, false, false);
167 audition_box.pack_start (audition_both_button, false, false);
168 audition_box.pack_start (audition_right_button, false, false);
169 audition_box.pack_start (audition_right_dry_button, false, false);
171 Frame* audition_frame = manage (new Frame (_("Audition")));
173 audition_frame->set_name (X_("CrossfadeEditFrame"));
174 audition_frame->add (audition_box);
176 acbox->pack_start (*audition_frame, true, false);
178 Frame* canvas_frame = manage (new Frame);
179 canvas_frame->add (*canvas);
180 canvas_frame->set_shadow_type (Gtk::SHADOW_IN);
182 fade_in_table.attach (select_in_button, 0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND);
183 fade_out_table.attach (select_out_button, 0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND);
193 for (list<Preset*>::iterator i = fade_in_presets->begin(); i != fade_in_presets->end(); ++i) {
195 pxmap = manage (new Image (::get_icon ((*i)->image_name)));
196 pbutton = manage (new Button);
197 pbutton->add (*pxmap);
198 pbutton->set_name ("CrossfadeEditButton");
199 pbutton->signal_clicked().connect (bind (mem_fun(*this, &CrossfadeEditor::apply_preset), *i));
200 fade_in_table.attach (*pbutton, col, col+1, row, row+1);
201 fade_in_buttons.push_back (pbutton);
214 for (list<Preset*>::iterator i = fade_out_presets->begin(); i != fade_out_presets->end(); ++i) {
216 pxmap = manage (new Image (::get_icon ((*i)->image_name)));
217 pbutton = manage (new Button);
218 pbutton->add (*pxmap);
219 pbutton->set_name ("CrossfadeEditButton");
220 pbutton->signal_clicked().connect (bind (mem_fun(*this, &CrossfadeEditor::apply_preset), *i));
221 fade_out_table.attach (*pbutton, col, col+1, row, row+1);
222 fade_out_buttons.push_back (pbutton);
232 clear_button.set_name ("CrossfadeEditButton");
233 revert_button.set_name ("CrossfadeEditButton");
234 ok_button->set_name ("CrossfadeEditButton");
235 cancel_button->set_name ("CrossfadeEditButton");
236 preroll_button.set_name ("CrossfadeEditButton");
237 postroll_button.set_name ("CrossfadeEditButton");
238 audition_both_button.set_name ("CrossfadeEditAuditionButton");
239 audition_left_dry_button.set_name ("CrossfadeEditAuditionButton");
240 audition_left_button.set_name ("CrossfadeEditAuditionButton");
241 audition_right_dry_button.set_name ("CrossfadeEditAuditionButton");
242 audition_right_button.set_name ("CrossfadeEditAuditionButton");
244 clear_button.signal_clicked().connect (mem_fun(*this, &CrossfadeEditor::clear));
245 revert_button.signal_clicked().connect (mem_fun(*this, &CrossfadeEditor::reset));
246 audition_both_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_toggled));
247 audition_right_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_right_toggled));
248 audition_right_dry_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_right_dry_toggled));
249 audition_left_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_left_toggled));
250 audition_left_dry_button.signal_toggled().connect (mem_fun(*this, &CrossfadeEditor::audition_left_dry_toggled));
252 roll_box.pack_start (preroll_button, false, false);
253 roll_box.pack_start (postroll_button, false, false);
255 Gtk::HBox* rcenter_box = manage (new HBox);
256 rcenter_box->pack_start (roll_box, true, false);
258 VBox* vpacker2 = manage (new (VBox));
260 vpacker2->set_border_width (12);
261 vpacker2->set_spacing (7);
262 vpacker2->pack_start (*acbox, false, false);
263 vpacker2->pack_start (*rcenter_box, false, false);
265 curve_button_box.set_spacing (7);
266 curve_button_box.pack_start (fade_out_table, false, false, 12);
267 curve_button_box.pack_start (*vpacker2, false, false, 12);
268 curve_button_box.pack_start (fade_in_table, false, false, 12);
270 get_vbox()->pack_start (*canvas_frame, true, true);
271 get_vbox()->pack_start (curve_button_box, false, false);
273 /* button to allow hackers to check the actual curve values */
275 // Button* foobut = manage (new Button ("dump"));
276 // foobut-.signal_clicked().connect (mem_fun(*this, &CrossfadeEditor::dump));
277 // vpacker.pack_start (*foobut, false, false);
280 set (xfade->fade_in(), In);
283 set (xfade->fade_out(), Out);
285 curve_select_clicked (In);
287 xfade->StateChanged.connect (mem_fun(*this, &CrossfadeEditor::xfade_changed));
289 session.AuditionActive.connect (mem_fun(*this, &CrossfadeEditor::audition_state_changed));
293 CrossfadeEditor::~CrossfadeEditor()
295 /* most objects will be destroyed when the toplevel window is. */
297 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
301 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
307 CrossfadeEditor::dump ()
309 for (AutomationList::iterator i = fade[Out].normative_curve.begin(); i != fade[Out].normative_curve.end(); ++i) {
310 cerr << (*i)->when << ' ' << (*i)->value << endl;
315 CrossfadeEditor::audition_state_changed (bool yn)
317 ENSURE_GUI_THREAD (bind (mem_fun(*this, &CrossfadeEditor::audition_state_changed), yn));
320 audition_both_button.set_active (false);
321 audition_left_button.set_active (false);
322 audition_right_button.set_active (false);
323 audition_left_dry_button.set_active (false);
324 audition_right_dry_button.set_active (false);
329 CrossfadeEditor::set (const ARDOUR::AutomationList& curve, WhichFade which)
332 ARDOUR::AutomationList::const_iterator the_end;
334 for (list<Point*>::iterator i = fade[which].points.begin(); i != fade[which].points.end(); ++i) {
338 fade[which].points.clear ();
339 fade[which].gain_curve.clear ();
340 fade[which].normative_curve.clear ();
346 the_end = curve.const_end();
349 firstx = (*curve.const_begin())->when;
350 endx = (*the_end)->when;
352 for (ARDOUR::AutomationList::const_iterator i = curve.const_begin(); i != curve.const_end(); ++i) {
354 double xfract = ((*i)->when - firstx) / (endx - firstx);
355 double yfract = ((*i)->value - miny) / (maxy - miny);
357 Point* p = make_point ();
359 p->move_to (x_coordinate (xfract), y_coordinate (yfract),
362 fade[which].points.push_back (p);
365 /* no need to sort because curve is already time-ordered */
369 swap (which, current);
371 swap (which, current);
375 CrossfadeEditor::curve_event (GdkEvent* event)
377 /* treat it like a toplevel event */
379 return canvas_event (event);
383 CrossfadeEditor::point_event (GdkEvent* event, Point* point)
386 if (point->curve != fade[current].line) {
390 switch (event->type) {
391 case GDK_BUTTON_PRESS:
392 point_grabbed = true;
394 case GDK_BUTTON_RELEASE:
395 point_grabbed = false;
397 if (Keyboard::is_delete_event (&event->button)) {
398 fade[current].points.remove (point);
405 case GDK_MOTION_NOTIFY:
409 /* can't drag first or last points horizontally */
411 if (point == fade[current].points.front() || point == fade[current].points.back()) {
414 new_x = (event->motion.x - canvas_border)/effective_width();
417 new_y = 1.0 - ((event->motion.y - canvas_border)/effective_height());
418 point->move_to (x_coordinate (new_x), y_coordinate (new_y),
430 CrossfadeEditor::canvas_event (GdkEvent* event)
432 switch (event->type) {
433 case GDK_BUTTON_PRESS:
434 add_control_point ((event->button.x - canvas_border)/effective_width(),
435 1.0 - ((event->button.y - canvas_border)/effective_height()));
444 CrossfadeEditor::Point::~Point()
449 CrossfadeEditor::Point*
450 CrossfadeEditor::make_point ()
452 Point* p = new Point;
454 p->box = new ArdourCanvas::SimpleRect (*(canvas->root()));
455 p->box->property_fill() = true;
456 p->box->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorPointFill.get();
457 p->box->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorPointOutline.get();
458 p->box->property_outline_pixels() = 1;
460 p->curve = fade[current].line;
462 p->box->signal_event().connect (bind (mem_fun (*this, &CrossfadeEditor::point_event), p));
468 CrossfadeEditor::add_control_point (double x, double y)
472 /* enforce end point x location */
474 if (fade[current].points.empty()) {
476 } else if (fade[current].points.size() == 1) {
480 Point* p = make_point ();
482 p->move_to (x_coordinate (x), y_coordinate (y), x, y);
484 fade[current].points.push_back (p);
485 fade[current].points.sort (cmp);
491 CrossfadeEditor::Point::move_to (double nx, double ny, double xfract, double yfract)
493 const double half_size = rint(size/2.0);
494 double x1 = nx - half_size;
495 double x2 = nx + half_size;
497 box->property_x1() = x1;
498 box->property_x2() = x2;
500 box->property_y1() = ny - half_size;
501 box->property_y2() = ny + half_size;
508 CrossfadeEditor::canvas_allocation (Gtk::Allocation& alloc)
511 toplevel->property_x1() = 0.0;
512 toplevel->property_y1() = 0.0;
513 toplevel->property_x2() = (double) canvas->get_allocation().get_width() + canvas_border;
514 toplevel->property_y2() = (double) canvas->get_allocation().get_height() + canvas_border;
517 canvas->set_scroll_region (0.0, 0.0,
518 canvas->get_allocation().get_width(),
519 canvas->get_allocation().get_height());
521 Point* end = make_point ();
524 if (fade[In].points.size() > 1) {
525 Point* old_end = fade[In].points.back();
526 fade[In].points.pop_back ();
527 end->move_to (x_coordinate (old_end->x),
528 y_coordinate (old_end->y),
529 old_end->x, old_end->y);
534 end->move_to (x_coordinate (x), y_coordinate (y), x, y);
538 fade[In].points.push_back (end);
539 fade[In].points.sort (cmp);
541 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
542 (*i)->move_to (x_coordinate((*i)->x), y_coordinate((*i)->y),
548 if (fade[Out].points.size() > 1) {
549 Point* old_end = fade[Out].points.back();
550 fade[Out].points.pop_back ();
551 end->move_to (x_coordinate (old_end->x),
552 y_coordinate (old_end->y),
553 old_end->x, old_end->y);
558 end->move_to (x_coordinate (x), y_coordinate (y), x, y);
562 fade[Out].points.push_back (end);
563 fade[Out].points.sort (cmp);
565 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
566 (*i)->move_to (x_coordinate ((*i)->x),
567 y_coordinate ((*i)->y),
571 WhichFade old_current = current;
576 current = old_current;
578 double spu = xfade->length() / (double) effective_width();
580 if (fade[In].waves.empty()) {
581 make_waves (xfade->in(), In);
584 if (fade[Out].waves.empty()) {
585 make_waves (xfade->out(), Out);
589 vector<ArdourCanvas::WaveView*>::iterator i;
592 ht = canvas->get_allocation().get_height() / xfade->in()->n_channels();
594 for (n = 0, i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i, ++n) {
599 (*i)->property_y() = yoff;
600 (*i)->property_height() = ht;
601 (*i)->property_samples_per_unit() = spu;
604 ht = canvas->get_allocation().get_height() / xfade->out()->n_channels();
606 for (n = 0, i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i, ++n) {
611 (*i)->property_y() = yoff;
612 (*i)->property_height() = ht;
613 (*i)->property_samples_per_unit() = spu;
620 CrossfadeEditor::xfade_changed (Change ignored)
622 set (xfade->fade_in(), In);
623 set (xfade->fade_out(), Out);
627 CrossfadeEditor::redraw ()
629 if (canvas->get_allocation().get_width() < 2) {
633 nframes_t len = xfade->length ();
635 fade[current].normative_curve.clear ();
636 fade[current].gain_curve.clear ();
638 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
639 fade[current].normative_curve.add ((*i)->x, (*i)->y);
640 fade[current].gain_curve.add (((*i)->x * len), (*i)->y);
643 size_t npoints = (size_t) effective_width();
646 fade[current].normative_curve.curve().get_vector (0, 1.0, vec, npoints);
648 ArdourCanvas::Points pts;
649 ArdourCanvas::Points spts;
651 while (pts.size() < npoints) {
652 pts.push_back (Gnome::Art::Point (0,0));
655 while (spts.size() < npoints + 3) {
656 spts.push_back (Gnome::Art::Point (0,0));
659 /* the shade coordinates *MUST* be in anti-clockwise order.
666 spts[0].set_x (canvas_border);
667 spts[0].set_y (effective_height() + canvas_border);
671 spts[1].set_x (effective_width() + canvas_border);
672 spts[1].set_y (effective_height() + canvas_border);
676 spts[2].set_x (effective_width() + canvas_border);
677 spts[2].set_y (canvas_border);
684 spts[0].set_x (canvas_border);
685 spts[0].set_y (canvas_border);
689 spts[1].set_x (canvas_border);
690 spts[1].set_y (effective_height() + canvas_border);
694 spts[2].set_x (effective_width() + canvas_border);
695 spts[2].set_y (effective_height() + canvas_border);
699 size_t last_spt = (npoints + 3) - 1;
701 for (size_t i = 0; i < npoints; ++i) {
705 pts[i].set_x (canvas_border + i);
706 pts[i].set_y (y_coordinate (y));
708 spts[last_spt - i].set_x (canvas_border + i);
709 spts[last_spt - i].set_y (pts[i].get_y());
712 fade[current].line->property_points() = pts;
713 fade[current].shading->property_points() = spts;
715 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[current].waves.begin(); i != fade[current].waves.end(); ++i) {
716 (*i)->property_gain_src() = &fade[current].gain_curve;
721 CrossfadeEditor::apply_preset (Preset *preset)
724 WhichFade wf = find(fade_in_presets->begin(), fade_in_presets->end(), preset) != fade_in_presets->end() ? In : Out;
729 select_in_button.clicked();
731 select_out_button.clicked();
734 curve_select_clicked (wf);
737 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
741 fade[current].points.clear ();
743 for (Preset::iterator i = preset->begin(); i != preset->end(); ++i) {
744 Point* p = make_point ();
745 p->move_to (x_coordinate ((*i).x), y_coordinate ((*i).y),
747 fade[current].points.push_back (p);
754 CrossfadeEditor::apply ()
760 CrossfadeEditor::_apply_to (boost::shared_ptr<Crossfade> xf)
762 ARDOUR::AutomationList& in (xf->fade_in());
763 ARDOUR::AutomationList& out (xf->fade_out());
768 ARDOUR::AutomationList::const_iterator the_end = in.const_end();
771 double firstx = (*in.begin())->when;
772 double endx = (*the_end)->when;
773 double miny = in.get_min_y ();
774 double maxy = in.get_max_y ();
779 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
781 double when = firstx + ((*i)->x * (endx - firstx));
782 double value = (*i)->y; // miny + ((*i)->y * (maxy - miny));
783 in.add (when, value);
788 the_end = out.const_end();
791 firstx = (*out.begin())->when;
792 endx = (*the_end)->when;
793 miny = out.get_min_y ();
794 maxy = out.get_max_y ();
799 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
801 double when = firstx + ((*i)->x * (endx - firstx));
802 double value = (*i)->y; // miny + ((*i)->y * (maxy - miny));
803 out.add (when, value);
811 CrossfadeEditor::setup (boost::shared_ptr<Crossfade> xfade)
814 xfade->set_active (true);
815 xfade->fade_in().curve().solve ();
816 xfade->fade_out().curve().solve ();
820 CrossfadeEditor::clear ()
822 for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
826 fade[current].points.clear ();
832 CrossfadeEditor::reset ()
834 set (xfade->fade_in(), In);
835 set (xfade->fade_out(), Out);
837 curve_select_clicked (current);
841 CrossfadeEditor::build_presets ()
845 fade_in_presets = new Presets;
846 fade_out_presets = new Presets;
849 // p = new Preset ("hiin.xpm");
850 p = new Preset ("crossfade_in_fast-cut");
851 p->push_back (PresetPoint (0, 0));
852 p->push_back (PresetPoint (0.0207373, 0.197222));
853 p->push_back (PresetPoint (0.0645161, 0.525));
854 p->push_back (PresetPoint (0.152074, 0.802778));
855 p->push_back (PresetPoint (0.276498, 0.919444));
856 p->push_back (PresetPoint (0.481567, 0.980556));
857 p->push_back (PresetPoint (0.767281, 1));
858 p->push_back (PresetPoint (1, 1));
859 fade_in_presets->push_back (p);
861 // p = new Preset ("loin.xpm");
862 p = new Preset ("crossfade_in_transition");
863 p->push_back (PresetPoint (0, 0));
864 p->push_back (PresetPoint (0.389401, 0.0333333));
865 p->push_back (PresetPoint (0.629032, 0.0861111));
866 p->push_back (PresetPoint (0.829493, 0.233333));
867 p->push_back (PresetPoint (0.9447, 0.483333));
868 p->push_back (PresetPoint (0.976959, 0.697222));
869 p->push_back (PresetPoint (1, 1));
870 fade_in_presets->push_back (p);
872 // p = new Preset ("regin.xpm");
873 p = new Preset ("crossfade_in_constant");
874 p->push_back (PresetPoint (0, 0));
875 p->push_back (PresetPoint (0.0737327, 0.308333));
876 p->push_back (PresetPoint (0.246544, 0.658333));
877 p->push_back (PresetPoint (0.470046, 0.886111));
878 p->push_back (PresetPoint (0.652074, 0.972222));
879 p->push_back (PresetPoint (0.771889, 0.988889));
880 p->push_back (PresetPoint (1, 1));
881 fade_in_presets->push_back (p);
883 // p = new Preset ("regin2.xpm");
884 p = new Preset ("crossfade_in_slow-cut");
885 p->push_back (PresetPoint (0, 0));
886 p->push_back (PresetPoint (0.304147, 0.0694444));
887 p->push_back (PresetPoint (0.529954, 0.152778));
888 p->push_back (PresetPoint (0.725806, 0.333333));
889 p->push_back (PresetPoint (0.847926, 0.558333));
890 p->push_back (PresetPoint (0.919355, 0.730556));
891 p->push_back (PresetPoint (1, 1));
892 fade_in_presets->push_back (p);
894 // p = new Preset ("linin.xpm");
895 p = new Preset ("crossfade_in_dipped");
896 p->push_back (PresetPoint (0, 0));
897 p->push_back (PresetPoint (1, 1));
898 fade_in_presets->push_back (p);
900 p = new Preset ("crossfade_in_default");
901 p->push_back (PresetPoint (0, 0));
902 p->push_back (PresetPoint (0.1, 0.01));
903 p->push_back (PresetPoint (0.2, 0.03));
904 p->push_back (PresetPoint (0.8, 0.97));
905 p->push_back (PresetPoint (0.9, 0.99));
906 p->push_back (PresetPoint (1, 1));
907 fade_in_presets->push_back (p);
911 // p = new Preset ("hiout.xpm");
912 p = new Preset ("crossfade_out_fast-cut");
913 p->push_back (PresetPoint (0, 1));
914 p->push_back (PresetPoint (0.305556, 1));
915 p->push_back (PresetPoint (0.548611, 0.991736));
916 p->push_back (PresetPoint (0.759259, 0.931129));
917 p->push_back (PresetPoint (0.918981, 0.68595));
918 p->push_back (PresetPoint (0.976852, 0.22865));
919 p->push_back (PresetPoint (1, 0));
920 fade_out_presets->push_back (p);
922 // p = new Preset ("regout.xpm");
923 p = new Preset ("crossfade_out_constant");
924 p->push_back (PresetPoint (0, 1));
925 p->push_back (PresetPoint (0.228111, 0.988889));
926 p->push_back (PresetPoint (0.347926, 0.972222));
927 p->push_back (PresetPoint (0.529954, 0.886111));
928 p->push_back (PresetPoint (0.753456, 0.658333));
929 p->push_back (PresetPoint (0.9262673, 0.308333));
930 p->push_back (PresetPoint (1, 0));
931 fade_out_presets->push_back (p);
933 // p = new Preset ("loout.xpm");
934 p = new Preset ("crossfade_out_transition");
935 p->push_back (PresetPoint (0, 1));
936 p->push_back (PresetPoint (0.023041, 0.697222));
937 p->push_back (PresetPoint (0.0553, 0.483333));
938 p->push_back (PresetPoint (0.170507, 0.233333));
939 p->push_back (PresetPoint (0.370968, 0.0861111));
940 p->push_back (PresetPoint (0.610599, 0.0333333));
941 p->push_back (PresetPoint (1, 0));
942 fade_out_presets->push_back (p);
944 // p = new Preset ("regout2.xpm");
945 p = new Preset ("crossfade_out_slow-fade");
946 p->push_back (PresetPoint (0, 1));
947 p->push_back (PresetPoint (0.080645, 0.730556));
948 p->push_back (PresetPoint (0.277778, 0.289256));
949 p->push_back (PresetPoint (0.470046, 0.152778));
950 p->push_back (PresetPoint (0.695853, 0.0694444));
951 p->push_back (PresetPoint (1, 0));
952 fade_out_presets->push_back (p);
954 // p = new Preset ("linout.xpm");
955 p = new Preset ("crossfade_out_dipped");
956 p->push_back (PresetPoint (0, 1));
957 p->push_back (PresetPoint (1, 0));
958 fade_out_presets->push_back (p);
960 p = new Preset ("crossfade_out_default");
961 p->push_back (PresetPoint (0, 1));
962 p->push_back (PresetPoint (0.1, 0.99));
963 p->push_back (PresetPoint (0.2, 0.97));
964 p->push_back (PresetPoint (0.8, 0.03));
965 p->push_back (PresetPoint (0.9, 0.01));
966 p->push_back (PresetPoint (1, 0));
967 fade_out_presets->push_back (p);
971 CrossfadeEditor::curve_select_clicked (WhichFade wf)
977 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) {
978 (*i)->property_wave_color() = ARDOUR_UI::config()->canvasvar_SelectedCrossfadeEditorWave.get();
981 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) {
982 (*i)->property_wave_color() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorWave.get();
985 fade[In].line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_SelectedCrossfadeEditorLine.get();
986 fade[Out].line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorLine.get();
987 fade[Out].shading->hide();
988 fade[In].shading->show();
990 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
994 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
1000 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) {
1001 (*i)->property_wave_color() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorWave.get();
1004 for (vector<ArdourCanvas::WaveView*>::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) {
1005 (*i)->property_wave_color() = ARDOUR_UI::config()->canvasvar_SelectedCrossfadeEditorWave.get();
1008 fade[Out].line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_SelectedCrossfadeEditorLine.get();
1009 fade[In].line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorLine.get();
1010 fade[In].shading->hide();
1011 fade[Out].shading->show();
1013 for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
1017 for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
1025 CrossfadeEditor::x_coordinate (double& xfract) const
1027 xfract = min (1.0, xfract);
1028 xfract = max (0.0, xfract);
1030 return canvas_border + (xfract * effective_width());
1034 CrossfadeEditor::y_coordinate (double& yfract) const
1036 yfract = min (1.0, yfract);
1037 yfract = max (0.0, yfract);
1039 return (canvas->get_allocation().get_height() - (canvas_border)) - (yfract * effective_height());
1043 CrossfadeEditor::make_waves (boost::shared_ptr<AudioRegion> region, WhichFade which)
1046 uint32_t nchans = region->n_channels();
1051 color = ARDOUR_UI::config()->canvasvar_SelectedCrossfadeEditorWave.get();
1053 color = ARDOUR_UI::config()->canvasvar_CrossfadeEditorWave.get();
1056 ht = canvas->get_allocation().get_height() / (double) nchans;
1057 spu = xfade->length() / (double) effective_width();
1059 for (uint32_t n = 0; n < nchans; ++n) {
1061 gdouble yoff = n * ht;
1063 if (region->audio_source(n)->peaks_ready (bind (mem_fun(*this, &CrossfadeEditor::peaks_ready), region, which), peaks_ready_connection)) {
1064 WaveView* waveview = new WaveView (*(canvas->root()));
1066 waveview->property_data_src() = region.get();
1067 waveview->property_cache_updater() = true;
1068 waveview->property_cache() = WaveView::create_cache();
1069 waveview->property_channel() = n;
1070 waveview->property_length_function() = (void*) region_length_from_c;
1071 waveview->property_sourcefile_length_function() = (void*) sourcefile_length_from_c;
1072 waveview->property_peak_function() = (void*) region_read_peaks_from_c;
1073 waveview->property_gain_function() = (void*) curve_get_vector_from_c;
1074 waveview->property_gain_src() = &fade[which].gain_curve;
1075 waveview->property_x() = canvas_border;
1076 waveview->property_y() = yoff;
1077 waveview->property_height() = ht;
1078 waveview->property_samples_per_unit() = spu;
1079 waveview->property_amplitude_above_axis() = 2.0;
1080 waveview->property_wave_color() = color;
1082 waveview->lower_to_bottom();
1083 fade[which].waves.push_back (waveview);
1087 toplevel->lower_to_bottom();
1091 CrossfadeEditor::peaks_ready (boost::shared_ptr<AudioRegion> r, WhichFade which)
1093 /* this should never be called, because the peak files for an xfade
1094 will be ready by the time we want them. but our API forces us
1095 to provide this, so ..
1097 peaks_ready_connection.disconnect ();
1098 make_waves (r, which);
1102 CrossfadeEditor::audition_both ()
1104 AudioPlaylist& pl (session.the_auditioner()->prepare_playlist());
1108 nframes_t left_start_offset;
1109 nframes_t right_length;
1110 nframes_t left_length;
1112 if (preroll_button.get_active()) {
1113 preroll = ARDOUR_UI::instance()->preroll_clock.current_duration ();
1118 if (postroll_button.get_active()) {
1119 postroll = ARDOUR_UI::instance()->postroll_clock.current_duration ();
1124 if ((left_start_offset = xfade->out()->length() - xfade->length()) >= preroll) {
1125 left_start_offset -= preroll;
1130 if ((left_length = xfade->length()) < xfade->out()->length() - left_start_offset) {
1134 right_length = xfade->length();
1136 if (xfade->in()->length() - right_length < postroll) {
1137 right_length += postroll;
1140 boost::shared_ptr<AudioRegion> left (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade->out(), left_start_offset, left_length, "xfade out",
1141 0, Region::DefaultFlags, false)));
1142 boost::shared_ptr<AudioRegion> right (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade->in(), 0, right_length, "xfade in",
1143 0, Region::DefaultFlags, false)));
1145 pl.add_region (left, 0);
1146 pl.add_region (right, 1+preroll);
1148 /* there is only one ... */
1150 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1152 session.audition_playlist ();
1156 CrossfadeEditor::audition_left_dry ()
1158 boost::shared_ptr<AudioRegion> left (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade->out(), xfade->out()->length() - xfade->length(), xfade->length(), "xfade left",
1159 0, Region::DefaultFlags, false)));
1161 session.audition_region (left);
1165 CrossfadeEditor::audition_left ()
1167 AudioPlaylist& pl (session.the_auditioner()->prepare_playlist());
1169 boost::shared_ptr<AudioRegion> left (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade->out(), xfade->out()->length() - xfade->length(), xfade->length(), "xfade left",
1170 0, Region::DefaultFlags, false)));
1171 boost::shared_ptr<AudioRegion> right (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade->in(), 0, xfade->length(), "xfade in",
1172 0, Region::DefaultFlags, false)));
1174 pl.add_region (left, 0);
1175 pl.add_region (right, 1);
1177 right->set_muted (true);
1179 /* there is only one ... */
1181 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1183 session.audition_playlist ();
1185 /* memory leak for regions */
1189 CrossfadeEditor::audition_right_dry ()
1191 boost::shared_ptr<AudioRegion> right (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade->in(), 0, xfade->length(), "xfade in",
1192 0, Region::DefaultFlags, false)));
1193 session.audition_region (right);
1197 CrossfadeEditor::audition_right ()
1199 AudioPlaylist& pl (session.the_auditioner()->prepare_playlist());
1201 boost::shared_ptr<AudioRegion> left (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade->out(), xfade->out()->length() - xfade->length(), xfade->length(), "xfade out",
1202 0, Region::DefaultFlags, false)));
1203 boost::shared_ptr<AudioRegion> right (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade->out(), 0, xfade->length(), "xfade out",
1204 0, Region::DefaultFlags, false)));
1206 pl.add_region (left, 0);
1207 pl.add_region (right, 1);
1209 left->set_muted (true);
1211 /* there is only one ... */
1213 pl.foreach_crossfade (this, &CrossfadeEditor::setup);
1215 session.audition_playlist ();
1219 CrossfadeEditor::cancel_audition ()
1221 session.cancel_audition ();
1225 CrossfadeEditor::audition_toggled ()
1229 if ((x = audition_both_button.get_active ()) != session.is_auditioning()) {
1240 CrossfadeEditor::audition_right_toggled ()
1244 if ((x = audition_right_button.get_active ()) != session.is_auditioning()) {
1255 CrossfadeEditor::audition_right_dry_toggled ()
1259 if ((x = audition_right_dry_button.get_active ()) != session.is_auditioning()) {
1262 audition_right_dry ();
1270 CrossfadeEditor::audition_left_toggled ()
1274 if ((x = audition_left_button.get_active ()) != session.is_auditioning()) {
1285 CrossfadeEditor::audition_left_dry_toggled ()
1289 if ((x = audition_left_dry_button.get_active ()) != session.is_auditioning()) {
1292 audition_left_dry ();