summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/editor.cc8
-rw-r--r--gtk2_ardour/editor.h3
-rw-r--r--gtk2_ardour/editor_canvas_events.cc4
-rw-r--r--gtk2_ardour/editor_drag.cc17
-rw-r--r--gtk2_ardour/editor_timefx.cc138
-rw-r--r--gtk2_ardour/route_time_axis.cc8
-rw-r--r--gtk2_ardour/time_fx_dialog.h4
-rw-r--r--libs/ardour/ardour/midi_stretch.h4
-rw-r--r--libs/ardour/ardour/playlist.h1
-rw-r--r--libs/ardour/ardour/types.h2
-rw-r--r--libs/ardour/midi_stretch.cc2
-rw-r--r--libs/ardour/playlist.cc8
12 files changed, 112 insertions, 87 deletions
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc
index f94269c564..01777f54a3 100644
--- a/gtk2_ardour/editor.cc
+++ b/gtk2_ardour/editor.cc
@@ -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);
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index e12e20f610..2bf8fa8052 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -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;
diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc
index 1875907345..0f07875eac 100644
--- a/gtk2_ardour/editor_canvas_events.cc
+++ b/gtk2_ardour/editor_canvas_events.cc
@@ -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;
}
diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc
index 269539dd72..582ddeb1fc 100644
--- a/gtk2_ardour/editor_drag.cc
+++ b/gtk2_ardour/editor_drag.cc
@@ -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;
+ }
}
}
diff --git a/gtk2_ardour/editor_timefx.cc b/gtk2_ardour/editor_timefx.cc
index 830d8999a4..d4d02ea1c4 100644
--- a/gtk2_ardour/editor_timefx.cc
+++ b/gtk2_ardour/editor_timefx.cc
@@ -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;
diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc
index 54b6ae5023..13f169b96e 100644
--- a/gtk2_ardour/route_time_axis.cc
+++ b/gtk2_ardour/route_time_axis.cc
@@ -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);
}
diff --git a/gtk2_ardour/time_fx_dialog.h b/gtk2_ardour/time_fx_dialog.h
index 20b0538a7f..be7c32c1e8 100644
--- a/gtk2_ardour/time_fx_dialog.h
+++ b/gtk2_ardour/time_fx_dialog.h
@@ -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;
diff --git a/libs/ardour/ardour/midi_stretch.h b/libs/ardour/ardour/midi_stretch.h
index 90c75bbc18..9b4fba80ce 100644
--- a/libs/ardour/ardour/midi_stretch.h
+++ b/libs/ardour/ardour/midi_stretch.h
@@ -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 */
diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h
index 022fdb3ccb..1f66310877 100644
--- a/libs/ardour/ardour/playlist.h
+++ b/libs/ardour/ardour/playlist.h
@@ -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);
diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h
index c2c7289329..c34869bc2b 100644
--- a/libs/ardour/ardour/types.h
+++ b/libs/ardour/ardour/types.h
@@ -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 {
diff --git a/libs/ardour/midi_stretch.cc b/libs/ardour/midi_stretch.cc
index 7a4164427a..83b845bbfc 100644
--- a/libs/ardour/midi_stretch.cc
+++ b/libs/ardour/midi_stretch.cc
@@ -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)
{
diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc
index bc11b863eb..a17d72c4eb 100644
--- a/libs/ardour/playlist.cc
+++ b/libs/ardour/playlist.cc
@@ -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);