Tidy a couple of minor things up.
[ardour.git] / gtk2_ardour / crossfade_edit.cc
index 4f0bbb702b22d4028fa42f65dedc513b476d7287..da833b8ea452f6eb40d87705c91f4a03f7b8fb3e 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <libgnomecanvasmm/line.h>
 
+#include "pbd/memento_command.h"
 #include "ardour/automation_list.h"
 #include "evoral/Curve.hpp"
 #include "ardour/crossfade.h"
@@ -36,6 +37,7 @@
 #include "ardour/audiosource.h"
 #include "ardour/region_factory.h"
 #include "ardour/profile.h"
+#include "ardour/crossfade_binder.h"
 
 #include <gtkmm2ext/gtk_ui.h>
 
@@ -54,7 +56,6 @@ using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
 using namespace Gtk;
-using namespace sigc;
 using namespace Editing;
 
 using Gtkmm2ext::Keyboard;
@@ -73,10 +74,9 @@ CrossfadeEditor::Half::Half ()
 {
 }
 
-CrossfadeEditor::CrossfadeEditor (Session& s, boost::shared_ptr<Crossfade> xf, double my, double mxy)
-       : ArdourDialog (_("ardour: x-fade edit")),
+CrossfadeEditor::CrossfadeEditor (Session* s, boost::shared_ptr<Crossfade> xf, double my, double mxy)
+       : ArdourDialog (_("Edit Crossfade")),
          xfade (xf),
-         session (s),
          clear_button (_("Clear")),
          revert_button (_("Reset")),
          audition_both_button (_("Fade")),
@@ -95,9 +95,14 @@ CrossfadeEditor::CrossfadeEditor (Session& s, boost::shared_ptr<Crossfade> xf, d
          fade_out_table (3, 3),
 
          select_in_button (_("Fade In")),
-         select_out_button (_("Fade Out"))
+         select_out_button (_("Fade Out")),
+
+         _peaks_ready_connection (0)
+
 {
-       set_wmclass (X_("ardour_automationedit"), "Ardour");
+       set_session (s);
+
+       set_wmclass (X_("ardour_automationedit"), PROGRAM_NAME);
        set_name ("CrossfadeEditWindow");
        set_position (Gtk::WIN_POS_MOUSE);
 
@@ -291,9 +296,9 @@ CrossfadeEditor::CrossfadeEditor (Session& s, boost::shared_ptr<Crossfade> xf, d
 
        curve_select_clicked (In);
 
-       xfade->StateChanged.connect (sigc::mem_fun(*this, &CrossfadeEditor::xfade_changed));
+       xfade->PropertyChanged.connect (state_connection, invalidator (*this), ui_bind (&CrossfadeEditor::xfade_changed, this, _1), gui_context());
 
-       session.AuditionActive.connect (sigc::mem_fun(*this, &CrossfadeEditor::audition_state_changed));
+       _session->AuditionActive.connect (_session_connections, invalidator (*this), ui_bind (&CrossfadeEditor::audition_state_changed, this, _1), gui_context());
        show_all_children();
 }
 
@@ -308,6 +313,8 @@ CrossfadeEditor::~CrossfadeEditor()
        for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
                delete *i;
        }
+
+       delete _peaks_ready_connection;
 }
 
 void
