+
+ if (sel) {
+ sel->sort (cmp);
+ } else {
+ selection->tracks.sort (cmp);
+ }
+}
+
+nframes64_t
+Editor::get_preferred_edit_position (bool ignore_playhead)
+{
+ bool ignored;
+ nframes64_t where = 0;
+ EditPoint ep = _edit_point;
+
+ if (entered_marker) {
+ return entered_marker->position();
+ }
+
+ if (ignore_playhead && ep == EditAtPlayhead) {
+ ep = EditAtSelectedMarker;
+ }
+
+ switch (ep) {
+ case EditAtPlayhead:
+ where = session->audible_frame();
+ break;
+
+ case EditAtSelectedMarker:
+ if (!selection->markers.empty()) {
+ bool is_start;
+ Location* loc = find_location_from_marker (selection->markers.front(), is_start);
+ if (loc) {
+ if (is_start) {
+ where = loc->start();
+ } else {
+ where = loc->end();
+ }
+ break;
+ }
+ }
+ /* fallthru */
+
+ default:
+ case EditAtMouse:
+ if (!mouse_frame (where, ignored)) {
+ /* XXX not right but what can we do ? */
+ return 0;
+ }
+ snap_to (where);
+ break;
+ }
+
+ return where;
+}
+
+void
+Editor::set_loop_range (nframes64_t start, nframes64_t end, string cmd)
+{
+ if (!session) return;
+
+ begin_reversible_command (cmd);
+
+ Location* tll;
+
+ if ((tll = transport_loop_location()) == 0) {
+ Location* loc = new Location (start, end, _("Loop"), Location::IsAutoLoop);
+ XMLNode &before = session->locations()->get_state();
+ session->locations()->add (loc, true);
+ session->set_auto_loop_location (loc);
+ XMLNode &after = session->locations()->get_state();
+ session->add_command (new MementoCommand<Locations>(*(session->locations()), &before, &after));
+ } else {
+ XMLNode &before = tll->get_state();
+ tll->set_hidden (false, this);
+ tll->set (start, end);
+ XMLNode &after = tll->get_state();
+ session->add_command (new MementoCommand<Location>(*tll, &before, &after));
+ }
+
+ commit_reversible_command ();
+}
+
+void
+Editor::set_punch_range (nframes64_t start, nframes64_t end, string cmd)
+{
+ if (!session) return;
+
+ begin_reversible_command (cmd);
+
+ Location* tpl;
+
+ if ((tpl = transport_punch_location()) == 0) {
+ Location* loc = new Location (start, end, _("Loop"), Location::IsAutoPunch);
+ XMLNode &before = session->locations()->get_state();
+ session->locations()->add (loc, true);
+ session->set_auto_loop_location (loc);
+ XMLNode &after = session->locations()->get_state();
+ session->add_command (new MementoCommand<Locations>(*(session->locations()), &before, &after));
+ }
+ else {
+ XMLNode &before = tpl->get_state();
+ tpl->set_hidden (false, this);
+ tpl->set (start, end);
+ XMLNode &after = tpl->get_state();
+ session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
+ }
+
+ commit_reversible_command ();
+}
+
+void
+Editor::get_regions_at (RegionSelection& rs, nframes64_t where, const TrackSelection& ts) const
+{
+ const TrackSelection* tracks;
+
+ if (ts.empty()) {
+ tracks = &track_views;
+ } else {
+ tracks = &ts;
+ }
+
+ for (TrackSelection::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
+
+ AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(*t);
+
+ if (atv) {
+ boost::shared_ptr<Diskstream> ds;
+ boost::shared_ptr<Playlist> pl;
+
+ if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
+
+ Playlist::RegionList* regions = pl->regions_at ((nframes64_t) floor ( (double)where * ds->speed()));
+
+ for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
+
+ RegionView* rv = atv->audio_view()->find_view (*i);
+
+ if (rv) {
+ rs.add (rv);
+ }
+ }
+
+ delete regions;
+ }
+ }
+ }
+}
+
+void
+Editor::get_regions_after (RegionSelection& rs, nframes64_t where, const TrackSelection& ts) const
+{
+ const TrackSelection* tracks;
+
+ if (ts.empty()) {
+ tracks = &track_views;
+ } else {
+ tracks = &ts;
+ }
+
+ for (TrackSelection::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
+
+ AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(*t);
+
+ if (atv) {
+ boost::shared_ptr<Diskstream> ds;
+ boost::shared_ptr<Playlist> pl;
+
+ if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
+
+ Playlist::RegionList* regions = pl->regions_touched ((nframes64_t) floor ( (double)where * ds->speed()), max_frames);
+
+ for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
+
+ RegionView* rv = atv->audio_view()->find_view (*i);
+
+ if (rv) {
+ rs.push_back (rv);
+ }
+ }
+
+ delete regions;
+ }
+ }
+ }
+}
+
+void
+Editor::get_regions_for_action (RegionSelection& rs, bool allow_entered)
+{
+ if (selection->regions.empty()) {
+
+ if (selection->tracks.empty()) {
+
+ /* no regions or tracks selected
+ */
+
+ if (entered_regionview && mouse_mode == Editing::MouseObject) {
+
+ /* entered regionview is valid and we're in object mode -
+ just use entered regionview
+ */
+
+ rs.add (entered_regionview);
+ }
+
+ return;
+
+ } else {
+
+ /* no regions selected, so get all regions at the edit point across
+ all selected tracks.
+ */
+
+ nframes64_t where = get_preferred_edit_position();
+ get_regions_at (rs, where, selection->tracks);
+
+ /* if the entered regionview wasn't selected and neither was its track
+ then add it.
+ */
+
+ if (entered_regionview != 0 &&
+ !selection->selected (entered_regionview) &&
+ !selection->selected (&entered_regionview->get_time_axis_view())) {
+ rs.add (entered_regionview);
+ }
+ }
+
+ } else {
+
+ /* just use the selected regions */
+
+ rs = selection->regions;
+
+ /* if the entered regionview wasn't selected and we allow this sort of thing,
+ then add it.
+ */
+
+ if (allow_entered && entered_regionview && !selection->selected (entered_regionview)) {
+ rs.add (entered_regionview);
+ }
+
+ }
+}
+
+void
+Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions)
+{
+
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+
+ RouteTimeAxisView* tatv;
+
+ if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
+
+ boost::shared_ptr<Playlist> pl;
+ vector<boost::shared_ptr<Region> > results;
+ RegionView* marv;
+ boost::shared_ptr<Diskstream> ds;
+
+ if ((ds = tatv->get_diskstream()) == 0) {
+ /* bus */
+ continue;
+ }
+
+ if ((pl = (ds->playlist())) != 0) {
+ pl->get_region_list_equivalent_regions (region, results);
+ }
+
+ for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
+ if ((marv = tatv->view()->find_view (*ir)) != 0) {
+ regions.push_back (marv);
+ }
+ }
+
+ }
+ }
+}
+
+void
+Editor::show_rhythm_ferret ()
+{
+ if (rhythm_ferret == 0) {
+ rhythm_ferret = new RhythmFerret(*this);
+ }
+
+ rhythm_ferret->set_session (session);
+ rhythm_ferret->show ();
+ rhythm_ferret->present ();
+}
+
+void
+Editor::show_bundle_manager ()
+{
+ if (_bundle_manager == 0) {
+ _bundle_manager = new BundleManager (*session);
+ }
+
+ _bundle_manager->show ();
+}
+
+void
+Editor::show_global_port_matrix (ARDOUR::DataType t)
+{
+ if (_global_port_matrix[t] == 0) {
+ _global_port_matrix[t] = new GlobalPortMatrixWindow (*session, t);
+ }
+
+ _global_port_matrix[t]->show ();