ardour
crossfade_edit.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2004 Paul Davis
3 
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.
8 
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.
13 
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.
17 
18 */
19 
20 #include <cmath>
21 
22 #include <sigc++/bind.h>
23 
24 #include <gtkmm/frame.h>
25 #include <gtkmm/image.h>
26 #include <gtkmm/scrolledwindow.h>
27 
28 
29 #include "pbd/memento_command.h"
30 #include "ardour/automation_list.h"
31 #include "evoral/Curve.hpp"
32 #include "ardour/crossfade.h"
33 #include "ardour/dB.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"
40 #include "ardour/crossfade_binder.h"
41 
42 #include <gtkmm2ext/gtk_ui.h>
43 
44 #include "canvas/rectangle.h"
45 #include "canvas/wave_view.h"
46 #include "canvas/line.h"
47 #include "canvas/polygon.h"
48 
49 #include "ardour_ui.h"
50 #include "crossfade_edit.h"
51 #include "rgb_macros.h"
52 #include "keyboard.h"
53 #include "gui_thread.h"
54 #include "actions.h"
55 
56 using namespace std;
57 using namespace ARDOUR;
58 using namespace PBD;
59 using namespace Gtk;
60 using namespace Editing;
61 
63 
64 #include "i18n.h"
65 
66 const int32_t CrossfadeEditor::Point::size = 7;
67 const double CrossfadeEditor::canvas_border = 10;
70 
72  : line (0)
73  , normative_curve (Evoral::Parameter(GainAutomation))
74  , gain_curve (Evoral::Parameter(GainAutomation))
75 {
76 }
77 
79  : ArdourDialog (_("Edit Crossfade")),
80  xfade (xf),
81  clear_button (_("Clear")),
82  revert_button (_("Reset")),
83  audition_both_button (_("Fade")),
84  audition_left_dry_button (_("Out (dry)")),
85  audition_left_button (_("Out")),
86  audition_right_dry_button (_("In (dry)")),
87  audition_right_button (_("In")),
88 
89  preroll_button (_("With Pre-roll")),
90  postroll_button (_("With Post-roll")),
91 
92  miny (my),
93  maxy (mxy),
94 
95  fade_in_table (3, 3),
96  fade_out_table (3, 3),
97 
98  select_in_button (_("Fade In")),
99  select_out_button (_("Fade Out")),
100 
102 
103 {
104  set_session (s);
105 
106  set_wmclass (X_("ardour_automationedit"), PROGRAM_NAME);
107  set_name ("CrossfadeEditWindow");
108 
109  add_accel_group (ActionManager::ui_manager->get_accel_group());
110 
111  add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
112 
113  RadioButtonGroup sel_but_group = select_in_button.get_group();
114  select_out_button.set_group (sel_but_group);
115  select_out_button.set_mode (false);
116  select_in_button.set_mode (false);
117 
118  get_action_area()->set_layout(BUTTONBOX_SPREAD);
119  get_action_area()->pack_start(clear_button);
120  get_action_area()->pack_start(revert_button);
121  cancel_button = add_button ("Cancel", RESPONSE_CANCEL);
122  ok_button = add_button ("OK", RESPONSE_ACCEPT);
123 
124  if (fade_in_presets == 0) {
125  build_presets ();
126  }
127 
128  point_grabbed = false;
129  toplevel = 0;
130 
131  canvas = new ArdourCanvas::GtkCanvas ();
132  canvas->signal_size_allocate().connect (sigc::mem_fun(*this, &CrossfadeEditor::canvas_allocation));
133  canvas->set_size_request (425, 200);
134 
135  toplevel = new ArdourCanvas::Rectangle (canvas->root());
136  toplevel->set (ArdourCanvas::Rect (0, 0, 10, 10));
137  toplevel->set_fill (true);
138  toplevel->set_fill_color (ARDOUR_UI::config()->get_CrossfadeEditorBase());
139  toplevel->set_outline (false);
140  toplevel->Event.connect (sigc::mem_fun (*this, &CrossfadeEditor::canvas_event));
141 
142  fade[Out].line = new ArdourCanvas::PolyLine (canvas->root());
143  fade[Out].line->set_outline_color (ARDOUR_UI::config()->get_CrossfadeEditorLine());
144 
145  fade[Out].shading = new ArdourCanvas::Polygon (canvas->root());
146  fade[Out].shading->set_fill_color (ARDOUR_UI::config()->get_CrossfadeEditorLineShading());
147 
148  fade[In].line = new ArdourCanvas::PolyLine (canvas->root());
149  fade[In].line->set_outline_color (ARDOUR_UI::config()->get_CrossfadeEditorLine());
150 
151  fade[In].shading = new ArdourCanvas::Polygon (canvas->root());
152  fade[In].shading->set_fill_color (ARDOUR_UI::config()->get_CrossfadeEditorLineShading());
153 
154  fade[In].shading->Event.connect (sigc::mem_fun (*this, &CrossfadeEditor::canvas_event));
155  fade[In].line->Event.connect (sigc::mem_fun (*this, &CrossfadeEditor::curve_event));
156  fade[Out].shading->Event.connect (sigc::mem_fun (*this, &CrossfadeEditor::canvas_event));
157  fade[Out].line->Event.connect (sigc::mem_fun (*this, &CrossfadeEditor::curve_event));
158 
159  select_in_button.set_name (X_("CrossfadeEditCurveButton"));
160  select_out_button.set_name (X_("CrossfadeEditCurveButton"));
161 
162  select_in_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &CrossfadeEditor::curve_select_clicked), In));
163  select_out_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &CrossfadeEditor::curve_select_clicked), Out));
164 
165  HBox* acbox = manage (new HBox);
166 
167  audition_box.set_border_width (7);
168  audition_box.set_spacing (5);
169  audition_box.set_homogeneous (false);
170  audition_box.pack_start (audition_left_dry_button, false, false);
171  audition_box.pack_start (audition_left_button, false, false);
172  audition_box.pack_start (audition_both_button, false, false);
173  audition_box.pack_start (audition_right_button, false, false);
174  audition_box.pack_start (audition_right_dry_button, false, false);
175 
176  Frame* audition_frame = manage (new Frame (_("Audition")));
177 
178  audition_frame->set_name (X_("CrossfadeEditFrame"));
179  audition_frame->add (audition_box);
180 
181  acbox->pack_start (*audition_frame, true, false);
182 
183  Frame* canvas_frame = manage (new Frame);
184  canvas_frame->add (*canvas);
185  canvas_frame->set_shadow_type (Gtk::SHADOW_IN);
186 
187  fade_in_table.attach (select_in_button, 0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND);
188  fade_out_table.attach (select_out_button, 0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND);
189 
190  Image *pxmap;
191  Button* pbutton;
192  int row;
193  int col;
194 
195  row = 1;
196  col = 0;
197 
198  for (list<Preset*>::iterator i = fade_in_presets->begin(); i != fade_in_presets->end(); ++i) {
199 
200  pxmap = manage (new Image (::get_icon ((*i)->image_name)));
201  pbutton = manage (new Button);
202  pbutton->add (*pxmap);
203  pbutton->set_name ("CrossfadeEditButton");
204  pbutton->signal_clicked().connect (sigc::bind (sigc::mem_fun(*this, &CrossfadeEditor::apply_preset), *i));
205  ARDOUR_UI::instance()->set_tip (pbutton, (*i)->name, "");
206  fade_in_table.attach (*pbutton, col, col+1, row, row+1);
207  fade_in_buttons.push_back (pbutton);
208 
209  col++;
210 
211  if (col == 2) {
212  col = 0;
213  row++;
214  }
215  }
216 
217  row = 1;
218  col = 0;
219 
220  for (list<Preset*>::iterator i = fade_out_presets->begin(); i != fade_out_presets->end(); ++i) {
221 
222  pxmap = manage (new Image (::get_icon ((*i)->image_name)));
223  pbutton = manage (new Button);
224  pbutton->add (*pxmap);
225  pbutton->set_name ("CrossfadeEditButton");
226  pbutton->signal_clicked().connect (sigc::bind (sigc::mem_fun(*this, &CrossfadeEditor::apply_preset), *i));
227  ARDOUR_UI::instance()->set_tip (pbutton, (*i)->name, "");
228  fade_out_table.attach (*pbutton, col, col+1, row, row+1);
229  fade_out_buttons.push_back (pbutton);
230 
231  col++;
232 
233  if (col == 2) {
234  col = 0;
235  row++;
236  }
237  }
238 
239  clear_button.set_name ("CrossfadeEditButton");
240  revert_button.set_name ("CrossfadeEditButton");
241  ok_button->set_name ("CrossfadeEditButton");
242  cancel_button->set_name ("CrossfadeEditButton");
243  preroll_button.set_name ("CrossfadeEditButton");
244  postroll_button.set_name ("CrossfadeEditButton");
245  audition_both_button.set_name ("CrossfadeEditAuditionButton");
246  audition_left_dry_button.set_name ("CrossfadeEditAuditionButton");
247  audition_left_button.set_name ("CrossfadeEditAuditionButton");
248  audition_right_dry_button.set_name ("CrossfadeEditAuditionButton");
249  audition_right_button.set_name ("CrossfadeEditAuditionButton");
250 
251  clear_button.signal_clicked().connect (sigc::mem_fun(*this, &CrossfadeEditor::clear));
252  revert_button.signal_clicked().connect (sigc::mem_fun(*this, &CrossfadeEditor::reset));
253  audition_both_button.signal_toggled().connect (sigc::mem_fun(*this, &CrossfadeEditor::audition_toggled));
254  audition_right_button.signal_toggled().connect (sigc::mem_fun(*this, &CrossfadeEditor::audition_right_toggled));
255  audition_right_dry_button.signal_toggled().connect (sigc::mem_fun(*this, &CrossfadeEditor::audition_right_dry_toggled));
256  audition_left_button.signal_toggled().connect (sigc::mem_fun(*this, &CrossfadeEditor::audition_left_toggled));
257  audition_left_dry_button.signal_toggled().connect (sigc::mem_fun(*this, &CrossfadeEditor::audition_left_dry_toggled));
258 
259  roll_box.pack_start (preroll_button, false, false);
260  roll_box.pack_start (postroll_button, false, false);
261 
262  Gtk::HBox* rcenter_box = manage (new HBox);
263  rcenter_box->pack_start (roll_box, true, false);
264 
265  VBox* vpacker2 = manage (new (VBox));
266 
267  vpacker2->set_border_width (12);
268  vpacker2->set_spacing (7);
269  vpacker2->pack_start (*acbox, false, false);
270  vpacker2->pack_start (*rcenter_box, false, false);
271 
272  curve_button_box.set_spacing (7);
273  curve_button_box.pack_start (fade_out_table, false, false, 12);
274  curve_button_box.pack_start (*vpacker2, false, false, 12);
275  curve_button_box.pack_start (fade_in_table, false, false, 12);
276 
277  get_vbox()->pack_start (*canvas_frame, true, true);
278  get_vbox()->pack_start (curve_button_box, false, false);
279 
280  /* button to allow hackers to check the actual curve values */
281 
282 // Button* foobut = manage (new Button ("dump"));
283 // foobut-.signal_clicked().connect (sigc::mem_fun(*this, &CrossfadeEditor::dump));
284 // vpacker.pack_start (*foobut, false, false);
285 
286  current = In;
287  set (xfade->fade_in(), In);
288 
289  current = Out;
290  set (xfade->fade_out(), Out);
291 
293 
294  xfade->PropertyChanged.connect (state_connection, invalidator (*this), boost::bind (&CrossfadeEditor::xfade_changed, this, _1), gui_context());
295 
297  show_all_children();
298 }
299 
301 {
302  /* most objects will be destroyed when the toplevel window is. */
303 
304  for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
305  delete *i;
306  }
307 
308  for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
309  delete *i;
310  }
311 
313 }
314 
315 void
317 {
318  for (AutomationList::iterator i = fade[Out].normative_curve.begin(); i != fade[Out].normative_curve.end(); ++i) {
319  cerr << (*i)->when << ' ' << (*i)->value << endl;
320  }
321 }
322 
323 void
325 {
327 
328  if (!yn) {
329  audition_both_button.set_active (false);
330  audition_left_button.set_active (false);
331  audition_right_button.set_active (false);
332  audition_left_dry_button.set_active (false);
333  audition_right_dry_button.set_active (false);
334  }
335 }
336 
337 void
339 {
340  double firstx, endx;
342 
343  for (list<Point*>::iterator i = fade[which].points.begin(); i != fade[which].points.end(); ++i) {
344  delete *i;
345  }
346 
347  fade[which].points.clear ();
348  fade[which].gain_curve.clear ();
349  fade[which].normative_curve.clear ();
350 
351  if (curve.empty()) {
352  goto out;
353  }
354 
355  the_end = curve.end();
356  --the_end;
357 
358  firstx = (*curve.begin())->when;
359  endx = (*the_end)->when;
360 
361  for (ARDOUR::AutomationList::const_iterator i = curve.begin(); i != curve.end(); ++i) {
362 
363  double xfract = ((*i)->when - firstx) / (endx - firstx);
364  double yfract = ((*i)->value - miny) / (maxy - miny);
365 
366  Point* p = make_point ();
367 
368  p->move_to (x_coordinate (xfract), y_coordinate (yfract),
369  xfract, yfract);
370 
371  fade[which].points.push_back (p);
372  }
373 
374  /* no need to sort because curve is already time-ordered */
375 
376  out:
377 
378  swap (which, current);
379  redraw ();
380  swap (which, current);
381 }
382 
383 bool
385 {
386  /* treat it like a toplevel event */
387 
388  return canvas_event (event);
389 }
390 
391 bool
392 CrossfadeEditor::point_event (GdkEvent* event, Point* point)
393 {
394 
395  if (point->curve != fade[current].line) {
396  return FALSE;
397  }
398 
399  switch (event->type) {
400  case GDK_BUTTON_PRESS:
401  point_grabbed = true;
402  break;
403  case GDK_BUTTON_RELEASE:
404  point_grabbed = false;
405 
406  if (Keyboard::is_delete_event (&event->button)) {
407  fade[current].points.remove (point);
408  delete point;
409  }
410 
411  redraw ();
412  break;
413 
414  case GDK_MOTION_NOTIFY:
415  if (point_grabbed) {
416  double new_x, new_y;
417 
418  /* can't drag first or last points horizontally or vertically */
419 
420  if (point == fade[current].points.front() || point == fade[current].points.back()) {
421  new_x = point->x;
422  new_y = point->y;
423  } else {
424  new_x = (event->motion.x - canvas_border)/effective_width();
425  new_y = 1.0 - ((event->motion.y - canvas_border)/effective_height());
426  }
427 
428  point->move_to (x_coordinate (new_x), y_coordinate (new_y),
429  new_x, new_y);
430  redraw ();
431  }
432  break;
433  default:
434  break;
435  }
436  return TRUE;
437 }
438 
439 bool
441 {
442  switch (event->type) {
443  case GDK_BUTTON_PRESS:
444  add_control_point ((event->button.x - canvas_border)/effective_width(),
445  1.0 - ((event->button.y - canvas_border)/effective_height()));
446  return true;
447  break;
448  default:
449  break;
450  }
451  return false;
452 }
453 
455 {
456  delete box;
457 }
458 
461 {
462  Point* p = new Point;
463 
464  p->box = new ArdourCanvas::Rectangle (canvas->root());
465  p->box->set_fill (true);
466  p->box->set_fill_color (ARDOUR_UI::config()->get_CrossfadeEditorPointFill());
467  p->box->set_outline_color (ARDOUR_UI::config()->get_CrossfadeEditorPointOutline());
468 
469  p->curve = fade[current].line;
470 
471  p->box->Event.connect (sigc::bind (sigc::mem_fun (*this, &CrossfadeEditor::point_event), p));
472 
473  return p;
474 }
475 
476 void
478 {
479  PointSorter cmp;
480 
481  /* enforce end point x location */
482 
483  if (fade[current].points.empty()) {
484  x = 0.0;
485  } else if (fade[current].points.size() == 1) {
486  x = 1.0;
487  }
488 
489  Point* p = make_point ();
490 
491  p->move_to (x_coordinate (x), y_coordinate (y), x, y);
492 
493  fade[current].points.push_back (p);
494  fade[current].points.sort (cmp);
495 
496  redraw ();
497 }
498 
499 void
500 CrossfadeEditor::Point::move_to (double nx, double ny, double xfract, double yfract)
501 {
502  if ( xfract < 0.0 ) {
503  xfract = 0.0;
504  } else if ( xfract > 1.0 ) {
505  xfract = 1.0;
506  }
507 
508  if ( yfract < 0.0 ) {
509  yfract = 0.0;
510  } else if ( yfract > 1.0 ) {
511  yfract = 1.0;
512  }
513 
514  const double half_size = rint(size/2.0);
515  double x1 = nx - half_size;
516  double x2 = nx + half_size;
517 
518  box->set (ArdourCanvas::Rect (x1, ny - half_size, x2, ny + half_size));
519 
520  x = xfract;
521  y = yfract;
522 }
523 
524 void
525 CrossfadeEditor::canvas_allocation (Gtk::Allocation& /*alloc*/)
526 {
527  if (toplevel) {
528  toplevel->set (
529  ArdourCanvas::Rect (
530  0,
531  0,
532  canvas->get_allocation().get_width() + canvas_border,
533  canvas->get_allocation().get_height() + canvas_border
534  )
535  );
536  }
537 
538  /* XXX: CANVAS */
539 // canvas->set_scroll_region (0.0, 0.0,
540 // canvas->get_allocation().get_width(),
541 // canvas->get_allocation().get_height());
542 
543  Point* end = make_point ();
544  PointSorter cmp;
545 
546  if (fade[In].points.size() > 1) {
547  Point* old_end = fade[In].points.back();
548  fade[In].points.pop_back ();
549  end->move_to (x_coordinate (old_end->x),
550  y_coordinate (old_end->y),
551  old_end->x, old_end->y);
552  delete old_end;
553  } else {
554  double x = 1.0;
555  double y = 0.5;
556  end->move_to (x_coordinate (x), y_coordinate (y), x, y);
557 
558  }
559 
560  fade[In].points.push_back (end);
561  fade[In].points.sort (cmp);
562 
563  for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
564  (*i)->move_to (x_coordinate((*i)->x), y_coordinate((*i)->y),
565  (*i)->x, (*i)->y);
566  }
567 
568  end = make_point ();
569 
570  if (fade[Out].points.size() > 1) {
571  Point* old_end = fade[Out].points.back();
572  fade[Out].points.pop_back ();
573  end->move_to (x_coordinate (old_end->x),
574  y_coordinate (old_end->y),
575  old_end->x, old_end->y);
576  delete old_end;
577  } else {
578  double x = 1.0;
579  double y = 0.5;
580  end->move_to (x_coordinate (x), y_coordinate (y), x, y);
581 
582  }
583 
584  fade[Out].points.push_back (end);
585  fade[Out].points.sort (cmp);
586 
587  for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
588  (*i)->move_to (x_coordinate ((*i)->x),
589  y_coordinate ((*i)->y),
590  (*i)->x, (*i)->y);
591  }
592 
593  WhichFade old_current = current;
594  current = In;
595  redraw ();
596  current = Out;
597  redraw ();
598  current = old_current;
599 
600  double spu = xfade->length() / (double) effective_width();
601 
602  if (fade[In].waves.empty()) {
603  make_waves (xfade->in(), In);
604  }
605 
606  if (fade[Out].waves.empty()) {
607  make_waves (xfade->out(), Out);
608  }
609 
610  double ht;
611  vector<ArdourCanvas::WaveView*>::iterator i;
612  uint32_t n;
613 
614  ht = canvas->get_allocation().get_height() / xfade->in()->n_channels();
615 
616  for (n = 0, i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i, ++n) {
617  double yoff;
618 
619  yoff = n * ht;
620 
621  (*i)->set_y_position (yoff);
622  (*i)->set_height (ht);
623  (*i)->set_samples_per_pixel (spu);
624  }
625 
626  ht = canvas->get_allocation().get_height() / xfade->out()->n_channels();
627 
628  for (n = 0, i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i, ++n) {
629  double yoff;
630 
631  yoff = n * ht;
632 
633  (*i)->set_y_position (yoff);
634  (*i)->set_height (ht);
635  (*i)->set_samples_per_pixel (spu);
636  }
637 
638 }
639 
640 
641 void
643 {
644  set (xfade->fade_in(), In);
645  set (xfade->fade_out(), Out);
646 }
647 
648 void
650 {
651  if (canvas->get_allocation().get_width() < 2) {
652  return;
653  }
654 
655  framecnt_t len = xfade->length ();
656 
659 
660  for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
661  fade[current].normative_curve.add ((*i)->x, (*i)->y);
662  double offset;
663  if (current==In)
664  offset = xfade->in()->start();
665  else
666  offset = xfade->out()->start()+xfade->out()->length()-xfade->length();
667  fade[current].gain_curve.add (((*i)->x * len) + offset, (*i)->y);
668  }
669 
670 
671  size_t npoints = (size_t) effective_width();
672  float vec[npoints];
673 
674  fade[current].normative_curve.curve().get_vector (0, 1.0, vec, npoints);
675 
676  ArdourCanvas::Points pts;
677  ArdourCanvas::Points spts;
678 
679  while (pts.size() < npoints) {
680  pts.push_back (ArdourCanvas::Duple (0,0));
681  }
682 
683  while (spts.size() < npoints + 3) {
684  spts.push_back (ArdourCanvas::Duple (0,0));
685  }
686 
687  /* the shade coordinates *MUST* be in anti-clockwise order.
688  */
689 
690  if (current == In) {
691 
692  /* lower left */
693 
694  spts[0].x = canvas_border;
695  spts[0].y = effective_height() + canvas_border;
696 
697  /* lower right */
698 
699  spts[1].x = effective_width() + canvas_border;
700  spts[1].y = effective_height() + canvas_border;
701 
702  /* upper right */
703 
704  spts[2].x = effective_width() + canvas_border;
705  spts[2].y = canvas_border;
706 
707 
708  } else {
709 
710  /* upper left */
711 
712  spts[0].x = canvas_border;
713  spts[0].y = canvas_border;
714 
715  /* lower left */
716 
717  spts[1].x = canvas_border;
718  spts[1].y = effective_height() + canvas_border;
719 
720  /* lower right */
721 
722  spts[2].x = effective_width() + canvas_border;
723  spts[2].y = effective_height() + canvas_border;
724 
725  }
726 
727  size_t last_spt = (npoints + 3) - 1;
728 
729  for (size_t i = 0; i < npoints; ++i) {
730 
731  double y = vec[i];
732 
733  pts[i].x = canvas_border + i;
734  pts[i].y = y_coordinate (y);
735 
736  spts[last_spt - i].x = canvas_border + i;
737  spts[last_spt - i].y = pts[i].y;
738  }
739 
740  fade[current].line->set (pts);
741  fade[current].shading->set (pts);
742 
743  for (vector<ArdourCanvas::WaveView*>::iterator i = fade[current].waves.begin(); i != fade[current].waves.end(); ++i) {
744  (*i)->property_gain_src() = static_cast<Evoral::Curve*>(&fade[current].gain_curve.curve());
745  }
746 }
747 
748 void
750 {
751 
752  WhichFade wf = find(fade_in_presets->begin(), fade_in_presets->end(), preset) != fade_in_presets->end() ? In : Out;
753 
754  if (current != wf) {
755 
756  if (wf == In) {
757  select_in_button.clicked();
758  } else {
759  select_out_button.clicked();
760  }
761 
763  }
764 
765  for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
766  delete *i;
767  }
768 
769  fade[current].points.clear ();
770 
771  for (Preset::iterator i = preset->begin(); i != preset->end(); ++i) {
772  Point* p = make_point ();
773  p->move_to (x_coordinate ((*i).x), y_coordinate ((*i).y),
774  (*i).x, (*i).y);
775  fade[current].points.push_back (p);
776  }
777 
778  redraw ();
779 }
780 
781 void
783 {
784  the_editor().begin_reversible_command (_("Edit crossfade"));
785 
786  XMLNode& before = xfade->get_state ();
787 
788  _apply_to (xfade);
789 
792  new ARDOUR::CrossfadeBinder (_session->playlists, xfade->id ()),
793  &before, &xfade->get_state ()
794  )
795  );
796 
797  the_editor().commit_reversible_command ();
798 }
799 
800 void
802 {
803  ARDOUR::AutomationList& in (xf->fade_in());
804  ARDOUR::AutomationList& out (xf->fade_out());
805 
806  /* IN */
807 
808 
810  --the_end;
811 
812  double firstx = (*in.begin())->when;
813  double endx = (*the_end)->when;
814 
815  in.freeze ();
816  in.clear ();
817 
818  for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
819 
820  double when = firstx + ((*i)->x * (endx - firstx));
821  double value = (*i)->y;
822  in.add (when, value);
823  }
824 
825  /* OUT */
826 
827  the_end = out.end();
828  --the_end;
829 
830  firstx = (*out.begin())->when;
831  endx = (*the_end)->when;
832 
833  out.freeze ();
834  out.clear ();
835 
836  for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
837 
838  double when = firstx + ((*i)->x * (endx - firstx));
839  double value = (*i)->y;
840  out.add (when, value);
841  }
842 
843  in.thaw ();
844  out.thaw ();
845 }
846 
847 void
849 {
850  _apply_to (xfade);
851  xfade->set_active (true);
852  xfade->fade_in().curve().solve ();
853  xfade->fade_out().curve().solve ();
854 }
855 
856 void
858 {
859  for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
860  delete *i;
861  }
862 
863  fade[current].points.clear ();
864 
865  redraw ();
866 }
867 
868 void
870 {
871  set (xfade->fade_in(), In);
872  set (xfade->fade_out(), Out);
873 
875 }
876 
877 void
879 {
880  Preset* p;
881 
882  fade_in_presets = new Presets;
884 
885  /* FADE IN */
886 
887  p = new Preset ("Linear (-6dB)", "fadein-linear");
888  p->push_back (PresetPoint (0.000000, GAIN_COEFF_SMALL));
889  p->push_back (PresetPoint (0.166667, 0.166366));
890  p->push_back (PresetPoint (0.333333, 0.332853));
891  p->push_back (PresetPoint (0.500000, 0.499459));
892  p->push_back (PresetPoint (0.666667, 0.666186));
893  p->push_back (PresetPoint (0.833333, 0.833033));
894  p->push_back (PresetPoint (1.000000, GAIN_COEFF_UNITY));
895  fade_in_presets->push_back (p);
896 
897  p = new Preset ("S(1)-curve", "fadein-S1");
898  p->push_back (PresetPoint (0, GAIN_COEFF_SMALL));
899  p->push_back (PresetPoint (0.1, 0.01));
900  p->push_back (PresetPoint (0.2, 0.03));
901  p->push_back (PresetPoint (0.8, 0.97));
902  p->push_back (PresetPoint (0.9, 0.99));
903  p->push_back (PresetPoint (1, GAIN_COEFF_UNITY));
904  fade_in_presets->push_back (p);
905 
906  p = new Preset ("S(2)-curve", "fadein-S2");
907  p->push_back (PresetPoint (0.0, GAIN_COEFF_SMALL));
908  p->push_back (PresetPoint (0.055, 0.222));
909  p->push_back (PresetPoint (0.163, 0.35));
910  p->push_back (PresetPoint (0.837, 0.678));
911  p->push_back (PresetPoint (0.945, 0.783));
912  p->push_back (PresetPoint (1.0, GAIN_COEFF_UNITY));
913  fade_in_presets->push_back (p);
914 
915  p = new Preset ("Constant power (-3dB)", "fadein-constant-power");
916 
917  p->push_back (PresetPoint (0.000000, GAIN_COEFF_SMALL));
918  p->push_back (PresetPoint (0.166667, 0.282192));
919  p->push_back (PresetPoint (0.333333, 0.518174));
920  p->push_back (PresetPoint (0.500000, 0.707946));
921  p->push_back (PresetPoint (0.666667, 0.851507));
922  p->push_back (PresetPoint (0.833333, 0.948859));
923  p->push_back (PresetPoint (1.000000, GAIN_COEFF_UNITY));
924 
925  fade_in_presets->push_back (p);
926 
927  if (!Profile->get_sae()) {
928 
929  p = new Preset ("Short cut", "fadein-short-cut");
930  p->push_back (PresetPoint (0, GAIN_COEFF_SMALL));
931  p->push_back (PresetPoint (0.389401, 0.0333333));
932  p->push_back (PresetPoint (0.629032, 0.0861111));
933  p->push_back (PresetPoint (0.829493, 0.233333));
934  p->push_back (PresetPoint (0.9447, 0.483333));
935  p->push_back (PresetPoint (0.976959, 0.697222));
936  p->push_back (PresetPoint (1, GAIN_COEFF_UNITY));
937  fade_in_presets->push_back (p);
938 
939  p = new Preset ("Slow cut", "fadein-slow-cut");
940  p->push_back (PresetPoint (0, GAIN_COEFF_SMALL));
941  p->push_back (PresetPoint (0.304147, 0.0694444));
942  p->push_back (PresetPoint (0.529954, 0.152778));
943  p->push_back (PresetPoint (0.725806, 0.333333));
944  p->push_back (PresetPoint (0.847926, 0.558333));
945  p->push_back (PresetPoint (0.919355, 0.730556));
946  p->push_back (PresetPoint (1, GAIN_COEFF_UNITY));
947  fade_in_presets->push_back (p);
948 
949  p = new Preset ("Fast cut", "fadein-fast-cut");
950  p->push_back (PresetPoint (0, GAIN_COEFF_SMALL));
951  p->push_back (PresetPoint (0.0737327, 0.308333));
952  p->push_back (PresetPoint (0.246544, 0.658333));
953  p->push_back (PresetPoint (0.470046, 0.886111));
954  p->push_back (PresetPoint (0.652074, 0.972222));
955  p->push_back (PresetPoint (0.771889, 0.988889));
956  p->push_back (PresetPoint (1, GAIN_COEFF_UNITY));
957  fade_in_presets->push_back (p);
958 
959  p = new Preset ("Long cut", "fadein-long-cut");
960  p->push_back (PresetPoint (0, GAIN_COEFF_SMALL));
961  p->push_back (PresetPoint (0.0207373, 0.197222));
962  p->push_back (PresetPoint (0.0645161, 0.525));
963  p->push_back (PresetPoint (0.152074, 0.802778));
964  p->push_back (PresetPoint (0.276498, 0.919444));
965  p->push_back (PresetPoint (0.481567, 0.980556));
966  p->push_back (PresetPoint (0.767281, 1));
967  p->push_back (PresetPoint (1, GAIN_COEFF_UNITY));
968  fade_in_presets->push_back (p);
969  }
970 
971  /* FADE OUT */
972 
973  // p = new Preset ("regout.xpm");
974  p = new Preset ("Linear (-6dB cut)", "fadeout-linear");
975  p->push_back (PresetPoint (0.000000, GAIN_COEFF_UNITY));
976  p->push_back (PresetPoint (0.166667, 0.833033));
977  p->push_back (PresetPoint (0.333333, 0.666186));
978  p->push_back (PresetPoint (0.500000, 0.499459));
979  p->push_back (PresetPoint (0.666667, 0.332853));
980  p->push_back (PresetPoint (0.833333, 0.166366));
981  p->push_back (PresetPoint (1.000000, GAIN_COEFF_SMALL));
982  fade_out_presets->push_back (p);
983 
984  p = new Preset ("S(1)-Curve", "fadeout-S1");
985  p->push_back (PresetPoint (0, GAIN_COEFF_UNITY));
986  p->push_back (PresetPoint (0.1, 0.99));
987  p->push_back (PresetPoint (0.2, 0.97));
988  p->push_back (PresetPoint (0.8, 0.03));
989  p->push_back (PresetPoint (0.9, 0.01));
990  p->push_back (PresetPoint (1, GAIN_COEFF_SMALL));
991  fade_out_presets->push_back (p);
992 
993  p = new Preset ("S(2)-Curve", "fadeout-S2");
994  p->push_back (PresetPoint (0.0, GAIN_COEFF_UNITY));
995  p->push_back (PresetPoint (0.163, 0.678));
996  p->push_back (PresetPoint (0.055, 0.783));
997  p->push_back (PresetPoint (0.837, 0.35));
998  p->push_back (PresetPoint (0.945, 0.222));
999  p->push_back (PresetPoint (1.0, GAIN_COEFF_SMALL));
1000  fade_out_presets->push_back (p);
1001 
1002  // p = new Preset ("linout.xpm");
1003  p = new Preset ("Constant power (-3dB cut)", "fadeout-constant-power");
1004  p->push_back (PresetPoint (0.000000, GAIN_COEFF_UNITY));
1005  p->push_back (PresetPoint (0.166667, 0.948859));
1006  p->push_back (PresetPoint (0.333333, 0.851507));
1007  p->push_back (PresetPoint (0.500000, 0.707946));
1008  p->push_back (PresetPoint (0.666667, 0.518174));
1009  p->push_back (PresetPoint (0.833333, 0.282192));
1010  p->push_back (PresetPoint (1.000000, GAIN_COEFF_SMALL));
1011  fade_out_presets->push_back (p);
1012 
1013  if (!Profile->get_sae()) {
1014  // p = new Preset ("hiout.xpm");
1015  p = new Preset ("Short cut", "fadeout-short-cut");
1016  p->push_back (PresetPoint (0, GAIN_COEFF_UNITY));
1017  p->push_back (PresetPoint (0.305556, GAIN_COEFF_UNITY));
1018  p->push_back (PresetPoint (0.548611, 0.991736));
1019  p->push_back (PresetPoint (0.759259, 0.931129));
1020  p->push_back (PresetPoint (0.918981, 0.68595));
1021  p->push_back (PresetPoint (0.976852, 0.22865));
1022  p->push_back (PresetPoint (1, GAIN_COEFF_SMALL));
1023  fade_out_presets->push_back (p);
1024 
1025  p = new Preset ("Slow cut", "fadeout-slow-cut");
1026  p->push_back (PresetPoint (0, GAIN_COEFF_UNITY));
1027  p->push_back (PresetPoint (0.228111, 0.988889));
1028  p->push_back (PresetPoint (0.347926, 0.972222));
1029  p->push_back (PresetPoint (0.529954, 0.886111));
1030  p->push_back (PresetPoint (0.753456, 0.658333));
1031  p->push_back (PresetPoint (0.9262673, 0.308333));
1032  p->push_back (PresetPoint (1, GAIN_COEFF_SMALL));
1033  fade_out_presets->push_back (p);
1034 
1035  p = new Preset ("Fast cut", "fadeout-fast-cut");
1036  p->push_back (PresetPoint (0, GAIN_COEFF_UNITY));
1037  p->push_back (PresetPoint (0.080645, 0.730556));
1038  p->push_back (PresetPoint (0.277778, 0.289256));
1039  p->push_back (PresetPoint (0.470046, 0.152778));
1040  p->push_back (PresetPoint (0.695853, 0.0694444));
1041  p->push_back (PresetPoint (1, GAIN_COEFF_SMALL));
1042  fade_out_presets->push_back (p);
1043 
1044  // p = new Preset ("loout.xpm");
1045  p = new Preset ("Long cut", "fadeout-long-cut");
1046  p->push_back (PresetPoint (0, GAIN_COEFF_UNITY));
1047  p->push_back (PresetPoint (0.023041, 0.697222));
1048  p->push_back (PresetPoint (0.0553, 0.483333));
1049  p->push_back (PresetPoint (0.170507, 0.233333));
1050  p->push_back (PresetPoint (0.370968, 0.0861111));
1051  p->push_back (PresetPoint (0.610599, 0.0333333));
1052  p->push_back (PresetPoint (1, GAIN_COEFF_SMALL));
1053  fade_out_presets->push_back (p);
1054 
1055  }
1056 }
1057 
1058 void
1060 {
1061  current = wf;
1062 
1063  if (wf == In) {
1064 
1065  for (vector<ArdourCanvas::WaveView*>::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) {
1066  (*i)->set_outline_color (ARDOUR_UI::config()->get_SelectedCrossfadeEditorWave());
1067  (*i)->set_fill_color (ARDOUR_UI::config()->get_SelectedCrossfadeEditorWave());
1068  }
1069 
1070  for (vector<ArdourCanvas::WaveView*>::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) {
1071  (*i)->set_outline_color (ARDOUR_UI::config()->get_CrossfadeEditorWave());
1072  (*i)->set_fill_color (ARDOUR_UI::config()->get_CrossfadeEditorWave());
1073  }
1074 
1075  fade[In].line->set_outline_color (ARDOUR_UI::config()->get_SelectedCrossfadeEditorLine());
1076  fade[Out].line->set_outline_color (ARDOUR_UI::config()->get_CrossfadeEditorLine());
1077  fade[Out].shading->hide();
1078  fade[In].shading->show();
1079 
1080  for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
1081  (*i)->box->hide();
1082  }
1083 
1084  for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
1085  (*i)->box->show ();
1086  }
1087 
1088  } else {
1089 
1090  for (vector<ArdourCanvas::WaveView*>::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) {
1091  (*i)->set_outline_color (ARDOUR_UI::config()->get_CrossfadeEditorWave());
1092  (*i)->set_fill_color (ARDOUR_UI::config()->get_CrossfadeEditorWave());
1093  }
1094 
1095  for (vector<ArdourCanvas::WaveView*>::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) {
1096  (*i)->set_outline_color (ARDOUR_UI::config()->get_SelectedCrossfadeEditorWave());
1097  (*i)->set_fill_color (ARDOUR_UI::config()->get_SelectedCrossfadeEditorWave());
1098  }
1099 
1100  fade[Out].line->set_outline_color (ARDOUR_UI::config()->get_SelectedCrossfadeEditorLine());
1101  fade[In].line->set_outline_color (ARDOUR_UI::config()->get_CrossfadeEditorLine());
1102  fade[In].shading->hide();
1103  fade[Out].shading->show();
1104 
1105  for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
1106  (*i)->box->hide();
1107  }
1108 
1109  for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
1110  (*i)->box->show();
1111  }
1112 
1113  }
1114 }
1115 
1116 double
1117 CrossfadeEditor::x_coordinate (double& xfract) const
1118 {
1119  xfract = min (1.0, xfract);
1120  xfract = max (0.0, xfract);
1121 
1122  return canvas_border + (xfract * effective_width());
1123 }
1124 
1125 double
1126 CrossfadeEditor::y_coordinate (double& yfract) const
1127 {
1128  yfract = min (1.0, yfract);
1129  yfract = max (0.0, yfract);
1130 
1131  return (canvas->get_allocation().get_height() - (canvas_border)) - (yfract * effective_height());
1132 }
1133 
1134 void
1136 {
1137  gdouble ht;
1138  uint32_t nchans = region->n_channels();
1139  guint32 color;
1140  double spu;
1141 
1142  if (which == In) {
1143  color = ARDOUR_UI::config()->get_SelectedCrossfadeEditorWave();
1144  } else {
1145  color = ARDOUR_UI::config()->get_CrossfadeEditorWave();
1146  }
1147 
1148  ht = canvas->get_allocation().get_height() / (double) nchans;
1149  spu = xfade->length() / (double) effective_width();
1150 
1151  delete _peaks_ready_connection;
1153 
1154  for (uint32_t n = 0; n < nchans; ++n) {
1155 
1156  gdouble yoff = n * ht;
1157 
1158  if (region->audio_source(n)->peaks_ready (boost::bind (&CrossfadeEditor::peaks_ready, this, boost::weak_ptr<AudioRegion>(region), which), &_peaks_ready_connection, gui_context())) {
1159  ArdourCanvas::WaveView* waveview = new ArdourCanvas::WaveView (canvas->root(), region);
1160 
1161  waveview->set_channel (n);
1162  waveview->property_gain_function() = (void*) curve_get_vector_from_c;
1163  waveview->property_gain_src() = static_cast<Evoral::Curve*>(&fade[which].gain_curve.curve());
1164  waveview->set_x_position (canvas_border);
1165  waveview->set_y_position (yoff);
1166  waveview->set_height (ht);
1167  waveview->set_samples_per_pixel (spu);
1168  waveview->property_amplitude_above_axis() = 2.0;
1169  waveview->set_outline_color (color);
1170  waveview->set_fill_color (color);
1171 
1172  if (which != In) {
1173  waveview->set_region_start (region->start() + region->length() - xfade->length());
1174  }
1175 
1176  waveview->lower_to_bottom();
1177  fade[which].waves.push_back (waveview);
1178  }
1179  }
1180 
1181  toplevel->lower_to_bottom();
1182 }
1183 
1184 void
1186 {
1187  boost::shared_ptr<AudioRegion> r (wr.lock());
1188 
1189  if (!r) {
1190  return;
1191  }
1192 
1193  /* this should never be called, because the peak files for an xfade
1194  will be ready by the time we want them. but our API forces us
1195  to provide this, so ..
1196  */
1197  delete _peaks_ready_connection;
1199 
1200  make_waves (r, which);
1201 }
1202 
1203 void
1205 {
1206  AudioPlaylist& pl (_session->the_auditioner()->prepare_playlist());
1207  framecnt_t preroll;
1208  framecnt_t postroll;
1209  framecnt_t left_start_offset;
1210  framecnt_t right_length;
1211  framecnt_t left_length;
1212 
1213  if (which != Right && preroll_button.get_active()) {
1214  preroll = _session->frame_rate() * 2; //2 second hardcoded preroll for now
1215  } else {
1216  preroll = 0;
1217  }
1218 
1219  if (which != Left && postroll_button.get_active()) {
1220  postroll = _session->frame_rate() * 2; //2 second hardcoded postroll for now
1221  } else {
1222  postroll = 0;
1223  }
1224 
1225  // Is there enough data for the whole preroll?
1226  left_length = xfade->length();
1227  if ((left_start_offset = xfade->out()->length() - xfade->length()) > preroll) {
1228  left_start_offset -= preroll;
1229  } else {
1230  preroll = left_start_offset;
1231  left_start_offset = 0;
1232  }
1233  left_length += preroll;
1234 
1235  // Is there enough data for the whole postroll?
1236  right_length = xfade->length();
1237  if ((xfade->in()->length() - right_length) > postroll) {
1238  right_length += postroll;
1239  } else {
1240  right_length = xfade->in()->length();
1241  }
1242 
1243  PropertyList left_plist;
1244  PropertyList right_plist;
1245 
1246 
1247  left_plist.add (ARDOUR::Properties::start, left_start_offset);
1248  left_plist.add (ARDOUR::Properties::length, left_length);
1249  left_plist.add (ARDOUR::Properties::name, string ("xfade out"));
1250  left_plist.add (ARDOUR::Properties::layer, 0);
1251  left_plist.add (ARDOUR::Properties::fade_in_active, true);
1252 
1253  right_plist.add (ARDOUR::Properties::start, 0);
1254  right_plist.add (ARDOUR::Properties::length, right_length);
1255  right_plist.add (ARDOUR::Properties::name, string("xfade in"));
1256  right_plist.add (ARDOUR::Properties::layer, 0);
1257  right_plist.add (ARDOUR::Properties::fade_out_active, true);
1258 
1259  if (which == Left) {
1260  right_plist.add (ARDOUR::Properties::scale_amplitude, 0.0f);
1261  } else if (which == Right) {
1262  left_plist.add (ARDOUR::Properties::scale_amplitude, 0.0f);
1263  }
1264 
1265  boost::shared_ptr<AudioRegion> left (boost::dynamic_pointer_cast<AudioRegion>
1266  (RegionFactory::create (xfade->out(), left_plist, false)));
1267  boost::shared_ptr<AudioRegion> right (boost::dynamic_pointer_cast<AudioRegion>
1268  (RegionFactory::create (xfade->in(), right_plist, false)));
1269 
1270  // apply a 20ms declicking fade at the start and end of auditioning
1271  // XXX this should really be a property
1272 
1273  left->set_fade_in_length (_session->frame_rate() / 50);
1274  right->set_fade_out_length (_session->frame_rate() / 50);
1275 
1276  pl.add_region (left, 0);
1277  pl.add_region (right, 1 + preroll);
1278 
1279  /* there is only one ... */
1280  pl.foreach_crossfade (sigc::mem_fun (*this, &CrossfadeEditor::setup));
1281 
1283 }
1284 
1285 void
1287 {
1288  audition (Both);
1289 }
1290 
1291 void
1293 {
1294  PropertyList plist;
1295 
1296  plist.add (ARDOUR::Properties::start, xfade->out()->length() - xfade->length());
1297  plist.add (ARDOUR::Properties::length, xfade->length());
1298  plist.add (ARDOUR::Properties::name, string("xfade left"));
1299  plist.add (ARDOUR::Properties::layer, 0);
1300 
1301  boost::shared_ptr<AudioRegion> left (boost::dynamic_pointer_cast<AudioRegion>
1302  (RegionFactory::create (xfade->out(), plist, false)));
1303 
1304  _session->audition_region (left);
1305 }
1306 
1307 void
1309 {
1310  audition (Left);
1311 }
1312 
1313 void
1315 {
1316  PropertyList plist;
1317 
1318  plist.add (ARDOUR::Properties::start, 0);
1319  plist.add (ARDOUR::Properties::length, xfade->length());
1320  plist.add (ARDOUR::Properties::name, string ("xfade right"));
1321  plist.add (ARDOUR::Properties::layer, 0);
1322 
1323  boost::shared_ptr<AudioRegion> right (boost::dynamic_pointer_cast<AudioRegion>
1324  (RegionFactory::create (xfade->in(), plist, false)));
1325 
1326  _session->audition_region (right);
1327 }
1328 
1329 void
1331 {
1332  audition (Right);
1333 }
1334 
1335 void
1337 {
1339 }
1340 
1341 void
1343 {
1344  bool x;
1345 
1346  if ((x = audition_both_button.get_active ()) != _session->is_auditioning()) {
1347 
1348  if (x) {
1349  audition_both ();
1350  } else {
1351  cancel_audition ();
1352  }
1353  }
1354 }
1355 
1356 void
1358 {
1359  bool x;
1360 
1361  if ((x = audition_right_button.get_active ()) != _session->is_auditioning()) {
1362 
1363  if (x) {
1364  audition_right ();
1365  } else {
1366  cancel_audition ();
1367  }
1368  }
1369 }
1370 
1371 void
1373 {
1374  bool x;
1375 
1376  if ((x = audition_right_dry_button.get_active ()) != _session->is_auditioning()) {
1377 
1378  if (x) {
1379  audition_right_dry ();
1380  } else {
1381  cancel_audition ();
1382  }
1383  }
1384 }
1385 
1386 void
1388 {
1389  bool x;
1390 
1391  if ((x = audition_left_button.get_active ()) != _session->is_auditioning()) {
1392 
1393  if (x) {
1394  audition_left ();
1395  } else {
1396  cancel_audition ();
1397  }
1398  }
1399 }
1400 
1401 void
1403 {
1404  bool x;
1405 
1406  if ((x = audition_left_dry_button.get_active ()) != _session->is_auditioning()) {
1407 
1408  if (x) {
1409  audition_left_dry ();
1410  } else {
1411  cancel_audition ();
1412  }
1413  }
1414 }
1415 
1416 bool
1418 {
1419  return true;
1420 }
1421 
1422 bool
1424 {
1425  switch (ev->keyval) {
1426  case GDK_Right:
1427  if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1428  audition_right_dry_button.set_active (!audition_right_dry_button.get_active());
1429  } else {
1430  audition_right_button.set_active (!audition_right_button.get_active());
1431  }
1432  break;
1433 
1434  case GDK_Left:
1435  if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1436  audition_left_dry_button.set_active (!audition_left_dry_button.get_active());
1437  } else {
1438  audition_left_button.set_active (!audition_left_button.get_active());
1439  }
1440  break;
1441 
1442  case GDK_space:
1443  if (_session->is_auditioning()) {
1444  cancel_audition ();
1445  } else {
1446  audition_both_button.set_active (!audition_both_button.get_active());
1447  }
1448  break;
1449 
1450  default:
1451  break;
1452  }
1453 
1454  return true;
1455 }
Gtk::ToggleButton audition_left_button
LIBEVORAL_API void curve_get_vector_from_c(void *arg, double, double, float *, int32_t)
Definition: Curve.cpp:423
LIBARDOUR_API PBD::PropertyDescriptor< bool > fade_out_active
Definition: audioregion.cc:65
bool on_key_release_event(GdkEventKey *)
void _apply_to(boost::shared_ptr< ARDOUR::Crossfade > xf)
bool get_sae() const
Definition: profile.h:48
std::list< Point * > points
double y_coordinate(double &yfract) const
double effective_height() const
Gtk::Button clear_button
double effective_width() const
void xfade_changed(const PBD::PropertyChange &)
void move_to(double x, double y, double xfract, double yfract)
LIBARDOUR_API PBD::PropertyDescriptor< layer_t > layer
Definition: region.cc:67
static Presets * fade_in_presets
Gtk::ToggleButton audition_right_dry_button
ArdourCanvas::Rectangle * box
void audition_left_dry_toggled()
Definition: ardour_ui.h:130
static ARDOUR_UI * instance()
Definition: ardour_ui.h:187
LIBARDOUR_API PBD::PropertyDescriptor< std::string > name
CrossfadeEditor(ARDOUR::Session *, boost::shared_ptr< ARDOUR::Crossfade >, double miny, double maxy)
std::list< Preset * > Presets
bool curve_event(GdkEvent *event)
void add_command(Command *const cmd)
Definition: session.h:787
Gtk::Button * cancel_button
void audition_playlist()
Definition: session.cc:4135
void audition_left_toggled()
tuple f
Definition: signals.py:35
Gtk::RadioButton select_in_button
bool is_auditioning() const
Definition: session.cc:4184
Gtk::ToggleButton audition_left_dry_button
Definition: Beats.hpp:239
Gtk::ToggleButton audition_both_button
Gtk::VBox vpacker2
Point * make_point()
static const double canvas_border
LIBARDOUR_API PBD::PropertyDescriptor< framepos_t > start
Definition: region.cc:63
framecnt_t frame_rate() const
Definition: session.h:365
#define ENSURE_GUI_THREAD(obj, method,...)
Definition: gui_thread.h:34
Gtk::Button revert_button
#define invalidator(x)
Definition: gui_thread.h:40
void get_vector(double x0, double x1, float *arg, int32_t veclen)
Definition: Curve.cpp:185
void cancel_audition()
Definition: session.cc:4160
ARDOUR::AutomationList gain_curve
boost::shared_ptr< Auditioner > the_auditioner()
Definition: session.h:673
std::vector< ArdourCanvas::WaveView * > waves
double x_coordinate(double &xfract) const
bool on_key_press_event(GdkEventKey *)
bool canvas_event(GdkEvent *event)
#define _(Text)
Definition: i18n.h:11
ArdourCanvas::GtkCanvas * canvas
void apply_preset(Preset *)
Gtk::ToggleButton preroll_button
LIBGTKMM2EXT_API uint64_t Keyboard
Definition: debug.cc:23
Gtk::Table fade_out_table
#define X_(Text)
Definition: i18n.h:13
ArdourCanvas::Rectangle * toplevel
Gtk::RadioButton select_out_button
int64_t framecnt_t
Definition: types.h:76
void peaks_ready(boost::weak_ptr< ARDOUR::AudioRegion > r, WhichFade)
Gtk::HBox curve_button_box
#define GAIN_COEFF_SMALL
Definition: dB.h:27
void set(const ARDOUR::AutomationList &alist, WhichFade)
std::vector< Gtk::Button * > fade_in_buttons
PBD::ScopedConnection state_connection
ArdourCanvas::Polygon * shading
Definition: amp.h:29
void add_control_point(double x, double y)
boost::shared_ptr< AudioSource > audio_source(uint32_t n=0) const
void set_fade_in_length(framecnt_t)
PBD::Signal1< void, bool > AuditionActive
Definition: session.h:679
#define gui_context()
Definition: gui_thread.h:36
void swap(shared_ptr< T > &a, shared_ptr< T > &b)
Definition: shared_ptr.hpp:381
void curve_select_clicked(WhichFade)
Gtk::HBox roll_box
PBD::ScopedConnectionList _session_connections
void make_waves(boost::shared_ptr< ARDOUR::AudioRegion >, WhichFade)
LIBARDOUR_API RuntimeProfile * Profile
Definition: globals.cc:120
void set_tip(Gtk::Widget &w, const gchar *tip)
LIBGTKMM2EXT_API Glib::RefPtr< Gtk::UIManager > ui_manager
Definition: actions.cc:53
void audition(Audition)
PBD::ScopedConnection * _peaks_ready_connection
void audition_region(boost::shared_ptr< Region >)
Definition: session.cc:4152
Gtk::HBox audition_box
uint32_t n_channels() const
Definition: region.h:259
Definition: xml++.h:95
static const int32_t size
ARDOUR::AutomationList normative_curve
static UIConfiguration * config()
Definition: ardour_ui.h:188
void audition_state_changed(bool)
void setup(boost::shared_ptr< ARDOUR::Crossfade >)
boost::shared_ptr< ARDOUR::Crossfade > xfade
Definition: debug.h:30
void audition_right_dry_toggled()
EventList::const_iterator const_iterator
Definition: ControlList.hpp:84
boost::shared_ptr< SessionPlaylists > playlists
Definition: session.h:907
Gtk::Table fade_in_table
void audition_right_toggled()
framecnt_t length() const
Definition: region.h:114
virtual void set_session(ARDOUR::Session *)
framepos_t start() const
Definition: region.h:113
virtual void add(double when, double value, bool with_guards=true, bool with_default=true)
#define GAIN_COEFF_UNITY
Definition: dB.h:28
Gtk::ToggleButton postroll_button
Gtk::ToggleButton audition_right_button
Glib::RefPtr< Gdk::Pixbuf > get_icon(const char *cname)
Definition: utils.cc:674
ArdourCanvas::PolyLine * curve
std::vector< Gtk::Button * > fade_out_buttons
LIBARDOUR_API PBD::PropertyDescriptor< float > scale_amplitude
Definition: audioregion.cc:66
static Presets * fade_out_presets
bool add(PropertyBase *prop)
ArdourCanvas::PolyLine * line
ARDOUR::Session * _session
void canvas_allocation(Gtk::Allocation &)
LIBARDOUR_API PBD::PropertyDescriptor< bool > fade_in_active
Definition: audioregion.cc:64
Gtk::Button * ok_button
bool empty() const
LIBARDOUR_API PBD::PropertyDescriptor< framecnt_t > length
Definition: region.cc:64
bool point_event(GdkEvent *event, Point *)
LIBARDOUR_API PBD::PropertyDescriptor< bool > color
Definition: route_group.cc:50