@@ -413,15 +420,16 @@ CrossfadeEditor::point_event (GdkEvent* event, Point* point)
                if (point_grabbed) {
                        double new_x, new_y;
 
-                       /* can't drag first or last points horizontally */
+                       /* can't drag first or last points horizontally or vertically */
 
                        if (point == fade[current].points.front() || point == fade[current].points.back()) {
                                new_x = point->x;
+                               new_y = point->y;
                        } else {
                                new_x = (event->motion.x - canvas_border)/effective_width();
+                               new_y = 1.0 - ((event->motion.y - canvas_border)/effective_height());
                        }
 
-                       new_y = 1.0 - ((event->motion.y - canvas_border)/effective_height());
                        point->move_to (x_coordinate (new_x), y_coordinate (new_y),
                                        new_x, new_y);
                        redraw ();
@@ -497,6 +505,18 @@ CrossfadeEditor::add_control_point (double x, double y)
 void
 CrossfadeEditor::Point::move_to (double nx, double ny, double xfract, double yfract)
 {
+       if ( xfract < 0.0 ) {
+               xfract = 0.0;
+       } else if ( xfract > 1.0 ) {
+               xfract = 1.0;
+       }
+
+       if ( yfract < 0.0 ) {
+               yfract = 0.0;
+       } else if ( yfract > 1.0 ) {
+               yfract = 1.0;
+       }
+
        const double half_size = rint(size/2.0);
        double x1 = nx - half_size;
        double x2 = nx + half_size;
@@ -624,7 +644,7 @@ CrossfadeEditor::canvas_allocation (Gtk::Allocation& /*alloc*/)
 
 
 void
-CrossfadeEditor::xfade_changed (Change)
+CrossfadeEditor::xfade_changed (const PropertyChange&)
 {
        set (xfade->fade_in(), In);
        set (xfade->fade_out(), Out);
@@ -637,7 +657,7 @@ CrossfadeEditor::redraw ()
                return;
        }
 
-       nframes_t len = xfade->length ();
+       framecnt_t len = xfade->length ();
 
        fade[current].normative_curve.clear ();
        fade[current].gain_curve.clear ();
@@ -766,7 +786,20 @@ CrossfadeEditor::apply_preset (Preset *preset)
 void
 CrossfadeEditor::apply ()
 {
+       _session->begin_reversible_command (_("Edit crossfade"));
+
+       XMLNode& before = xfade->get_state ();
+
        _apply_to (xfade);
+
+       _session->add_command (
+               new MementoCommand<Crossfade> (
+                       new ARDOUR::CrossfadeBinder (_session->playlists, xfade->id ()),
+                       &before, &xfade->get_state ()
+                       )
+               );
+
+       _session->commit_reversible_command ();
 }
 
 void
@@ -783,8 +816,6 @@ CrossfadeEditor::_apply_to (boost::shared_ptr<Crossfade> xf)
 
        double firstx = (*in.begin())->when;
        double endx = (*the_end)->when;
-       double miny = in.get_min_y ();
-       double maxy = in.get_max_y ();
 
        in.freeze ();
        in.clear ();
@@ -792,7 +823,7 @@ CrossfadeEditor::_apply_to (boost::shared_ptr<Crossfade> xf)
        for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
 
                double when = firstx + ((*i)->x * (endx - firstx));
-               double value = (*i)->y; // miny + ((*i)->y * (maxy - miny));
+               double value = (*i)->y;
                in.add (when, value);
        }
 
@@ -803,8 +834,6 @@ CrossfadeEditor::_apply_to (boost::shared_ptr<Crossfade> xf)
 
        firstx = (*out.begin())->when;
        endx = (*the_end)->when;
-       miny = out.get_min_y ();
-       maxy = out.get_max_y ();
 
        out.freeze ();
        out.clear ();
@@ -812,7 +841,7 @@ CrossfadeEditor::_apply_to (boost::shared_ptr<Crossfade> xf)
        for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
 
                double when = firstx + ((*i)->x * (endx - firstx));
-               double value = (*i)->y; // miny + ((*i)->y * (maxy - miny));
+               double value = (*i)->y;
                out.add (when, value);
        }
 
@@ -847,7 +876,7 @@ CrossfadeEditor::reset ()
        set (xfade->fade_in(),  In);
        set (xfade->fade_out(), Out);
 
-        curve_select_clicked (current);
+       curve_select_clicked (current);
 }
 
 void
