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 "pbd/memento_command.h"
31 #include "ardour/automation_list.h"
32 #include "evoral/Curve.hpp"
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/region_factory.h"
39 #include "ardour/profile.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
;
58 using namespace Editing
;
60 using Gtkmm2ext::Keyboard
;
64 const int32_t CrossfadeEditor::Point::size
= 7;
65 const double CrossfadeEditor::canvas_border
= 10;
66 CrossfadeEditor::Presets
* CrossfadeEditor::fade_in_presets
= 0;
67 CrossfadeEditor::Presets
* CrossfadeEditor::fade_out_presets
= 0;
69 CrossfadeEditor::Half::Half ()
71 , normative_curve (Evoral::Parameter(GainAutomation
))
72 , gain_curve (Evoral::Parameter(GainAutomation
))
76 CrossfadeEditor::CrossfadeEditor (Session
* s
, boost::shared_ptr
<Crossfade
> xf
, double my
, double mxy
)
77 : ArdourDialog (_("Edit Crossfade")),
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 _peaks_ready_connection (0)
104 set_wmclass (X_("ardour_automationedit"), PROGRAM_NAME
);
105 set_name ("CrossfadeEditWindow");
106 set_position (Gtk::WIN_POS_MOUSE
);
108 add_accel_group (ActionManager::ui_manager
->get_accel_group());
110 add_events (Gdk::KEY_PRESS_MASK
|Gdk::KEY_RELEASE_MASK
|Gdk::POINTER_MOTION_MASK
);
112 RadioButtonGroup sel_but_group
= select_in_button
.get_group();
113 select_out_button
.set_group (sel_but_group
);
114 select_out_button
.set_mode (false);
115 select_in_button
.set_mode (false);
117 get_action_area()->set_layout(BUTTONBOX_SPREAD
);
118 get_action_area()->pack_start(clear_button
);
119 get_action_area()->pack_start(revert_button
);
120 cancel_button
= add_button ("Cancel", RESPONSE_CANCEL
);
121 ok_button
= add_button ("OK", RESPONSE_ACCEPT
);
123 if (fade_in_presets
== 0) {
127 point_grabbed
= false;
130 canvas
= new ArdourCanvas::CanvasAA ();
131 canvas
->signal_size_allocate().connect (sigc::mem_fun(*this, &CrossfadeEditor::canvas_allocation
));
132 canvas
->set_size_request (425, 200);
134 toplevel
= new ArdourCanvas::SimpleRect (*(canvas
->root()));
135 toplevel
->property_x1() = 0.0;
136 toplevel
->property_y1() = 0.0;
137 toplevel
->property_x2() = 10.0;
138 toplevel
->property_y2() = 10.0;
139 toplevel
->property_fill() = true;
140 toplevel
->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorBase
.get();
141 toplevel
->property_outline_pixels() = 0;
142 toplevel
->signal_event().connect (sigc::mem_fun (*this, &CrossfadeEditor::canvas_event
));
144 fade
[Out
].line
= new ArdourCanvas::Line (*(canvas
->root()));
145 fade
[Out
].line
->property_width_pixels() = 1;
146 fade
[Out
].line
->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorLine
.get();
148 fade
[Out
].shading
= new ArdourCanvas::Polygon (*(canvas
->root()));
149 fade
[Out
].shading
->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorLineShading
.get();
151 fade
[In
].line
= new ArdourCanvas::Line (*(canvas
->root()));
152 fade
[In
].line
->property_width_pixels() = 1;
153 fade
[In
].line
->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorLine
.get();
155 fade
[In
].shading
= new ArdourCanvas::Polygon (*(canvas
->root()));
156 fade
[In
].shading
->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorLineShading
.get();
158 fade
[In
].shading
->signal_event().connect (sigc::mem_fun (*this, &CrossfadeEditor::canvas_event
));
159 fade
[In
].line
->signal_event().connect (sigc::mem_fun (*this, &CrossfadeEditor::curve_event
));
160 fade
[Out
].shading
->signal_event().connect (sigc::mem_fun (*this, &CrossfadeEditor::canvas_event
));
161 fade
[Out
].line
->signal_event().connect (sigc::mem_fun (*this, &CrossfadeEditor::curve_event
));
163 select_in_button
.set_name (X_("CrossfadeEditCurveButton"));
164 select_out_button
.set_name (X_("CrossfadeEditCurveButton"));
166 select_in_button
.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &CrossfadeEditor::curve_select_clicked
), In
));
167 select_out_button
.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &CrossfadeEditor::curve_select_clicked
), Out
));
169 HBox
* acbox
= manage (new HBox
);
171 audition_box
.set_border_width (7);
172 audition_box
.set_spacing (5);
173 audition_box
.set_homogeneous (false);
174 audition_box
.pack_start (audition_left_dry_button
, false, false);
175 audition_box
.pack_start (audition_left_button
, false, false);
176 audition_box
.pack_start (audition_both_button
, false, false);
177 audition_box
.pack_start (audition_right_button
, false, false);
178 audition_box
.pack_start (audition_right_dry_button
, false, false);
180 Frame
* audition_frame
= manage (new Frame (_("Audition")));
182 audition_frame
->set_name (X_("CrossfadeEditFrame"));
183 audition_frame
->add (audition_box
);
185 acbox
->pack_start (*audition_frame
, true, false);
187 Frame
* canvas_frame
= manage (new Frame
);
188 canvas_frame
->add (*canvas
);
189 canvas_frame
->set_shadow_type (Gtk::SHADOW_IN
);
191 fade_in_table
.attach (select_in_button
, 0, 2, 0, 1, Gtk::FILL
|Gtk::EXPAND
);
192 fade_out_table
.attach (select_out_button
, 0, 2, 0, 1, Gtk::FILL
|Gtk::EXPAND
);
202 for (list
<Preset
*>::iterator i
= fade_in_presets
->begin(); i
!= fade_in_presets
->end(); ++i
) {
204 pxmap
= manage (new Image (::get_icon ((*i
)->image_name
)));
205 pbutton
= manage (new Button
);
206 pbutton
->add (*pxmap
);
207 pbutton
->set_name ("CrossfadeEditButton");
208 pbutton
->signal_clicked().connect (sigc::bind (sigc::mem_fun(*this, &CrossfadeEditor::apply_preset
), *i
));
209 ARDOUR_UI::instance()->set_tip (pbutton
, (*i
)->name
, "");
210 fade_in_table
.attach (*pbutton
, col
, col
+1, row
, row
+1);
211 fade_in_buttons
.push_back (pbutton
);
224 for (list
<Preset
*>::iterator i
= fade_out_presets
->begin(); i
!= fade_out_presets
->end(); ++i
) {
226 pxmap
= manage (new Image (::get_icon ((*i
)->image_name
)));
227 pbutton
= manage (new Button
);
228 pbutton
->add (*pxmap
);
229 pbutton
->set_name ("CrossfadeEditButton");
230 pbutton
->signal_clicked().connect (sigc::bind (sigc::mem_fun(*this, &CrossfadeEditor::apply_preset
), *i
));
231 ARDOUR_UI::instance()->set_tip (pbutton
, (*i
)->name
, "");
232 fade_out_table
.attach (*pbutton
, col
, col
+1, row
, row
+1);
233 fade_out_buttons
.push_back (pbutton
);
243 clear_button
.set_name ("CrossfadeEditButton");
244 revert_button
.set_name ("CrossfadeEditButton");
245 ok_button
->set_name ("CrossfadeEditButton");
246 cancel_button
->set_name ("CrossfadeEditButton");
247 preroll_button
.set_name ("CrossfadeEditButton");
248 postroll_button
.set_name ("CrossfadeEditButton");
249 audition_both_button
.set_name ("CrossfadeEditAuditionButton");
250 audition_left_dry_button
.set_name ("CrossfadeEditAuditionButton");
251 audition_left_button
.set_name ("CrossfadeEditAuditionButton");
252 audition_right_dry_button
.set_name ("CrossfadeEditAuditionButton");
253 audition_right_button
.set_name ("CrossfadeEditAuditionButton");
255 clear_button
.signal_clicked().connect (sigc::mem_fun(*this, &CrossfadeEditor::clear
));
256 revert_button
.signal_clicked().connect (sigc::mem_fun(*this, &CrossfadeEditor::reset
));
257 audition_both_button
.signal_toggled().connect (sigc::mem_fun(*this, &CrossfadeEditor::audition_toggled
));
258 audition_right_button
.signal_toggled().connect (sigc::mem_fun(*this, &CrossfadeEditor::audition_right_toggled
));
259 audition_right_dry_button
.signal_toggled().connect (sigc::mem_fun(*this, &CrossfadeEditor::audition_right_dry_toggled
));
260 audition_left_button
.signal_toggled().connect (sigc::mem_fun(*this, &CrossfadeEditor::audition_left_toggled
));
261 audition_left_dry_button
.signal_toggled().connect (sigc::mem_fun(*this, &CrossfadeEditor::audition_left_dry_toggled
));
263 roll_box
.pack_start (preroll_button
, false, false);
264 roll_box
.pack_start (postroll_button
, false, false);
266 Gtk::HBox
* rcenter_box
= manage (new HBox
);
267 rcenter_box
->pack_start (roll_box
, true, false);
269 VBox
* vpacker2
= manage (new (VBox
));
271 vpacker2
->set_border_width (12);
272 vpacker2
->set_spacing (7);
273 vpacker2
->pack_start (*acbox
, false, false);
274 vpacker2
->pack_start (*rcenter_box
, false, false);
276 curve_button_box
.set_spacing (7);
277 curve_button_box
.pack_start (fade_out_table
, false, false, 12);
278 curve_button_box
.pack_start (*vpacker2
, false, false, 12);
279 curve_button_box
.pack_start (fade_in_table
, false, false, 12);
281 get_vbox()->pack_start (*canvas_frame
, true, true);
282 get_vbox()->pack_start (curve_button_box
, false, false);
284 /* button to allow hackers to check the actual curve values */
286 // Button* foobut = manage (new Button ("dump"));
287 // foobut-.signal_clicked().connect (sigc::mem_fun(*this, &CrossfadeEditor::dump));
288 // vpacker.pack_start (*foobut, false, false);
291 set (xfade
->fade_in(), In
);
294 set (xfade
->fade_out(), Out
);
296 curve_select_clicked (In
);
298 xfade
->PropertyChanged
.connect (state_connection
, invalidator (*this), ui_bind (&CrossfadeEditor::xfade_changed
, this, _1
), gui_context());
300 _session
->AuditionActive
.connect (_session_connections
, invalidator (*this), ui_bind (&CrossfadeEditor::audition_state_changed
, this, _1
), gui_context());
304 CrossfadeEditor::~CrossfadeEditor()
306 /* most objects will be destroyed when the toplevel window is. */
308 for (list
<Point
*>::iterator i
= fade
[In
].points
.begin(); i
!= fade
[In
].points
.end(); ++i
) {
312 for (list
<Point
*>::iterator i
= fade
[Out
].points
.begin(); i
!= fade
[Out
].points
.end(); ++i
) {
316 delete _peaks_ready_connection
;
320 CrossfadeEditor::dump ()
322 for (AutomationList::iterator i
= fade
[Out
].normative_curve
.begin(); i
!= fade
[Out
].normative_curve
.end(); ++i
) {
323 cerr
<< (*i
)->when
<< ' ' << (*i
)->value
<< endl
;
328 CrossfadeEditor::audition_state_changed (bool yn
)
330 ENSURE_GUI_THREAD (*this, &CrossfadeEditor::audition_state_changed
, yn
)
333 audition_both_button
.set_active (false);
334 audition_left_button
.set_active (false);
335 audition_right_button
.set_active (false);
336 audition_left_dry_button
.set_active (false);
337 audition_right_dry_button
.set_active (false);
342 CrossfadeEditor::set (const ARDOUR::AutomationList
& curve
, WhichFade which
)
345 ARDOUR::AutomationList::const_iterator the_end
;
347 for (list
<Point
*>::iterator i
= fade
[which
].points
.begin(); i
!= fade
[which
].points
.end(); ++i
) {
351 fade
[which
].points
.clear ();
352 fade
[which
].gain_curve
.clear ();
353 fade
[which
].normative_curve
.clear ();
359 the_end
= curve
.end();
362 firstx
= (*curve
.begin())->when
;
363 endx
= (*the_end
)->when
;
365 for (ARDOUR::AutomationList::const_iterator i
= curve
.begin(); i
!= curve
.end(); ++i
) {
367 double xfract
= ((*i
)->when
- firstx
) / (endx
- firstx
);
368 double yfract
= ((*i
)->value
- miny
) / (maxy
- miny
);
370 Point
* p
= make_point ();
372 p
->move_to (x_coordinate (xfract
), y_coordinate (yfract
),
375 fade
[which
].points
.push_back (p
);
378 /* no need to sort because curve is already time-ordered */
382 swap (which
, current
);
384 swap (which
, current
);
388 CrossfadeEditor::curve_event (GdkEvent
* event
)
390 /* treat it like a toplevel event */
392 return canvas_event (event
);
396 CrossfadeEditor::point_event (GdkEvent
* event
, Point
* point
)
399 if (point
->curve
!= fade
[current
].line
) {
403 switch (event
->type
) {
404 case GDK_BUTTON_PRESS
:
405 point_grabbed
= true;
407 case GDK_BUTTON_RELEASE
:
408 point_grabbed
= false;
410 if (Keyboard::is_delete_event (&event
->button
)) {
411 fade
[current
].points
.remove (point
);
418 case GDK_MOTION_NOTIFY
:
422 /* can't drag first or last points horizontally or vertically */
424 if (point
== fade
[current
].points
.front() || point
== fade
[current
].points
.back()) {
428 new_x
= (event
->motion
.x
- canvas_border
)/effective_width();
429 new_y
= 1.0 - ((event
->motion
.y
- canvas_border
)/effective_height());
432 point
->move_to (x_coordinate (new_x
), y_coordinate (new_y
),
444 CrossfadeEditor::canvas_event (GdkEvent
* event
)
446 switch (event
->type
) {
447 case GDK_BUTTON_PRESS
:
448 add_control_point ((event
->button
.x
- canvas_border
)/effective_width(),
449 1.0 - ((event
->button
.y
- canvas_border
)/effective_height()));
458 CrossfadeEditor::Point::~Point()
463 CrossfadeEditor::Point
*
464 CrossfadeEditor::make_point ()
466 Point
* p
= new Point
;
468 p
->box
= new ArdourCanvas::SimpleRect (*(canvas
->root()));
469 p
->box
->property_fill() = true;
470 p
->box
->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorPointFill
.get();
471 p
->box
->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorPointOutline
.get();
472 p
->box
->property_outline_pixels() = 1;
474 p
->curve
= fade
[current
].line
;
476 p
->box
->signal_event().connect (sigc::bind (sigc::mem_fun (*this, &CrossfadeEditor::point_event
), p
));
482 CrossfadeEditor::add_control_point (double x
, double y
)
486 /* enforce end point x location */
488 if (fade
[current
].points
.empty()) {
490 } else if (fade
[current
].points
.size() == 1) {
494 Point
* p
= make_point ();
496 p
->move_to (x_coordinate (x
), y_coordinate (y
), x
, y
);
498 fade
[current
].points
.push_back (p
);
499 fade
[current
].points
.sort (cmp
);
505 CrossfadeEditor::Point::move_to (double nx
, double ny
, double xfract
, double yfract
)
507 if ( xfract
< 0.0 ) {
509 } else if ( xfract
> 1.0 ) {
513 if ( yfract
< 0.0 ) {
515 } else if ( yfract
> 1.0 ) {
519 const double half_size
= rint(size
/2.0);
520 double x1
= nx
- half_size
;
521 double x2
= nx
+ half_size
;
523 box
->property_x1() = x1
;
524 box
->property_x2() = x2
;
526 box
->property_y1() = ny
- half_size
;
527 box
->property_y2() = ny
+ half_size
;
534 CrossfadeEditor::canvas_allocation (Gtk::Allocation
& /*alloc*/)
537 toplevel
->property_x1() = 0.0;
538 toplevel
->property_y1() = 0.0;
539 toplevel
->property_x2() = (double) canvas
->get_allocation().get_width() + canvas_border
;
540 toplevel
->property_y2() = (double) canvas
->get_allocation().get_height() + canvas_border
;
543 canvas
->set_scroll_region (0.0, 0.0,
544 canvas
->get_allocation().get_width(),
545 canvas
->get_allocation().get_height());
547 Point
* end
= make_point ();
550 if (fade
[In
].points
.size() > 1) {
551 Point
* old_end
= fade
[In
].points
.back();
552 fade
[In
].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
[In
].points
.push_back (end
);
565 fade
[In
].points
.sort (cmp
);
567 for (list
<Point
*>::iterator i
= fade
[In
].points
.begin(); i
!= fade
[In
].points
.end(); ++i
) {
568 (*i
)->move_to (x_coordinate((*i
)->x
), y_coordinate((*i
)->y
),
574 if (fade
[Out
].points
.size() > 1) {
575 Point
* old_end
= fade
[Out
].points
.back();
576 fade
[Out
].points
.pop_back ();
577 end
->move_to (x_coordinate (old_end
->x
),
578 y_coordinate (old_end
->y
),
579 old_end
->x
, old_end
->y
);
584 end
->move_to (x_coordinate (x
), y_coordinate (y
), x
, y
);
588 fade
[Out
].points
.push_back (end
);
589 fade
[Out
].points
.sort (cmp
);
591 for (list
<Point
*>::iterator i
= fade
[Out
].points
.begin(); i
!= fade
[Out
].points
.end(); ++i
) {
592 (*i
)->move_to (x_coordinate ((*i
)->x
),
593 y_coordinate ((*i
)->y
),
597 WhichFade old_current
= current
;
602 current
= old_current
;
604 double spu
= xfade
->length() / (double) effective_width();
606 if (fade
[In
].waves
.empty()) {
607 make_waves (xfade
->in(), In
);
610 if (fade
[Out
].waves
.empty()) {
611 make_waves (xfade
->out(), Out
);
615 vector
<ArdourCanvas::WaveView
*>::iterator i
;
618 ht
= canvas
->get_allocation().get_height() / xfade
->in()->n_channels();
620 for (n
= 0, i
= fade
[In
].waves
.begin(); i
!= fade
[In
].waves
.end(); ++i
, ++n
) {
625 (*i
)->property_y() = yoff
;
626 (*i
)->property_height() = ht
;
627 (*i
)->property_samples_per_unit() = spu
;
630 ht
= canvas
->get_allocation().get_height() / xfade
->out()->n_channels();
632 for (n
= 0, i
= fade
[Out
].waves
.begin(); i
!= fade
[Out
].waves
.end(); ++i
, ++n
) {
637 (*i
)->property_y() = yoff
;
638 (*i
)->property_height() = ht
;
639 (*i
)->property_samples_per_unit() = spu
;
646 CrossfadeEditor::xfade_changed (const PropertyChange
&)
648 set (xfade
->fade_in(), In
);
649 set (xfade
->fade_out(), Out
);
653 CrossfadeEditor::redraw ()
655 if (canvas
->get_allocation().get_width() < 2) {
659 nframes_t len
= xfade
->length ();
661 fade
[current
].normative_curve
.clear ();
662 fade
[current
].gain_curve
.clear ();
664 for (list
<Point
*>::iterator i
= fade
[current
].points
.begin(); i
!= fade
[current
].points
.end(); ++i
) {
665 fade
[current
].normative_curve
.add ((*i
)->x
, (*i
)->y
);
668 offset
= xfade
->in()->start();
670 offset
= xfade
->out()->start()+xfade
->out()->length()-xfade
->length();
671 fade
[current
].gain_curve
.add (((*i
)->x
* len
) + offset
, (*i
)->y
);
675 size_t npoints
= (size_t) effective_width();
678 fade
[current
].normative_curve
.curve().get_vector (0, 1.0, vec
, npoints
);
680 ArdourCanvas::Points pts
;
681 ArdourCanvas::Points spts
;
683 while (pts
.size() < npoints
) {
684 pts
.push_back (Gnome::Art::Point (0,0));
687 while (spts
.size() < npoints
+ 3) {
688 spts
.push_back (Gnome::Art::Point (0,0));
691 /* the shade coordinates *MUST* be in anti-clockwise order.
698 spts
[0].set_x (canvas_border
);
699 spts
[0].set_y (effective_height() + canvas_border
);
703 spts
[1].set_x (effective_width() + canvas_border
);
704 spts
[1].set_y (effective_height() + canvas_border
);
708 spts
[2].set_x (effective_width() + canvas_border
);
709 spts
[2].set_y (canvas_border
);
716 spts
[0].set_x (canvas_border
);
717 spts
[0].set_y (canvas_border
);
721 spts
[1].set_x (canvas_border
);
722 spts
[1].set_y (effective_height() + canvas_border
);
726 spts
[2].set_x (effective_width() + canvas_border
);
727 spts
[2].set_y (effective_height() + canvas_border
);
731 size_t last_spt
= (npoints
+ 3) - 1;
733 for (size_t i
= 0; i
< npoints
; ++i
) {
737 pts
[i
].set_x (canvas_border
+ i
);
738 pts
[i
].set_y (y_coordinate (y
));
740 spts
[last_spt
- i
].set_x (canvas_border
+ i
);
741 spts
[last_spt
- i
].set_y (pts
[i
].get_y());
744 fade
[current
].line
->property_points() = pts
;
745 fade
[current
].shading
->property_points() = spts
;
747 for (vector
<ArdourCanvas::WaveView
*>::iterator i
= fade
[current
].waves
.begin(); i
!= fade
[current
].waves
.end(); ++i
) {
748 (*i
)->property_gain_src() = static_cast<Evoral::Curve
*>(&fade
[current
].gain_curve
.curve());
753 CrossfadeEditor::apply_preset (Preset
*preset
)
756 WhichFade wf
= find(fade_in_presets
->begin(), fade_in_presets
->end(), preset
) != fade_in_presets
->end() ? In
: Out
;
761 select_in_button
.clicked();
763 select_out_button
.clicked();
766 curve_select_clicked (wf
);
769 for (list
<Point
*>::iterator i
= fade
[current
].points
.begin(); i
!= fade
[current
].points
.end(); ++i
) {
773 fade
[current
].points
.clear ();
775 for (Preset::iterator i
= preset
->begin(); i
!= preset
->end(); ++i
) {
776 Point
* p
= make_point ();
777 p
->move_to (x_coordinate ((*i
).x
), y_coordinate ((*i
).y
),
779 fade
[current
].points
.push_back (p
);
786 CrossfadeEditor::apply ()
788 _session
->begin_reversible_command (_("Edit crossfade"));
790 XMLNode
& before
= xfade
->get_state ();
794 _session
->add_command (new MementoCommand
<Crossfade
> (*xfade
.get(), &before
, &xfade
->get_state ()));
795 _session
->commit_reversible_command ();
799 CrossfadeEditor::_apply_to (boost::shared_ptr
<Crossfade
> xf
)
801 ARDOUR::AutomationList
& in (xf
->fade_in());
802 ARDOUR::AutomationList
& out (xf
->fade_out());
807 ARDOUR::AutomationList::const_iterator the_end
= in
.end();
810 double firstx
= (*in
.begin())->when
;
811 double endx
= (*the_end
)->when
;
812 double miny
= in
.get_min_y ();
813 double maxy
= in
.get_max_y ();
818 for (list
<Point
*>::iterator i
= fade
[In
].points
.begin(); i
!= fade
[In
].points
.end(); ++i
) {
820 double when
= firstx
+ ((*i
)->x
* (endx
- firstx
));
821 double value
= (*i
)->y
; // miny + ((*i)->y * (maxy - miny));
822 in
.add (when
, value
);
830 firstx
= (*out
.begin())->when
;
831 endx
= (*the_end
)->when
;
832 miny
= out
.get_min_y ();
833 maxy
= out
.get_max_y ();
838 for (list
<Point
*>::iterator i
= fade
[Out
].points
.begin(); i
!= fade
[Out
].points
.end(); ++i
) {
840 double when
= firstx
+ ((*i
)->x
* (endx
- firstx
));
841 double value
= (*i
)->y
; // miny + ((*i)->y * (maxy - miny));
842 out
.add (when
, value
);
850 CrossfadeEditor::setup (boost::shared_ptr
<Crossfade
> xfade
)
853 xfade
->set_active (true);
854 xfade
->fade_in().curve().solve ();
855 xfade
->fade_out().curve().solve ();
859 CrossfadeEditor::clear ()
861 for (list
<Point
*>::iterator i
= fade
[current
].points
.begin(); i
!= fade
[current
].points
.end(); ++i
) {
865 fade
[current
].points
.clear ();
871 CrossfadeEditor::reset ()
873 set (xfade
->fade_in(), In
);
874 set (xfade
->fade_out(), Out
);
876 curve_select_clicked (current
);
880 CrossfadeEditor::build_presets ()
884 fade_in_presets
= new Presets
;
885 fade_out_presets
= new Presets
;
889 p
= new Preset ("Linear (-6dB)", "crossfade-in-linear");
890 p
->push_back (PresetPoint (0, 0));
891 p
->push_back (PresetPoint (0.000000, 0.000000));
892 p
->push_back (PresetPoint (0.166667, 0.166366));
893 p
->push_back (PresetPoint (0.333333, 0.332853));
894 p
->push_back (PresetPoint (0.500000, 0.499459));
895 p
->push_back (PresetPoint (0.666667, 0.666186));
896 p
->push_back (PresetPoint (0.833333, 0.833033));
897 p
->push_back (PresetPoint (1.000000, 1.000000));
898 fade_in_presets
->push_back (p
);
900 p
= new Preset ("S(1)-curve", "crossfade-in-S1");
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
);
909 p
= new Preset ("S(2)-curve", "crossfade-in-S2");
910 p
->push_back (PresetPoint (0.0, 0.0));
911 p
->push_back (PresetPoint (0.055, 0.222));
912 p
->push_back (PresetPoint (0.163, 0.35));
913 p
->push_back (PresetPoint (0.837, 0.678));
914 p
->push_back (PresetPoint (0.945, 0.783));
915 p
->push_back (PresetPoint (1.0, 1.0));
916 fade_in_presets
->push_back (p
);
918 p
= new Preset ("Constant Power (-3dB)", "crossfade-in-constant-power");
920 p
->push_back (PresetPoint (0.000000, 0.000000));
921 p
->push_back (PresetPoint (0.166667, 0.282192));
922 p
->push_back (PresetPoint (0.333333, 0.518174));
923 p
->push_back (PresetPoint (0.500000, 0.707946));
924 p
->push_back (PresetPoint (0.666667, 0.851507));
925 p
->push_back (PresetPoint (0.833333, 0.948859));
926 p
->push_back (PresetPoint (1.000000, 1.000000));
928 fade_in_presets
->push_back (p
);
930 if (!Profile
->get_sae()) {
932 p
= new Preset ("Short cut", "crossfade-in-short-cut");
933 p
->push_back (PresetPoint (0, 0));
934 p
->push_back (PresetPoint (0.389401, 0.0333333));
935 p
->push_back (PresetPoint (0.629032, 0.0861111));
936 p
->push_back (PresetPoint (0.829493, 0.233333));
937 p
->push_back (PresetPoint (0.9447, 0.483333));
938 p
->push_back (PresetPoint (0.976959, 0.697222));
939 p
->push_back (PresetPoint (1, 1));
940 fade_in_presets
->push_back (p
);
942 p
= new Preset ("Slow cut", "crossfade-in-slow-cut");
943 p
->push_back (PresetPoint (0, 0));
944 p
->push_back (PresetPoint (0.304147, 0.0694444));
945 p
->push_back (PresetPoint (0.529954, 0.152778));
946 p
->push_back (PresetPoint (0.725806, 0.333333));
947 p
->push_back (PresetPoint (0.847926, 0.558333));
948 p
->push_back (PresetPoint (0.919355, 0.730556));
949 p
->push_back (PresetPoint (1, 1));
950 fade_in_presets
->push_back (p
);
952 p
= new Preset ("Fast cut", "crossfade-in-fast-cut");
953 p
->push_back (PresetPoint (0, 0));
954 p
->push_back (PresetPoint (0.0737327, 0.308333));
955 p
->push_back (PresetPoint (0.246544, 0.658333));
956 p
->push_back (PresetPoint (0.470046, 0.886111));
957 p
->push_back (PresetPoint (0.652074, 0.972222));
958 p
->push_back (PresetPoint (0.771889, 0.988889));
959 p
->push_back (PresetPoint (1, 1));
960 fade_in_presets
->push_back (p
);
962 p
= new Preset ("Long cut", "crossfade-in-long-cut");
963 p
->push_back (PresetPoint (0, 0));
964 p
->push_back (PresetPoint (0.0207373, 0.197222));
965 p
->push_back (PresetPoint (0.0645161, 0.525));
966 p
->push_back (PresetPoint (0.152074, 0.802778));
967 p
->push_back (PresetPoint (0.276498, 0.919444));
968 p
->push_back (PresetPoint (0.481567, 0.980556));
969 p
->push_back (PresetPoint (0.767281, 1));
970 p
->push_back (PresetPoint (1, 1));
971 fade_in_presets
->push_back (p
);
976 // p = new Preset ("regout.xpm");
977 p
= new Preset ("Linear (-6dB cut)", "crossfade-out-linear");
978 p
->push_back (PresetPoint (0, 1));
979 p
->push_back (PresetPoint (0.000000, 1.000000));
980 p
->push_back (PresetPoint (0.166667, 0.833033));
981 p
->push_back (PresetPoint (0.333333, 0.666186));
982 p
->push_back (PresetPoint (0.500000, 0.499459));
983 p
->push_back (PresetPoint (0.666667, 0.332853));
984 p
->push_back (PresetPoint (0.833333, 0.166366));
985 p
->push_back (PresetPoint (1.000000, 0.000000));
986 fade_out_presets
->push_back (p
);
988 p
= new Preset ("S(1)-Curve", "crossfade-out-S1");
989 p
->push_back (PresetPoint (0, 1));
990 p
->push_back (PresetPoint (0.1, 0.99));
991 p
->push_back (PresetPoint (0.2, 0.97));
992 p
->push_back (PresetPoint (0.8, 0.03));
993 p
->push_back (PresetPoint (0.9, 0.01));
994 p
->push_back (PresetPoint (1, 0));
995 fade_out_presets
->push_back (p
);
997 p
= new Preset ("S(2)-Curve", "crossfade-out-S2");
998 p
->push_back (PresetPoint (0.0, 1.0));
999 p
->push_back (PresetPoint (0.163, 0.678));
1000 p
->push_back (PresetPoint (0.055, 0.783));
1001 p
->push_back (PresetPoint (0.837, 0.35));
1002 p
->push_back (PresetPoint (0.945, 0.222));
1003 p
->push_back (PresetPoint (1.0, 0.0));
1004 fade_out_presets
->push_back (p
);
1006 // p = new Preset ("linout.xpm");
1007 p
= new Preset ("Constant Power (-3dB cut)", "crossfade-out-constant-power");
1008 p
->push_back (PresetPoint (0.000000, 1.000000));
1009 p
->push_back (PresetPoint (0.166667, 0.948859));
1010 p
->push_back (PresetPoint (0.333333, 0.851507));
1011 p
->push_back (PresetPoint (0.500000, 0.707946));
1012 p
->push_back (PresetPoint (0.666667, 0.518174));
1013 p
->push_back (PresetPoint (0.833333, 0.282192));
1014 p
->push_back (PresetPoint (1.000000, 0.000000));
1015 fade_out_presets
->push_back (p
);
1017 if (!Profile
->get_sae()) {
1018 // p = new Preset ("hiout.xpm");
1019 p
= new Preset ("Short cut", "crossfade-out-short-cut");
1020 p
->push_back (PresetPoint (0, 1));
1021 p
->push_back (PresetPoint (0.305556, 1));
1022 p
->push_back (PresetPoint (0.548611, 0.991736));
1023 p
->push_back (PresetPoint (0.759259, 0.931129));
1024 p
->push_back (PresetPoint (0.918981, 0.68595));
1025 p
->push_back (PresetPoint (0.976852, 0.22865));
1026 p
->push_back (PresetPoint (1, 0));
1027 fade_out_presets
->push_back (p
);
1029 p
= new Preset ("Slow cut", "crossfade-out-slow-cut");
1030 p
->push_back (PresetPoint (0, 1));
1031 p
->push_back (PresetPoint (0.228111, 0.988889));
1032 p
->push_back (PresetPoint (0.347926, 0.972222));
1033 p
->push_back (PresetPoint (0.529954, 0.886111));
1034 p
->push_back (PresetPoint (0.753456, 0.658333));
1035 p
->push_back (PresetPoint (0.9262673, 0.308333));
1036 p
->push_back (PresetPoint (1, 0));
1037 fade_out_presets
->push_back (p
);
1039 p
= new Preset ("Fast cut", "crossfade-out-fast-cut");
1040 p
->push_back (PresetPoint (0, 1));
1041 p
->push_back (PresetPoint (0.080645, 0.730556));
1042 p
->push_back (PresetPoint (0.277778, 0.289256));
1043 p
->push_back (PresetPoint (0.470046, 0.152778));
1044 p
->push_back (PresetPoint (0.695853, 0.0694444));
1045 p
->push_back (PresetPoint (1, 0));
1046 fade_out_presets
->push_back (p
);
1048 // p = new Preset ("loout.xpm");
1049 p
= new Preset ("Long cut", "crossfade-out-long-cut");
1050 p
->push_back (PresetPoint (0, 1));
1051 p
->push_back (PresetPoint (0.023041, 0.697222));
1052 p
->push_back (PresetPoint (0.0553, 0.483333));
1053 p
->push_back (PresetPoint (0.170507, 0.233333));
1054 p
->push_back (PresetPoint (0.370968, 0.0861111));
1055 p
->push_back (PresetPoint (0.610599, 0.0333333));
1056 p
->push_back (PresetPoint (1, 0));
1057 fade_out_presets
->push_back (p
);
1063 CrossfadeEditor::curve_select_clicked (WhichFade wf
)
1069 for (vector
<ArdourCanvas::WaveView
*>::iterator i
= fade
[In
].waves
.begin(); i
!= fade
[In
].waves
.end(); ++i
) {
1070 (*i
)->property_wave_color() = ARDOUR_UI::config()->canvasvar_SelectedCrossfadeEditorWave
.get();
1071 (*i
)->property_fill_color() = ARDOUR_UI::config()->canvasvar_SelectedCrossfadeEditorWave
.get();
1074 for (vector
<ArdourCanvas::WaveView
*>::iterator i
= fade
[Out
].waves
.begin(); i
!= fade
[Out
].waves
.end(); ++i
) {
1075 (*i
)->property_wave_color() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorWave
.get();
1076 (*i
)->property_fill_color() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorWave
.get();
1079 fade
[In
].line
->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_SelectedCrossfadeEditorLine
.get();
1080 fade
[Out
].line
->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorLine
.get();
1081 fade
[Out
].shading
->hide();
1082 fade
[In
].shading
->show();
1084 for (list
<Point
*>::iterator i
= fade
[Out
].points
.begin(); i
!= fade
[Out
].points
.end(); ++i
) {
1088 for (list
<Point
*>::iterator i
= fade
[In
].points
.begin(); i
!= fade
[In
].points
.end(); ++i
) {
1094 for (vector
<ArdourCanvas::WaveView
*>::iterator i
= fade
[In
].waves
.begin(); i
!= fade
[In
].waves
.end(); ++i
) {
1095 (*i
)->property_wave_color() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorWave
.get();
1096 (*i
)->property_fill_color() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorWave
.get();
1099 for (vector
<ArdourCanvas::WaveView
*>::iterator i
= fade
[Out
].waves
.begin(); i
!= fade
[Out
].waves
.end(); ++i
) {
1100 (*i
)->property_wave_color() = ARDOUR_UI::config()->canvasvar_SelectedCrossfadeEditorWave
.get();
1101 (*i
)->property_fill_color() = ARDOUR_UI::config()->canvasvar_SelectedCrossfadeEditorWave
.get();
1104 fade
[Out
].line
->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_SelectedCrossfadeEditorLine
.get();
1105 fade
[In
].line
->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeEditorLine
.get();
1106 fade
[In
].shading
->hide();
1107 fade
[Out
].shading
->show();
1109 for (list
<Point
*>::iterator i
= fade
[In
].points
.begin(); i
!= fade
[In
].points
.end(); ++i
) {
1113 for (list
<Point
*>::iterator i
= fade
[Out
].points
.begin(); i
!= fade
[Out
].points
.end(); ++i
) {
1121 CrossfadeEditor::x_coordinate (double& xfract
) const
1123 xfract
= min (1.0, xfract
);
1124 xfract
= max (0.0, xfract
);
1126 return canvas_border
+ (xfract
* effective_width());
1130 CrossfadeEditor::y_coordinate (double& yfract
) const
1132 yfract
= min (1.0, yfract
);
1133 yfract
= max (0.0, yfract
);
1135 return (canvas
->get_allocation().get_height() - (canvas_border
)) - (yfract
* effective_height());
1139 CrossfadeEditor::make_waves (boost::shared_ptr
<AudioRegion
> region
, WhichFade which
)
1142 uint32_t nchans
= region
->n_channels();
1147 color
= ARDOUR_UI::config()->canvasvar_SelectedCrossfadeEditorWave
.get();
1149 color
= ARDOUR_UI::config()->canvasvar_CrossfadeEditorWave
.get();
1152 ht
= canvas
->get_allocation().get_height() / (double) nchans
;
1153 spu
= xfade
->length() / (double) effective_width();
1155 delete _peaks_ready_connection
;
1156 _peaks_ready_connection
= 0;
1158 for (uint32_t n
= 0; n
< nchans
; ++n
) {
1160 gdouble yoff
= n
* ht
;
1162 if (region
->audio_source(n
)->peaks_ready (boost::bind (&CrossfadeEditor::peaks_ready
, this, boost::weak_ptr
<AudioRegion
>(region
), which
), &_peaks_ready_connection
, gui_context())) {
1163 WaveView
* waveview
= new WaveView (*(canvas
->root()));
1165 waveview
->property_data_src() = region
.get();
1166 waveview
->property_cache_updater() = true;
1167 waveview
->property_cache() = WaveView::create_cache();
1168 waveview
->property_channel() = n
;
1169 waveview
->property_length_function() = (void*) region_length_from_c
;
1170 waveview
->property_sourcefile_length_function() = (void*) sourcefile_length_from_c
;
1171 waveview
->property_peak_function() = (void*) region_read_peaks_from_c
;
1172 waveview
->property_gain_function() = (void*) curve_get_vector_from_c
;
1173 waveview
->property_gain_src() = static_cast<Evoral::Curve
*>(&fade
[which
].gain_curve
.curve());
1174 waveview
->property_x() = canvas_border
;
1175 waveview
->property_y() = yoff
;
1176 waveview
->property_height() = ht
;
1177 waveview
->property_samples_per_unit() = spu
;
1178 waveview
->property_amplitude_above_axis() = 2.0;
1179 waveview
->property_wave_color() = color
;
1180 waveview
->property_fill_color() = color
;
1183 waveview
->property_region_start() = region
->start();
1185 waveview
->property_region_start() = region
->start()+region
->length()-xfade
->length();
1187 waveview
->lower_to_bottom();
1188 fade
[which
].waves
.push_back (waveview
);
1192 toplevel
->lower_to_bottom();
1196 CrossfadeEditor::peaks_ready (boost::weak_ptr
<AudioRegion
> wr
, WhichFade which
)
1198 boost::shared_ptr
<AudioRegion
> r (wr
.lock());
1204 /* this should never be called, because the peak files for an xfade
1205 will be ready by the time we want them. but our API forces us
1206 to provide this, so ..
1208 delete _peaks_ready_connection
;
1209 _peaks_ready_connection
= 0;
1211 make_waves (r
, which
);
1215 CrossfadeEditor::audition (Audition which
)
1217 AudioPlaylist
& pl (_session
->the_auditioner()->prepare_playlist());
1220 nframes_t left_start_offset
;
1221 nframes_t right_length
;
1222 nframes_t left_length
;
1224 if (which
!= Right
&& preroll_button
.get_active()) {
1225 preroll
= _session
->frame_rate() * 2; //2 second hardcoded preroll for now
1230 if (which
!= Left
&& postroll_button
.get_active()) {
1231 postroll
= _session
->frame_rate() * 2; //2 second hardcoded postroll for now
1236 // Is there enough data for the whole preroll?
1237 left_length
= xfade
->length();
1238 if ((left_start_offset
= xfade
->out()->length() - xfade
->length()) > preroll
) {
1239 left_start_offset
-= preroll
;
1241 preroll
= left_start_offset
;
1242 left_start_offset
= 0;
1244 left_length
+= preroll
;
1246 // Is there enough data for the whole postroll?
1247 right_length
= xfade
->length();
1248 if ((xfade
->in()->length() - right_length
) > postroll
) {
1249 right_length
+= postroll
;
1251 right_length
= xfade
->in()->length();
1254 PropertyList left_plist
;
1255 PropertyList right_plist
;
1258 left_plist
.add (ARDOUR::Properties::start
, left_start_offset
);
1259 left_plist
.add (ARDOUR::Properties::length
, left_length
);
1260 left_plist
.add (ARDOUR::Properties::name
, string ("xfade out"));
1261 left_plist
.add (ARDOUR::Properties::layer
, 0);
1262 left_plist
.add (ARDOUR::Properties::fade_in_active
, true);
1264 right_plist
.add (ARDOUR::Properties::start
, 0);
1265 right_plist
.add (ARDOUR::Properties::length
, right_length
);
1266 right_plist
.add (ARDOUR::Properties::name
, string("xfade in"));
1267 right_plist
.add (ARDOUR::Properties::layer
, 0);
1268 right_plist
.add (ARDOUR::Properties::fade_out_active
, true);
1270 if (which
== Left
) {
1271 right_plist
.add (ARDOUR::Properties::scale_amplitude
, 0.0f
);
1272 } else if (which
== Right
) {
1273 left_plist
.add (ARDOUR::Properties::scale_amplitude
, 0.0f
);
1276 boost::shared_ptr
<AudioRegion
> left (boost::dynamic_pointer_cast
<AudioRegion
>
1277 (RegionFactory::create (xfade
->out(), left_plist
, false)));
1278 boost::shared_ptr
<AudioRegion
> right (boost::dynamic_pointer_cast
<AudioRegion
>
1279 (RegionFactory::create (xfade
->in(), right_plist
, false)));
1281 // apply a 20ms declicking fade at the start and end of auditioning
1282 // XXX this should really be a property
1284 left
->set_fade_in_length (_session
->frame_rate() / 50);
1285 right
->set_fade_out_length (_session
->frame_rate() / 50);
1287 pl
.add_region (left
, 0);
1288 pl
.add_region (right
, 1 + preroll
);
1290 /* there is only one ... */
1291 pl
.foreach_crossfade (sigc::mem_fun (*this, &CrossfadeEditor::setup
));
1293 _session
->audition_playlist ();
1297 CrossfadeEditor::audition_both ()
1303 CrossfadeEditor::audition_left_dry ()
1307 plist
.add (ARDOUR::Properties::start
, xfade
->out()->length() - xfade
->length());
1308 plist
.add (ARDOUR::Properties::length
, xfade
->length());
1309 plist
.add (ARDOUR::Properties::name
, string("xfade left"));
1310 plist
.add (ARDOUR::Properties::layer
, 0);
1312 boost::shared_ptr
<AudioRegion
> left (boost::dynamic_pointer_cast
<AudioRegion
>
1313 (RegionFactory::create (xfade
->out(), plist
, false)));
1315 _session
->audition_region (left
);
1319 CrossfadeEditor::audition_left ()
1325 CrossfadeEditor::audition_right_dry ()
1329 plist
.add (ARDOUR::Properties::start
, 0);
1330 plist
.add (ARDOUR::Properties::length
, xfade
->length());
1331 plist
.add (ARDOUR::Properties::name
, string ("xfade right"));
1332 plist
.add (ARDOUR::Properties::layer
, 0);
1334 boost::shared_ptr
<AudioRegion
> right (boost::dynamic_pointer_cast
<AudioRegion
>
1335 (RegionFactory::create (xfade
->in(), plist
, false)));
1337 _session
->audition_region (right
);
1341 CrossfadeEditor::audition_right ()
1347 CrossfadeEditor::cancel_audition ()
1349 _session
->cancel_audition ();
1353 CrossfadeEditor::audition_toggled ()
1357 if ((x
= audition_both_button
.get_active ()) != _session
->is_auditioning()) {
1368 CrossfadeEditor::audition_right_toggled ()
1372 if ((x
= audition_right_button
.get_active ()) != _session
->is_auditioning()) {
1383 CrossfadeEditor::audition_right_dry_toggled ()
1387 if ((x
= audition_right_dry_button
.get_active ()) != _session
->is_auditioning()) {
1390 audition_right_dry ();
1398 CrossfadeEditor::audition_left_toggled ()
1402 if ((x
= audition_left_button
.get_active ()) != _session
->is_auditioning()) {
1413 CrossfadeEditor::audition_left_dry_toggled ()
1417 if ((x
= audition_left_dry_button
.get_active ()) != _session
->is_auditioning()) {
1420 audition_left_dry ();
1428 CrossfadeEditor::on_key_press_event (GdkEventKey */
*ev*/
)
1434 CrossfadeEditor::on_key_release_event (GdkEventKey
* ev
)
1436 switch (ev
->keyval
) {
1438 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::PrimaryModifier
)) {
1439 audition_right_dry_button
.set_active (!audition_right_dry_button
.get_active());
1441 audition_right_button
.set_active (!audition_right_button
.get_active());
1446 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::PrimaryModifier
)) {
1447 audition_left_dry_button
.set_active (!audition_left_dry_button
.get_active());
1449 audition_left_button
.set_active (!audition_left_button
.get_active());
1454 if (_session
->is_auditioning()) {
1457 audition_both_button
.set_active (!audition_both_button
.get_active());