promote Playlist::RegionList to ARDOUR::RegionList; fix timefx on multiple regions...
authorPaul Davis <paul@linuxaudiosystems.com>
Fri, 27 Jan 2012 16:29:01 +0000 (16:29 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Fri, 27 Jan 2012 16:29:01 +0000 (16:29 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@11362 d708f5d6-7413-0410-9779-e7cbd77b26cf

12 files changed:
gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/editor_canvas_events.cc
gtk2_ardour/editor_drag.cc
gtk2_ardour/editor_timefx.cc
gtk2_ardour/route_time_axis.cc
gtk2_ardour/time_fx_dialog.h
libs/ardour/ardour/midi_stretch.h
libs/ardour/ardour/playlist.h
libs/ardour/ardour/types.h
libs/ardour/midi_stretch.cc
libs/ardour/playlist.cc

index f94269c564f27aeacb9078081930ec4c2632cbd3..01777f54a300adbddb33445bffef2ca397303fb6 100644 (file)
@@ -4430,10 +4430,10 @@ Editor::get_regions_at (RegionSelection& rs, framepos_t where, const TrackViewLi
 
                        if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
 
-                               boost::shared_ptr<Playlist::RegionList> regions = pl->regions_at (
+                               boost::shared_ptr<RegionList> regions = pl->regions_at (
                                                (framepos_t) floor ( (double) where * tr->speed()));
 
-                               for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
+                               for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
                                        RegionView* rv = rtv->view()->find_view (*i);
                                        if (rv) {
                                                rs.add (rv);
@@ -4463,10 +4463,10 @@ Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackVie
 
                        if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
 
-                               boost::shared_ptr<Playlist::RegionList> regions = pl->regions_touched (
+                               boost::shared_ptr<RegionList> regions = pl->regions_touched (
                                        (framepos_t) floor ( (double)where * tr->speed()), max_framepos);
 
-                               for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
+                               for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
 
                                        RegionView* rv = rtv->view()->find_view (*i);
 
index e12e20f610de50d4afd3d9fd6ea84317cec69653..2bf8fa8052650067a393e5a133ddf69c2018ca22 100644 (file)
@@ -1834,7 +1834,6 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
        int time_stretch (RegionSelection&, float fraction);
        int pitch_shift (RegionSelection&, float cents);
        void pitch_shift_region ();
-       int time_fx (RegionSelection&, float val, bool pitching);
 
        void transpose_region ();
 
@@ -2081,6 +2080,8 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
        void follow_mixer_selection ();
        bool _following_mixer_selection;
 
+       int time_fx (ARDOUR::RegionList&, float val, bool pitching);
+
        friend class Drag;
        friend class RegionDrag;
        friend class RegionMoveDrag;
index 187590734532013c489792329da4d1268bc5461d..0f07875eacbc38c330f3f4eca9e502dfe69e1c17 100644 (file)
@@ -568,7 +568,7 @@ Editor::canvas_crossfade_view_event (GdkEvent* event, ArdourCanvas::Item* item,
                        boost::shared_ptr<AudioPlaylist> pl;
                        if ((pl = boost::dynamic_pointer_cast<AudioPlaylist> (atv->track()->playlist())) != 0) {
 
-                               boost::shared_ptr<Playlist::RegionList> rl = pl->regions_at (event_frame (event));
+                               boost::shared_ptr<RegionList> rl = pl->regions_at (event_frame (event));
                                if (!rl->empty()) {
 
                                        if (atv->layer_display() == Overlaid) {
@@ -618,7 +618,7 @@ Editor::canvas_crossfade_view_event (GdkEvent* event, ArdourCanvas::Item* item,
                                                layer_t const l = pl->top_layer () + 1 - (cy / c);
 
                                                /* hence region */
-                                               Playlist::RegionList::iterator i = rl->begin();
+                                               RegionList::iterator i = rl->begin();
                                                while (i != rl->end() && (*i)->layer() != l) {
                                                        ++i;
                                                }
index 269539dd722df5feb05b2d971d05bc93ad8a4593..582ddeb1fccdd1202b8d5cf96ed79f3f2f6a2748 100644 (file)
@@ -3304,15 +3304,16 @@ TimeFXDrag::finished (GdkEvent* /*event*/, bool movement_occurred)
        }
 #endif
 
-       // XXX how do timeFX on multiple regions ?
-
-       RegionSelection rs;
-       rs.add (_primary);
-
-       RegionSelection all = _editor->get_equivalent_regions (rs, ARDOUR::Properties::edit.property_id);
+       if (!_editor->get_selection().regions.empty()) {
+               /* primary will already be included in the selection, and edit
+                  group shared editing will propagate selection across
+                  equivalent regions, so just use the current region
+                  selection.
+               */
 
-       if (_editor->time_stretch (all, percentage) == -1) {
-               error << _("An error occurred while executing time stretch operation") << endmsg;
+               if (_editor->time_stretch (_editor->get_selection().regions, percentage) == -1) {
+                       error << _("An error occurred while executing time stretch operation") << endmsg;
+               }
        }
 }
 
index 830d8999a445b4cb67b496b7176f88385bcc054d..d4d02ea1c4acf6ba44d601815e5a4e84e5591dc8 100644 (file)
@@ -21,8 +21,8 @@
 #include <cstdlib>
 #include <cmath>
 #include <ctime>
-
 #include <string>
+#include <set>
 
 #include "pbd/error.h"
 #include "pbd/pthread_utils.h"
@@ -63,45 +63,87 @@ using namespace Gtkmm2ext;
 int
 Editor::time_stretch (RegionSelection& regions, float fraction)
 {
-       // FIXME: kludge, implement stretching of selection of both types
+       RegionList audio;
+       RegionList midi;
+       int aret;
+
+       begin_reversible_command (_("stretch/shrink"));
+
+       for (RegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) {
+               if  ((*i)->region()->data_type() == DataType::AUDIO) {
+                       audio.push_back ((*i)->region());
+               } else if  ((*i)->region()->data_type() == DataType::MIDI) {
+                       midi.push_back ((*i)->region());
+               }
+       }
+
+       if ((aret = time_fx (audio, fraction, false)) != 0) {
+               return aret;
+       }
+
+       set<boost::shared_ptr<Playlist> > midi_playlists_affected;
+
+       for (RegionList::iterator i = midi.begin(); i != midi.end(); ++i) {
+               boost::shared_ptr<Playlist> playlist = (*i)->playlist();
+
+               if (playlist) {
+                       playlist->clear_changes ();
+               }
+
+       }
+
+       ARDOUR::TimeFXRequest request;
+       request.time_fraction = fraction;
+
+       for (RegionList::iterator i = midi.begin(); i != midi.end(); ++i) {
+               boost::shared_ptr<Playlist> playlist = (*i)->playlist();
+
+               if (!playlist) {
+                       continue;
+               }
+
+               MidiStretch stretch (*_session, request);
+               stretch.run (*i);
 
-       if (regions.front()->region()->data_type() == DataType::AUDIO) {
-               // Audio, pop up timefx dialog
-               return time_fx (regions, fraction, false);
-       } else {
-               // MIDI, just stretch
-               RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (&regions.front()->get_time_axis_view());
-               if (!rtv)
-                       return -1;
-
-               boost::shared_ptr<Playlist> playlist = rtv->track()->playlist();
-
-               ARDOUR::TimeFXRequest request;
-               request.time_fraction = fraction;
-               MidiStretch stretch(*_session, request);
-               begin_reversible_command ("midi stretch");
-               stretch.run(regions.front()->region());
-                playlist->clear_changes ();
                playlist->replace_region (regions.front()->region(), stretch.results[0],
-                               regions.front()->region()->position());
-               _session->add_command (new StatefulDiffCommand (playlist));
-               commit_reversible_command ();
+                                         regions.front()->region()->position());
+               midi_playlists_affected.insert (playlist);
        }
 
+       for (set<boost::shared_ptr<Playlist> >::iterator p = midi_playlists_affected.begin(); p != midi_playlists_affected.end(); ++p) {
+               _session->add_command (new StatefulDiffCommand (*p));
+       }
+
+       commit_reversible_command ();
+
        return 0;
 }
 
 int
 Editor::pitch_shift (RegionSelection& regions, float fraction)
 {
-       return time_fx (regions, fraction, true);
+       RegionList rl;
+
+       for (RegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) {
+               rl.push_back ((*i)->region());
+       }
+
+       begin_reversible_command (_("pitch shift"));
+
+       int ret = time_fx (rl, fraction, true);
+
+       if (ret == 0) {
+               commit_reversible_command ();
+       }
+
+       return ret;
 }
 
 /** @param val Percentage to time stretch by; ignored if pitch-shifting.
  *  @param pitching true to pitch shift, false to time stretch.
  *  @return -1 in case of error, 1 if operation was cancelled by the user, 0 if everything went ok */
 int
-Editor::time_fx (RegionSelection& regions, float val, bool pitching)
+Editor::time_fx (RegionList& regions, float val, bool pitching)
 {
        delete current_timefx;
 
@@ -264,45 +306,31 @@ Editor::time_fx (RegionSelection& regions, float val, bool pitching)
 void
 Editor::do_timefx (TimeFXDialog& dialog)
 {
-       Track*    t;
        boost::shared_ptr<Playlist> playlist;
        boost::shared_ptr<Region>   new_region;
-       bool in_command = false;
+       set<boost::shared_ptr<Playlist> > playlists_affected;
 
        uint32_t const N = dialog.regions.size ();
 
-       for (RegionSelection::iterator i = dialog.regions.begin(); i != dialog.regions.end(); ) {
-               AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*i);
+       for (RegionList::iterator i = dialog.regions.begin(); i != dialog.regions.end(); ++i) {
+               boost::shared_ptr<Playlist> playlist = (*i)->playlist();
 
-               if (!arv) {
-                       continue;
+               if (playlist) {
+                       playlist->clear_changes ();
                }
+       }
 
-               boost::shared_ptr<AudioRegion> region (arv->audio_region());
-               TimeAxisView* tv = &(arv->get_time_axis_view());
-               RouteTimeAxisView* rtv;
-               RegionSelection::iterator tmp;
-
-               tmp = i;
-               ++tmp;
-
-               if ((rtv = dynamic_cast<RouteTimeAxisView*> (tv)) == 0) {
-                       i = tmp;
-                       continue;
-               }
+       for (RegionList::iterator i = dialog.regions.begin(); i != dialog.regions.end(); ++i) {
 
-               if ((t = dynamic_cast<Track*> (rtv->route().get())) == 0) {
-                       i = tmp;
-                       continue;
-               }
+               boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (*i);
 
-               if ((playlist = t->playlist()) == 0) {
-                       i = tmp;
+               if (!region || (playlist = region->playlist()) == 0) {
                        continue;
                }
 
                if (dialog.request.cancel) {
                        /* we were cancelled */
+                       /* XXX what to do about playlists already affected ? */
                        dialog.status = 1;
                        return;
                }
@@ -331,24 +359,16 @@ Editor::do_timefx (TimeFXDialog& dialog)
                if (!fx->results.empty()) {
                        new_region = fx->results.front();
 
-                       if (!in_command) {
-                               _session->begin_reversible_command (dialog.pitching ? _("pitch shift") : _("time stretch"));
-                               in_command = true;
-                       }
-
-                        playlist->clear_changes ();
                        playlist->replace_region (region, new_region, region->position());
-                       _session->add_command (new StatefulDiffCommand (playlist));
+                       playlists_affected.insert (playlist);
                }
 
                current_timefx->ascend ();
-
-               i = tmp;
                delete fx;
        }
 
-       if (in_command) {
-               _session->commit_reversible_command ();
+       for (set<boost::shared_ptr<Playlist> >::iterator p = playlists_affected.begin(); p != playlists_affected.end(); ++p) {
+               _session->add_command (new StatefulDiffCommand (*p));
        }
 
        dialog.status = 0;
index 54b6ae5023f28b7feb23f293fac14dd0095d8bb4..13f169b96e91337b4d1976248b6591acbc1fc080 100644 (file)
@@ -2416,7 +2416,7 @@ RouteTimeAxisView::create_gain_automation_child (const Evoral::Parameter& param,
 }
 
 static
-void add_region_to_list (RegionView* rv, Playlist::RegionList* l)
+void add_region_to_list (RegionView* rv, RegionList* l)
 {
        l->push_back (rv->region());
 }
@@ -2435,7 +2435,7 @@ RouteTimeAxisView::combine_regions ()
                return 0;
        }
 
-       Playlist::RegionList selected_regions;
+       RegionList selected_regions;
        boost::shared_ptr<Playlist> playlist = track()->playlist();
 
        _view->foreach_selected_regionview (sigc::bind (sigc::ptr_fun (add_region_to_list), &selected_regions));
@@ -2466,7 +2466,7 @@ RouteTimeAxisView::uncombine_regions ()
                return;
        }
 
-       Playlist::RegionList selected_regions;
+       RegionList selected_regions;
        boost::shared_ptr<Playlist> playlist = track()->playlist();
 
        /* have to grab selected regions first because the uncombine is going
@@ -2477,7 +2477,7 @@ RouteTimeAxisView::uncombine_regions ()
 
        playlist->clear_changes ();
 
-       for (Playlist::RegionList::iterator i = selected_regions.begin(); i != selected_regions.end(); ++i) {
+       for (RegionList::iterator i = selected_regions.begin(); i != selected_regions.end(); ++i) {
                playlist->uncombine (*i);
        }
 
index 20b0538a7fa6dd9ca1972816aaf3340fa21f4fa4..be7c32c1e822f28f97729e7f365772bb521b1b22 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <gtkmm.h>
 
+#include "ardour/playlist.h"
+
 #include "ardour_dialog.h"
 #include "region_selection.h"
 #include "progress_reporter.h"
@@ -40,8 +42,8 @@ public:
     Gtk::SpinButton       pitch_octave_spinner;
     Gtk::SpinButton       pitch_semitone_spinner;
     Gtk::SpinButton       pitch_cent_spinner;
-    RegionSelection       regions;
     Gtk::ProgressBar      progress_bar;
+    ARDOUR::RegionList    regions;
 
     /* SoundTouch */
     Gtk::CheckButton      quick_button;
index 90c75bbc18116b943e34f242a5072ef749f72944..9b4fba80ceab14cacf865eab4cf9a7c17308f526 100644 (file)
@@ -26,13 +26,13 @@ namespace ARDOUR {
 
 class MidiStretch : public Filter {
   public:
-       MidiStretch (ARDOUR::Session&, TimeFXRequest&);
+       MidiStretch (ARDOUR::Session&, const TimeFXRequest&);
        ~MidiStretch ();
 
        int run (boost::shared_ptr<ARDOUR::Region>, Progress* progress = 0);
 
   private:
-       TimeFXRequest& _request;
+       const TimeFXRequest& _request;
 };
 
 } /* namespace ARDOUR */
index 022fdb3ccbf5438a7949e0196a3179e60313082f..1f663108774d86083e2279ad5e34b5ef889c72e8 100644 (file)
@@ -81,7 +81,6 @@ class RegionListProperty : public PBD::SequenceProperty<std::list<boost::shared_
 class Playlist : public SessionObject , public boost::enable_shared_from_this<Playlist>
 {
 public:
-       typedef std::list<boost::shared_ptr<Region> > RegionList;
        static void make_property_quarks ();
 
        Playlist (Session&, const XMLNode&, DataType type, bool hidden = false);
index c2c72893292663e92610714f625324a9ff58ca67..c34869bc2b5ca407fa97665d5930d90b8511491e 100644 (file)
@@ -82,6 +82,8 @@ namespace ARDOUR {
        // associate a set of intervals with regions (e.g. for silence detection)
        typedef std::map<boost::shared_ptr<ARDOUR::Region>,AudioIntervalResult> AudioIntervalMap;
 
+       typedef std::list<boost::shared_ptr<Region> > RegionList;
+
        struct IOChange {
 
                enum Type {
index 7a4164427a24ba0f7e7a0a530acc9cb41c1ef04c..83b845bbfcba1521e4684ba7422e28044a4a8e14 100644 (file)
@@ -33,7 +33,7 @@ using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
 
-MidiStretch::MidiStretch (Session& s, TimeFXRequest& req)
+MidiStretch::MidiStretch (Session& s, const TimeFXRequest& req)
        : Filter (s)
        , _request (req)
 {
index bc11b863eb0420a003a5b0a4d04fa538113e9c33..a17d72c4ebcd0671cc85184db596f398992062c1 100644 (file)
@@ -1634,7 +1634,7 @@ Playlist::flush_notifications (bool from_undo)
   FINDING THINGS
   **********************************************************************/
 
-boost::shared_ptr<Playlist::RegionList>
+boost::shared_ptr<RegionList>
 Playlist::regions_at (framepos_t frame)
 {
        RegionLock rlock (this);
@@ -1703,7 +1703,7 @@ Playlist::regions_at (framepos_t frame)
         return region;
  }
 
-boost::shared_ptr<Playlist::RegionList>
+boost::shared_ptr<RegionList>
 Playlist::regions_to_read (framepos_t start, framepos_t end)
 {
         /* Caller must hold lock */
@@ -1838,7 +1838,7 @@ Playlist::regions_to_read (framepos_t start, framepos_t end)
         return rlist;
  }
 
-boost::shared_ptr<Playlist::RegionList>
+boost::shared_ptr<RegionList>
 Playlist::find_regions_at (framepos_t frame)
 {
        /* Caller must hold lock */
@@ -1854,7 +1854,7 @@ Playlist::find_regions_at (framepos_t frame)
        return rlist;
 }
 
-boost::shared_ptr<Playlist::RegionList>
+boost::shared_ptr<RegionList>
 Playlist::regions_touched (framepos_t start, framepos_t end)
 {
        RegionLock rlock (this);