@@ -1126,11 +1155,14 @@ CrossfadeEditor::make_waves (boost::shared_ptr<AudioRegion> region, WhichFade wh
        ht = canvas->get_allocation().get_height() / (double) nchans;
        spu = xfade->length() / (double) effective_width();
 
+       delete _peaks_ready_connection;
+       _peaks_ready_connection = 0;
+
        for (uint32_t n = 0; n < nchans; ++n) {
 
                gdouble yoff = n * ht;
 
-               if (region->audio_source(n)->peaks_ready (sigc::bind (sigc::mem_fun(*this, &CrossfadeEditor::peaks_ready), region, which), peaks_ready_connection)) {
+               if (region->audio_source(n)->peaks_ready (boost::bind (&CrossfadeEditor::peaks_ready, this, boost::weak_ptr<AudioRegion>(region), which), &_peaks_ready_connection, gui_context())) {
                        WaveView* waveview = new WaveView (*(canvas->root()));
 
                        waveview->property_data_src() = region.get();
@@ -1164,34 +1196,42 @@ CrossfadeEditor::make_waves (boost::shared_ptr<AudioRegion> region, WhichFade wh
 }
 
 void
-CrossfadeEditor::peaks_ready (boost::shared_ptr<AudioRegion> r, WhichFade which)
+CrossfadeEditor::peaks_ready (boost::weak_ptr<AudioRegion> wr, WhichFade which)
 {
+       boost::shared_ptr<AudioRegion> r (wr.lock());
+
+       if (!r) {
+               return;
+       }
+
        /* this should never be called, because the peak files for an xfade
           will be ready by the time we want them. but our API forces us
           to provide this, so ..
        */
-       peaks_ready_connection.disconnect ();
+       delete _peaks_ready_connection;
+       _peaks_ready_connection = 0;
+
        make_waves (r, which);
 }
 
 void
 CrossfadeEditor::audition (Audition which)
 {
-       AudioPlaylist& pl (session.the_auditioner()->prepare_playlist());
-       nframes_t preroll;
-       nframes_t postroll;
-       nframes_t left_start_offset;
-       nframes_t right_length;
-       nframes_t left_length;
+       AudioPlaylist& pl (_session->the_auditioner()->prepare_playlist());
+       framecnt_t preroll;
+       framecnt_t postroll;
+       framecnt_t left_start_offset;
+       framecnt_t right_length;
+       framecnt_t left_length;
 
        if (which != Right && preroll_button.get_active()) {
-               preroll = session.frame_rate() * 2;  //2 second hardcoded preroll for now
+               preroll = _session->frame_rate() * 2;  //2 second hardcoded preroll for now
        } else {
                preroll = 0;
        }
 
        if (which != Left && postroll_button.get_active()) {
-               postroll = session.frame_rate() * 2;  //2 second hardcoded postroll for now
+               postroll = _session->frame_rate() * 2;  //2 second hardcoded postroll for now
        } else {
                postroll = 0;
        }
@@ -1214,30 +1254,46 @@ CrossfadeEditor::audition (Audition which)
                right_length = xfade->in()->length();
        }
 
-       boost::shared_ptr<AudioRegion> left (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade->out(), left_start_offset, left_length, "xfade out",
-                                                                                                             0, Region::DefaultFlags, false)));
-       boost::shared_ptr<AudioRegion> right (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade->in(), 0, right_length, "xfade in",
-                                                                                                              0, Region::DefaultFlags, false)));
+       PropertyList left_plist;
+       PropertyList right_plist;
 
-       //apply a 20ms declicking fade at the start and end of auditioning
-       left->set_fade_in_active(true);
-       left->set_fade_in_length(session.frame_rate() / 50);
-       right->set_fade_out_active(true);
-       right->set_fade_out_length(session.frame_rate() / 50);
 
-       pl.add_region (left, 0);
-       pl.add_region (right, 1 + preroll);
+       left_plist.add (ARDOUR::Properties::start, left_start_offset);
+       left_plist.add (ARDOUR::Properties::length, left_length);
+       left_plist.add (ARDOUR::Properties::name, string ("xfade out"));
+       left_plist.add (ARDOUR::Properties::layer, 0);
+       left_plist.add (ARDOUR::Properties::fade_in_active, true);
+
+       right_plist.add (ARDOUR::Properties::start, 0);
+       right_plist.add (ARDOUR::Properties::length, right_length);
+       right_plist.add (ARDOUR::Properties::name, string("xfade in"));
+       right_plist.add (ARDOUR::Properties::layer, 0);
+       right_plist.add (ARDOUR::Properties::fade_out_active, true);
 
        if (which == Left) {
-               right->set_scale_amplitude (0.0);
+               right_plist.add (ARDOUR::Properties::scale_amplitude, 0.0f);
        } else if (which == Right) {
-               left->set_scale_amplitude (0.0);
+               left_plist.add (ARDOUR::Properties::scale_amplitude, 0.0f);
        }
 
+       boost::shared_ptr<AudioRegion> left (boost::dynamic_pointer_cast<AudioRegion>
+                                                    (RegionFactory::create (xfade->out(), left_plist, false)));
+       boost::shared_ptr<AudioRegion> right (boost::dynamic_pointer_cast<AudioRegion>
+                                             (RegionFactory::create (xfade->in(), right_plist, false)));
+
+       // apply a 20ms declicking fade at the start and end of auditioning
+       // XXX this should really be a property
+
+       left->set_fade_in_length (_session->frame_rate() / 50);
+       right->set_fade_out_length (_session->frame_rate() / 50);
+
+       pl.add_region (left, 0);
+       pl.add_region (right, 1 + preroll);
+
        /* there is only one ... */
        pl.foreach_crossfade (sigc::mem_fun (*this, &CrossfadeEditor::setup));
 
