From 33c61757fc8352fdb1280bca28b54d1adee183ff Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 27 Jan 2012 16:29:01 +0000 Subject: promote Playlist::RegionList to ARDOUR::RegionList; fix timefx on multiple regions, even regions of mixed type. this mostly involved some trivial code changes but to make the code simpler and less error prone, the API switched away from using RegionSelection (list of regionviews that catches regionviews vanishing) and used RegionList (lists of regions, no semantics) instead. git-svn-id: svn://localhost/ardour2/branches/3.0@11362 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/editor.cc | 8 +-- gtk2_ardour/editor.h | 3 +- gtk2_ardour/editor_canvas_events.cc | 4 +- gtk2_ardour/editor_drag.cc | 17 ++--- gtk2_ardour/editor_timefx.cc | 138 +++++++++++++++++++++--------------- gtk2_ardour/route_time_axis.cc | 8 +-- gtk2_ardour/time_fx_dialog.h | 4 +- 7 files changed, 103 insertions(+), 79 deletions(-) (limited to 'gtk2_ardour') 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 regions = pl->regions_at ( + boost::shared_ptr 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 regions = pl->regions_touched ( + boost::shared_ptr 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 pl; if ((pl = boost::dynamic_pointer_cast (atv->track()->playlist())) != 0) { - boost::shared_ptr rl = pl->regions_at (event_frame (event)); + boost::shared_ptr 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 #include #include - #include +#include #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 > midi_playlists_affected; + + for (RegionList::iterator i = midi.begin(); i != midi.end(); ++i) { + boost::shared_ptr 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 = (*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 (®ions.front()->get_time_axis_view()); - if (!rtv) - return -1; - - boost::shared_ptr 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 >::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; boost::shared_ptr new_region; - bool in_command = false; + set > playlists_affected; uint32_t const N = dialog.regions.size (); - for (RegionSelection::iterator i = dialog.regions.begin(); i != dialog.regions.end(); ) { - AudioRegionView* arv = dynamic_cast(*i); + for (RegionList::iterator i = dialog.regions.begin(); i != dialog.regions.end(); ++i) { + boost::shared_ptr playlist = (*i)->playlist(); - if (!arv) { - continue; + if (playlist) { + playlist->clear_changes (); } + } - boost::shared_ptr region (arv->audio_region()); - TimeAxisView* tv = &(arv->get_time_axis_view()); - RouteTimeAxisView* rtv; - RegionSelection::iterator tmp; - - tmp = i; - ++tmp; - - if ((rtv = dynamic_cast (tv)) == 0) { - i = tmp; - continue; - } + for (RegionList::iterator i = dialog.regions.begin(); i != dialog.regions.end(); ++i) { - if ((t = dynamic_cast (rtv->route().get())) == 0) { - i = tmp; - continue; - } + boost::shared_ptr region = boost::dynamic_pointer_cast (*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 >::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 = 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 = 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 +#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; -- cgit v1.2.3