-       session.audition_playlist ();
+       _session->audition_playlist ();
 }
 
 void
@@ -1249,10 +1305,17 @@ CrossfadeEditor::audition_both ()
 void
 CrossfadeEditor::audition_left_dry ()
 {
-       boost::shared_ptr<AudioRegion> left (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade->out(), xfade->out()->length() - xfade->length(), xfade->length(), "xfade left",
-                                                                                                             0, Region::DefaultFlags, false)));
+       PropertyList plist;
+
+       plist.add (ARDOUR::Properties::start, xfade->out()->length() - xfade->length());
+       plist.add (ARDOUR::Properties::length, xfade->length());
+       plist.add (ARDOUR::Properties::name, string("xfade left"));
+       plist.add (ARDOUR::Properties::layer, 0);
 
-       session.audition_region (left);
+       boost::shared_ptr<AudioRegion> left (boost::dynamic_pointer_cast<AudioRegion>
+                                            (RegionFactory::create (xfade->out(), plist, false)));
+
+       _session->audition_region (left);
 }
 
 void
@@ -1264,9 +1327,17 @@ CrossfadeEditor::audition_left ()
 void
 CrossfadeEditor::audition_right_dry ()
 {
-       boost::shared_ptr<AudioRegion> right (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (xfade->in(), 0, xfade->length(), "xfade in",
-                                                                                                              0, Region::DefaultFlags, false)));
-       session.audition_region (right);
+       PropertyList plist;
+
+       plist.add (ARDOUR::Properties::start, 0);
+       plist.add (ARDOUR::Properties::length, xfade->length());
+       plist.add (ARDOUR::Properties::name, string ("xfade right"));
+       plist.add (ARDOUR::Properties::layer, 0);
+
+       boost::shared_ptr<AudioRegion> right (boost::dynamic_pointer_cast<AudioRegion>
+                                             (RegionFactory::create (xfade->in(), plist, false)));
+
+       _session->audition_region (right);
 }
 
 void
@@ -1278,7 +1349,7 @@ CrossfadeEditor::audition_right ()
 void
 CrossfadeEditor::cancel_audition ()
 {
-       session.cancel_audition ();
+       _session->cancel_audition ();
 }
 
 void
@@ -1286,7 +1357,7 @@ CrossfadeEditor::audition_toggled ()
 {
        bool x;
 
-       if ((x = audition_both_button.get_active ()) != session.is_auditioning()) {
+       if ((x = audition_both_button.get_active ()) != _session->is_auditioning()) {
 
                if (x) {
                        audition_both ();
@@ -1301,7 +1372,7 @@ CrossfadeEditor::audition_right_toggled ()
 {
        bool x;
 
-       if ((x = audition_right_button.get_active ()) != session.is_auditioning()) {
+       if ((x = audition_right_button.get_active ()) != _session->is_auditioning()) {
 
                if (x) {
                        audition_right ();
@@ -1316,7 +1387,7 @@ CrossfadeEditor::audition_right_dry_toggled ()
 {
        bool x;
 
-       if ((x = audition_right_dry_button.get_active ()) != session.is_auditioning()) {
+       if ((x = audition_right_dry_button.get_active ()) != _session->is_auditioning()) {
 
                if (x) {
                        audition_right_dry ();
@@ -1331,7 +1402,7 @@ CrossfadeEditor::audition_left_toggled ()
 {
        bool x;
 
-       if ((x = audition_left_button.get_active ()) != session.is_auditioning()) {
+       if ((x = audition_left_button.get_active ()) != _session->is_auditioning()) {
 
                if (x) {
                        audition_left ();
@@ -1346,7 +1417,7 @@ CrossfadeEditor::audition_left_dry_toggled ()
 {
        bool x;
 
-       if ((x = audition_left_dry_button.get_active ()) != session.is_auditioning()) {
+       if ((x = audition_left_dry_button.get_active ()) != _session->is_auditioning()) {
 
                if (x) {
                        audition_left_dry ();
@@ -1383,7 +1454,7 @@ CrossfadeEditor::on_key_release_event (GdkEventKey* ev)
                break;
 
        case GDK_space:
-               if (session.is_auditioning()) {
+               if (_session->is_auditioning()) {
                        cancel_audition ();
                } else {
                        audition_both_button.set_active (!audition_both_button.get_active());