#include <map>
#include <set>
+#include <gtkmm/messagedialog.h>
+
#include "pbd/error.h"
#include "pbd/basename.h"
#include "pbd/pthread_utils.h"
#include "pbd/whitespace.h"
#include "pbd/stateful_diff_command.h"
-#include <gtkmm2ext/utils.h>
-#include <gtkmm2ext/choice.h>
-#include <gtkmm2ext/popup.h>
+#include "gtkmm2ext/utils.h"
+
+#include "widgets/choice.h"
+#include "widgets/popup.h"
+#include "widgets/prompter.h"
#include "ardour/audio_track.h"
#include "ardour/audioregion.h"
#include "ardour/strip_silence.h"
#include "ardour/transient_detector.h"
#include "ardour/transpose.h"
+#include "ardour/vca_manager.h"
#include "canvas/canvas.h"
#include "item_counts.h"
#include "keyboard.h"
#include "midi_region_view.h"
+#include "mixer_ui.h"
#include "mixer_strip.h"
#include "mouse_cursors.h"
#include "normalize_dialog.h"
#include "transpose_dialog.h"
#include "transform_dialog.h"
#include "ui_config.h"
+#include "vca_time_axis.h"
#include "pbd/i18n.h"
using namespace PBD;
using namespace Gtk;
using namespace Gtkmm2ext;
+using namespace ArdourWidgets;
using namespace Editing;
using Gtkmm2ext::Keyboard;
}
void
-Editor::split_regions_at (framepos_t where, RegionSelection& regions, const int32_t sub_num)
+Editor::split_regions_at (MusicFrame where, RegionSelection& regions, bool snap_frame)
{
bool frozen = false;
case SnapToRegionEnd:
break;
default:
- snap_to (where);
+ if (snap_frame) {
+ snap_to (where);
+ }
}
} else {
- snap_to (where);
+ if (snap_frame) {
+ snap_to (where);
+ }
frozen = true;
EditorFreeze(); /* Emit Signal */
have something to split.
*/
- if (!(*a)->region()->covers (where)) {
+ if (!(*a)->region()->covers (where.frame)) {
++a;
continue;
}
if (pl) {
pl->clear_changes ();
- pl->split_region ((*a)->region(), where, sub_num);
+ pl->split_region ((*a)->region(), where);
_session->add_command (new StatefulDiffCommand (pl));
}
if (working_on_selection) {
// IFF we were working on selected regions, try to reinstate the other region selections that existed before the freeze/thaw.
- _ignore_follow_edits = true; // a split will change the region selection in mysterious ways; it's not practical or wanted to follow this edit
RegionSelectionAfterSplit rsas = Config->get_region_selection_after_split();
/* There are three classes of regions that we might want selected after
splitting selected regions:
}
for (RegionSelection::iterator ri = latest_regionviews.begin(); ri != latest_regionviews.end(); ri++) {
- if ((*ri)->region()->position() < where) {
+ if ((*ri)->region()->position() < where.frame) {
// new regions created before the split
if (rsas & NewlyCreatedLeft) {
selection->add (*ri);
}
}
}
- _ignore_follow_edits = false;
} else {
- _ignore_follow_edits = true;
if( working_on_selection ) {
selection->add (latest_regionviews); //these are the new regions created after the split
}
- _ignore_follow_edits = false;
}
commit_reversible_command ();
bool is_start;
bool in_command = false;
+ const int32_t divisions = get_grid_music_divisions (0);
for (MarkerSelection::iterator i = selection->markers.begin(); i != selection->markers.end(); ++i) {
distance = next_distance;
}
if (max_framepos - distance > loc->start() + loc->length()) {
- loc->set_start (loc->start() + distance);
+ loc->set_start (loc->start() + distance, false, true, divisions);
} else {
- loc->set_start (max_framepos - loc->length());
+ loc->set_start (max_framepos - loc->length(), false, true, divisions);
}
} else {
distance = get_nudge_distance (loc->end(), next_distance);
distance = next_distance;
}
if (max_framepos - distance > loc->end()) {
- loc->set_end (loc->end() + distance);
+ loc->set_end (loc->end() + distance, false, true, divisions);
} else {
- loc->set_end (max_framepos);
+ loc->set_end (max_framepos, false, true, divisions);
}
if (loc->is_session_range()) {
_session->set_end_is_free (false);
distance = next_distance;
}
if (distance < loc->start()) {
- loc->set_start (loc->start() - distance);
+ loc->set_start (loc->start() - distance, false, true, get_grid_music_divisions(0));
} else {
- loc->set_start (0);
+ loc->set_start (0, false, true, get_grid_music_divisions(0));
}
} else {
distance = get_nudge_distance (loc->end(), next_distance);
}
if (distance < loc->end() - loc->length()) {
- loc->set_end (loc->end() - distance);
+ loc->set_end (loc->end() - distance, false, true, get_grid_music_divisions(0));
} else {
- loc->set_end (loc->length());
+ loc->set_end (loc->length(), false, true, get_grid_music_divisions(0));
}
if (loc->is_session_range()) {
_session->set_end_is_free (false);
}
struct RegionSelectionPositionSorter {
- bool operator() (RegionView* a, RegionView* b) {
- return a->region()->position() < b->region()->position();
- }
+ bool operator() (RegionView* a, RegionView* b) {
+ return a->region()->position() < b->region()->position();
+ }
};
void
return;
}
+ bool maybe_first_frame = false;
+
switch (_snap_type) {
case SnapToRegionStart:
interesting_points.push_back (Start);
+ maybe_first_frame = true;
break;
case SnapToRegionEnd:
interesting_points.push_back (End);
case SnapToRegionBoundary:
interesting_points.push_back (Start);
interesting_points.push_back (End);
+ maybe_first_frame = true;
break;
default:
fatal << string_compose (_("build_region_boundary_cache called with snap_type = %1"), _snap_type) << endmsg;
tlist = track_views.filter_to_unique_playlists ();
}
+ if (maybe_first_frame) {
+ TrackViewList::const_iterator i;
+ for (i = tlist.begin(); i != tlist.end(); ++i) {
+ boost::shared_ptr<Playlist> pl = (*i)->playlist();
+ if (pl && pl->count_regions_at (0)) {
+ region_boundary_cache.push_back (0);
+ break;
+ }
+ }
+ }
+
while (pos < _session->current_end_frame() && !at_end) {
framepos_t rpos;
return;
}
- loc->move_to (target);
+ loc->move_to (target, 0);
}
void
pos = track_frame_to_session_frame(pos, speed);
- loc->move_to (pos);
+ loc->move_to (pos, 0);
}
void
return;
}
- loc->move_to (pos);
+ loc->move_to (pos, 0);
}
void
return;
}
- loc->move_to (pos);
+ loc->move_to (pos, 0);
}
void
_session->request_locate (selection->markers.front()->position(), _session->transport_rolling());
} else {
+ const int32_t divisions = get_grid_music_divisions (0);
/* move selected markers to playhead */
for (MarkerSelection::iterator i = selection->markers.begin(); i != selection->markers.end(); ++i) {
Location* loc = find_location_from_marker (*i, ignored);
if (loc->is_mark()) {
- loc->set_start (playhead_cursor->current_frame ());
+ loc->set_start (playhead_cursor->current_frame (), false, true, divisions);
} else {
loc->set (playhead_cursor->current_frame (),
- playhead_cursor->current_frame () + loc->length());
+ playhead_cursor->current_frame () + loc->length(), true, divisions);
}
}
}
reset_y_origin (vertical_adjustment.get_value() - 60);
}
+void
+Editor::select_topmost_track ()
+{
+ const double top_of_trackviews = vertical_adjustment.get_value();
+ for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
+ if ((*t)->hidden()) {
+ continue;
+ }
+ std::pair<TimeAxisView*,double> res = (*t)->covers_y_position (top_of_trackviews);
+ if (res.first) {
+ selection->set (*t);
+ break;
+ }
+ }
+}
+
bool
Editor::scroll_down_one_track (bool skip_child_views)
{
}
void
-Editor::temporal_zoom_step_mouse_focus (bool coarser)
+Editor::temporal_zoom_step_mouse_focus_scale (bool zoom_out, double scale)
{
Editing::ZoomFocus temp_focus = zoom_focus;
zoom_focus = Editing::ZoomFocusMouse;
- temporal_zoom_step (coarser);
+ temporal_zoom_step_scale (zoom_out, scale);
zoom_focus = temp_focus;
}
void
-Editor::temporal_zoom_step (bool coarser)
+Editor::temporal_zoom_step_mouse_focus (bool zoom_out)
{
- ENSURE_GUI_THREAD (*this, &Editor::temporal_zoom_step, coarser)
+ temporal_zoom_step_mouse_focus_scale (zoom_out, 2.0);
+}
+
+void
+Editor::temporal_zoom_step (bool zoom_out)
+{
+ temporal_zoom_step_scale (zoom_out, 2.0);
+}
+
+void
+Editor::temporal_zoom_step_scale (bool zoom_out, double scale)
+{
+ ENSURE_GUI_THREAD (*this, &Editor::temporal_zoom_step, zoom_out, scale)
framecnt_t nspp = samples_per_pixel;
- if (coarser) {
- nspp *= 2;
+ if (zoom_out) {
+ nspp *= scale;
+ if (nspp == samples_per_pixel) {
+ nspp *= 2.0;
+ }
} else {
- nspp /= 2;
+ nspp /= scale;
+ if (nspp == samples_per_pixel) {
+ nspp /= 2.0;
+ }
+ }
+
+ // ToDo: encapsulate all of this into something like editor::get_session_extents() or editor::leftmost(), rightmost()
+ {
+ //ToDo: also incorporate automation regions (in case the session has no audio/midi but is just used for automating plugins or the like)
+
+ //calculate the extents of all regions in every playlist
+ framecnt_t session_extent_start = 0;
+ framecnt_t session_extent_end = 0;
+ {
+ boost::shared_ptr<RouteList> rl = _session->get_routes();
+ for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
+ boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*r);
+ if (tr) {
+ boost::shared_ptr<Playlist> pl = tr->playlist();
+ if (pl) {
+ pair<framepos_t, framepos_t> e;
+ e = pl->get_extent();
+ if (e.first < session_extent_start) {
+ session_extent_start = e.first;
+ }
+ if (e.second > session_extent_end) {
+ session_extent_end = e.second;
+ }
+ }
+ }
+ }
+ }
+ framecnt_t session_extents = session_extent_end - session_extent_start;
+
+ //in a session with no regions, use the start/end markers to set max zoom
+ framecnt_t const session_length = _session->current_end_frame() - _session->current_start_frame ();
+ if ( session_length > session_extents )
+ session_extents = session_length;
+
+ //in a session with no regions or start/end markers, use 2 minutes to set max zoom
+ framecnt_t const min_length = _session->nominal_frame_rate()*60*2;
+ if ( min_length > session_extents )
+ session_extents = min_length;
+
+ //convert to samples-per-pixel and limit our zoom to this value
+ framecnt_t session_extents_pp = session_extents / _visible_canvas_width;
+ if (nspp > session_extents_pp)
+ nspp = session_extents_pp;
}
temporal_zoom (nspp);
framepos_t leftmost_after_zoom = 0;
framepos_t where;
bool in_track_canvas;
+ bool use_mouse_frame = true;
framecnt_t nfpp;
double l;
case ZoomFocusMouse:
/* try to keep the mouse over the same point in the display */
- if (!mouse_frame (where, in_track_canvas)) {
- /* use playhead instead */
- where = playhead_cursor->current_frame ();
-
- if (where < half_page_size) {
- leftmost_after_zoom = 0;
- } else {
- leftmost_after_zoom = where - half_page_size;
- }
-
- } else {
+ if (_drags->active()) {
+ where = _drags->current_pointer_frame ();
+ } else if (!mouse_frame (where, in_track_canvas)) {
+ use_mouse_frame = false;
+ }
+ if (use_mouse_frame) {
l = - ((new_page_size * ((where - current_leftmost)/(double)current_page)) - where);
if (l < 0) {
} else {
leftmost_after_zoom = (framepos_t) l;
}
- }
+ } else {
+ /* use playhead instead */
+ where = playhead_cursor->current_frame ();
+ if (where < half_page_size) {
+ leftmost_after_zoom = 0;
+ } else {
+ leftmost_after_zoom = where - half_page_size;
+ }
+ }
break;
case ZoomFocusEdit:
}
}
-void
-Editor::temporal_zoom_region (bool both_axes)
-{
- framepos_t start = max_framepos;
- framepos_t end = 0;
- set<TimeAxisView*> tracks;
-
- if ( !get_selection_extents(start, end) )
- return;
-
- calc_extra_zoom_edges (start, end);
-
- /* if we're zooming on both axes we need to save track heights etc.
- */
-
- undo_visual_stack.push_back (current_visual_state (both_axes));
-
- PBD::Unwinder<bool> nsv (no_save_visual, true);
-
- temporal_zoom_by_frame (start, end);
-
- if (both_axes) {
- uint32_t per_track_height = (uint32_t) floor ((_visible_canvas_height - 10.0) / tracks.size());
-
- /* set visible track heights appropriately */
-
- for (set<TimeAxisView*>::iterator t = tracks.begin(); t != tracks.end(); ++t) {
- (*t)->set_height (per_track_height);
- }
-
- /* hide irrelevant tracks */
-
- DisplaySuspender ds;
-
- for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
- if (find (tracks.begin(), tracks.end(), (*i)) == tracks.end()) {
- hide_track_in_display (*i);
- }
- }
-
- vertical_adjustment.set_value (0.0);
- }
-
- redo_visual_stack.push_back (current_visual_state (both_axes));
-}
-
-
bool
Editor::get_selection_extents (framepos_t &start, framepos_t &end) const
{
void
-Editor::temporal_zoom_selection (bool both_axes)
+Editor::temporal_zoom_selection (Editing::ZoomAxis axes)
{
if (!selection) return;
//ToDo: if control points are selected, zoom to that
- //if region(s) are selected, zoom to that
- if ( !selection->regions.empty() )
- temporal_zoom_region (both_axes);
+ if (axes == Horizontal || axes == Both) {
- //if a range is selected, zoom to that
- if (!selection->time.empty()) {
-
- framepos_t start, end;
+ framepos_t start, end;
if (get_selection_extents (start, end)) {
- calc_extra_zoom_edges(start, end);
+ calc_extra_zoom_edges (start, end);
temporal_zoom_by_frame (start, end);
}
-
- if (both_axes)
- fit_selection();
}
+ if (axes == Vertical || axes == Both) {
+ fit_selection ();
+ }
}
void
return true;
}
- ArdourPrompter dialog (true);
+ Prompter dialog (true);
dialog.set_prompt (_("New Name:"));
framepos_t end = selection->time[clicked_selection].end;
_session->locations()->next_available_name(rangename,"selection");
- Location *location = new Location (*_session, start, end, rangename, Location::IsRangeMarker);
+ Location *location = new Location (*_session, start, end, rangename, Location::IsRangeMarker, get_grid_music_divisions(0));
begin_reversible_command (_("add marker"));
if (!choose_new_marker_name(markername)) {
return;
}
- Location *location = new Location (*_session, where, where, markername, Location::IsMark);
+ Location *location = new Location (*_session, where, where, markername, Location::IsMark, get_grid_music_divisions (0));
begin_reversible_command (_("add marker"));
XMLNode &before = _session->locations()->get_state();
boost::shared_ptr<Region> region = (*i)->region ();
- Location *location = new Location (*_session, region->position(), region->last_frame(), region->name(), Location::IsRangeMarker);
+ Location *location = new Location (*_session, region->position(), region->last_frame(), region->name(), Location::IsRangeMarker, 0);
_session->locations()->add (location, true);
commit = true;
}
// single range spanning all selected
- Location *location = new Location (*_session, selection->regions.start(), selection->regions.end_frame(), markername, Location::IsRangeMarker);
+ Location *location = new Location (*_session, selection->regions.start(), selection->regions.end_frame(), markername, Location::IsRangeMarker, 0);
_session->locations()->add (location, true);
begin_reversible_command (_("add marker"));
framepos_t pos = _session->locations()->first_mark_before (playhead_cursor->current_frame());
+ //handle the case where we are rolling, and we're less than one-half second past the mark, we want to go to the prior mark...
+ if ( _session->transport_rolling() ) {
+ if ( (playhead_cursor->current_frame() - pos) < _session->frame_rate()/2 ) {
+ framepos_t prior = _session->locations()->first_mark_before ( pos );
+ pos = prior;
+ }
+ }
+
if (pos < 0) {
return;
}
return;
}
- _session->locations()->add (new Location (*_session, pos, 0, markername, Location::IsMark), true);
+ _session->locations()->add (new Location (*_session, pos, 0, markername, Location::IsMark, 0), true);
}
void
_session->request_play_range (&lar, true);
}
-framepos_t
-Editor::get_preroll ()
-{
- return Config->get_preroll_seconds() * _session->frame_rate();
-}
-
void
-Editor::maybe_locate_with_edit_preroll ( framepos_t location )
+Editor::maybe_locate_with_edit_preroll (framepos_t location)
{
- if ( _session->transport_rolling() || !UIConfiguration::instance().get_follow_edits() || _ignore_follow_edits || _session->config.get_external_sync() )
+ if ( _session->transport_rolling() || !UIConfiguration::instance().get_follow_edits() || _session->config.get_external_sync() )
return;
- location -= get_preroll();
+ location -= _session->preroll_samples (location);
//don't try to locate before the beginning of time
- if ( location < 0 )
+ if (location < 0) {
location = 0;
+ }
//if follow_playhead is on, keep the playhead on the screen
if ( _follow_playhead )
void
Editor::play_with_preroll ()
{
- {
- framepos_t preroll = get_preroll();
+ framepos_t start, end;
+ if ( UIConfiguration::instance().get_follow_edits() && get_selection_extents ( start, end) ) {
+ const framepos_t preroll = _session->preroll_samples (start);
- framepos_t start, end;
- if (!get_selection_extents ( start, end))
- return;
+ framepos_t ret = start;
- if (start > preroll)
+ if (start > preroll) {
start = start - preroll;
+ }
end = end + preroll; //"post-roll"
lar.push_back (ar);
_session->request_play_range (&lar, true);
+ _session->set_requested_return_frame (ret); //force auto-return to return to range start, without the preroll
+ } else {
+ framepos_t ph = playhead_cursor->current_frame ();
+ const framepos_t preroll = _session->preroll_samples (ph);
+ framepos_t start;
+ if (ph > preroll) {
+ start = ph - preroll;
+ } else {
+ start = 0;
+ }
+ _session->request_locate (start, true);
+ _session->set_requested_return_frame (ph); //force auto-return to return to playhead location, without the preroll
}
}
+void
+Editor::rec_with_preroll ()
+{
+ framepos_t ph = playhead_cursor->current_frame ();
+ framepos_t preroll = _session->preroll_samples (ph);
+ _session->request_preroll_record_trim (ph, preroll);
+}
+
+void
+Editor::rec_with_count_in ()
+{
+ _session->request_count_in_record ();
+}
+
void
Editor::play_location (Location& location)
{
if (!latest_regionviews.empty()) {
rtv->view()->foreach_regionview (sigc::bind (
- sigc::ptr_fun (add_if_covered),
- &(*t), &new_selection));
+ sigc::ptr_fun (add_if_covered),
+ &(*t), &new_selection));
if (!in_command) {
begin_reversible_command (_("separate"));
}
struct PlaylistState {
- boost::shared_ptr<Playlist> playlist;
- XMLNode* before;
+ boost::shared_ptr<Playlist> playlist;
+ XMLNode* before;
};
/** Take tracks from get_tracks_for_range_action and cut any regions
boost::shared_ptr<Playlist> playlist = (*rl)->playlist();
- if (!playlist) {
+ if (!playlist) {
// is this check necessary?
continue;
- }
+ }
vector<PlaylistState>::iterator i;
PlaylistState before;
before.playlist = playlist;
before.before = &playlist->get_state();
-
+ playlist->clear_changes ();
playlist->freeze ();
playlists.push_back(before);
}
{
if (!selection->time.empty()) {
- crop_region_to (selection->time.start(), selection->time.end_frame());
-
+ begin_reversible_command (_("Crop Regions to Time Selection"));
+ for (std::list<AudioRange>::iterator i = selection->time.begin(); i != selection->time.end(); ++i) {
+ crop_region_to ((*i).start, (*i).end);
+ }
+ commit_reversible_command();
} else {
framepos_t start;
framepos_t end;
if (get_edit_op_range (start, end)) {
+ begin_reversible_command (_("Crop Regions to Edit Range"));
+
crop_region_to (start, end);
+
+ commit_reversible_command();
}
}
framepos_t new_start;
framepos_t new_end;
framecnt_t new_length;
- bool in_command = false;
for (vector<boost::shared_ptr<Playlist> >::iterator i = playlists.begin(); i != playlists.end(); ++i) {
new_end = min (end, new_end);
new_length = new_end - new_start + 1;
- if(!in_command) {
- begin_reversible_command (_("trim to selection"));
- in_command = true;
- }
(*i)->clear_changes ();
(*i)->trim_to (new_start, new_length);
_session->add_command (new StatefulDiffCommand (*i));
}
}
-
- if (in_command) {
- commit_reversible_command ();
- }
}
void
}
struct RegionSortByTime {
- bool operator() (const RegionView* a, const RegionView* b) {
- return a->region()->position() < b->region()->position();
- }
+ bool operator() (const RegionView* a, const RegionView* b) {
+ return a->region()->position() < b->region()->position();
+ }
};
void
if (front) {
(*i)->region()->trim_front (where);
- maybe_locate_with_edit_preroll ( where );
} else {
(*i)->region()->trim_end (where);
- maybe_locate_with_edit_preroll ( where );
}
_session->add_command (new StatefulDiffCommand ((*i)->region()));
if (forward) {
- next_region = playlist->find_next_region (region->first_frame(), Start, 1);
+ next_region = playlist->find_next_region (region->first_frame(), Start, 1);
- if (!next_region) {
- continue;
- }
+ if (!next_region) {
+ continue;
+ }
- region->trim_end((framepos_t) ( (next_region->first_frame() - 1) * speed));
- arv->region_changed (PropertyChange (ARDOUR::Properties::length));
+ region->trim_end((framepos_t) ( (next_region->first_frame() - 1) * speed));
+ arv->region_changed (PropertyChange (ARDOUR::Properties::length));
}
else {
- next_region = playlist->find_next_region (region->first_frame(), Start, 0);
+ next_region = playlist->find_next_region (region->first_frame(), Start, 0);
- if(!next_region){
- continue;
- }
+ if(!next_region){
+ continue;
+ }
- region->trim_front((framepos_t) ((next_region->last_frame() + 1) * speed));
+ region->trim_front((framepos_t) ((next_region->last_frame() + 1) * speed));
- arv->region_changed (ARDOUR::bounds_change);
+ arv->region_changed (ARDOUR::bounds_change);
}
if (!in_command) {
if (clicked_routeview->track()->has_external_redirects()) {
MessageDialog d (string_compose (_("<b>%1</b>\n\nThis track has at least one send/insert/return as part of its signal flow.\n\n"
- "Freezing will only process the signal as far as the first send/insert/return."),
- clicked_routeview->track()->name()), true, MESSAGE_INFO, BUTTONS_NONE, true);
+ "Freezing will only process the signal as far as the first send/insert/return."),
+ clicked_routeview->track()->name()), true, MESSAGE_INFO, BUTTONS_NONE, true);
d.add_button (_("Freeze anyway"), Gtk::RESPONSE_OK);
d.add_button (_("Don't freeze"), Gtk::RESPONSE_CANCEL);
}
}
- if ( op != Delete ) //"Delete" doesn't change copy/paste buf
+ if ( op != Delete ) { //"Delete" doesn't change copy/paste buf
cut_buffer->clear ();
+ }
if (entered_marker) {
if (did_edit) {
/* reset repeated paste state */
paste_count = 0;
- last_paste_pos = 0;
+ last_paste_pos = -1;
commit_reversible_command ();
}
const AutomationLine* line; ///< line this came from
boost::shared_ptr<Evoral::ControlList> copy; ///< copied events for the cut buffer
};
+
struct PointsSelectionPositionSorter {
bool operator() (ControlPoint* a, ControlPoint* b) {
return (*(a->model()))->when < (*(b->model()))->when;
}
};
+
/** Cut, copy or clear selected automation points.
* @param op Operation (Cut, Copy or Clear)
*/
/* user could select points in any order */
selection->points.sort(PointsSelectionPositionSorter ());
-
+
/* Go through all selected points, making an AutomationRecord for each distinct AutomationList */
for (PointSelection::iterator sel_point = selection->points.begin(); sel_point != selection->points.end(); ++sel_point) {
const AutomationLine& line = (*sel_point)->line();
}
/* Add all selected points to the relevant copy ControlLists */
- framepos_t start = std::numeric_limits<framepos_t>::max();
+ MusicFrame start (std::numeric_limits<framepos_t>::max(), 0);
for (PointSelection::iterator sel_point = selection->points.begin(); sel_point != selection->points.end(); ++sel_point) {
boost::shared_ptr<AutomationList> al = (*sel_point)->line().the_list();
AutomationList::const_iterator ctrl_evt = (*sel_point)->model ();
earliest = std::min(earliest, Evoral::Beats((*ctrl_evt)->when));
} else {
/* Update earliest session start time in frames */
- start = std::min(start, (*sel_point)->line().session_position(ctrl_evt));
+ start.frame = std::min(start.frame, (*sel_point)->line().session_position(ctrl_evt));
}
}
}
earliest.round_down_to_beat();
} else {
- if (start == std::numeric_limits<double>::max()) {
- start = 0; // Weird... don't offset
+ if (start.frame == std::numeric_limits<double>::max()) {
+ start.frame = 0; // Weird... don't offset
}
snap_to(start, RoundDownMaybe);
}
- const double line_offset = midi ? earliest.to_double() : start;
+ const double line_offset = midi ? earliest.to_double() : start.frame;
for (Lists::iterator i = lists.begin(); i != lists.end(); ++i) {
/* Correct this copy list so that it is relative to the earliest
start time, so relative ordering between points is preserved
boost::shared_ptr<AutomationList> al = line.the_list();
bool erase = true;
-
+
if (dynamic_cast<AudioRegionGainLine*> (&line)) {
/* removing of first and last gain point in region gain lines is prohibited*/
if (line.is_last_point (*(*sel_point)) || line.is_first_point (*(*sel_point))) {
}
struct lt_playlist {
- bool operator () (const PlaylistState& a, const PlaylistState& b) {
- return a.playlist < b.playlist;
- }
+ bool operator () (const PlaylistState& a, const PlaylistState& b) {
+ return a.playlist < b.playlist;
+ }
};
struct PlaylistMapping {
- TimeAxisView* tv;
- boost::shared_ptr<Playlist> pl;
+ TimeAxisView* tv;
+ boost::shared_ptr<Playlist> pl;
- PlaylistMapping (TimeAxisView* tvp) : tv (tvp) {}
+ PlaylistMapping (TimeAxisView* tvp) : tv (tvp) {}
};
/** Remove `clicked_regionview' */
boost::shared_ptr<Playlist> playlist = (*rl)->playlist();
- if (!playlist) {
+ if (!playlist) {
// is this check necessary?
continue;
- }
+ }
/* get_regions_from_selection_and_entered() guarantees that
the playlists involved are unique, so there is no need
void
Editor::paste (float times, bool from_context)
{
- DEBUG_TRACE (DEBUG::CutNPaste, "paste to preferred edit pos\n");
-
- paste_internal (get_preferred_edit_position (EDIT_IGNORE_NONE, from_context), times, get_grid_music_divisions (0));
+ DEBUG_TRACE (DEBUG::CutNPaste, "paste to preferred edit pos\n");
+ MusicFrame where (get_preferred_edit_position (EDIT_IGNORE_NONE, from_context), 0);
+ paste_internal (where.frame, times, 0);
}
void
Editor::mouse_paste ()
{
- framepos_t where;
+ MusicFrame where (0, 0);
bool ignored;
-
- if (!mouse_frame (where, ignored)) {
+ if (!mouse_frame (where.frame, ignored)) {
return;
}
snap_to (where);
- paste_internal (where, 1, get_grid_music_divisions (0));
+ paste_internal (where.frame, 1, where.division);
}
void
Editor::paste_internal (framepos_t position, float times, const int32_t sub_num)
{
- DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("apparent paste position is %1\n", position));
+ DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("apparent paste position is %1\n", position));
if (cut_buffer->empty(internal_editing())) {
return;
if (position == max_framepos) {
position = get_preferred_edit_position();
- DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("preferred edit position is %1\n", position));
+ DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("preferred edit position is %1\n", position));
}
if (position == last_paste_pos) {
TrackViewList ts;
if (!selection->tracks.empty()) {
/* If there is a track selection, paste into exactly those tracks and
- only those tracks. This allows the user to be explicit and override
- the below "do the reasonable thing" logic. */
+ * only those tracks. This allows the user to be explicit and override
+ * the below "do the reasonable thing" logic. */
ts = selection->tracks.filter_to_unique_playlists ();
sort_track_selection (ts);
} else {
/* Only one line copied, and one automation track selected. Do a
"greedy" paste from one automation type to another. */
- PasteContext ctx(paste_count, times, ItemCounts(), true);
- ts.front()->paste (position, *cut_buffer, ctx, sub_num);
+ PasteContext ctx(paste_count, times, ItemCounts(), true);
+ ts.front()->paste (position, *cut_buffer, ctx, sub_num);
} else {
}
if (in_command) {
- // now "move" range selection to after the current range selection
- framecnt_t distance = 0;
+ if (times == 1.0f) {
+ // now "move" range selection to after the current range selection
+ framecnt_t distance = 0;
- if (clicked_selection) {
- distance = selection->time[clicked_selection].end -
- selection->time[clicked_selection].start;
- } else {
- distance = selection->time.end_frame() - selection->time.start();
- }
-
- selection->move_time (distance);
+ if (clicked_selection) {
+ distance =
+ selection->time[clicked_selection].end - selection->time[clicked_selection].start;
+ } else {
+ distance = selection->time.end_frame () - selection->time.start ();
+ }
+ selection->move_time (distance);
+ }
commit_reversible_command ();
}
}
{
for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
ARDOUR::AutomationList::iterator j = (*i)->model ();
- (*j)->value = (*i)->line().the_list()->default_value ();
+ (*j)->value = (*i)->line().the_list()->descriptor ().normal;
}
}
if (Config->get_verify_remove_last_capture()) {
prompt = _("Do you really want to destroy the last capture?"
- "\n(This is destructive and cannot be undone)");
+ "\n(This is destructive and cannot be undone)");
choices.push_back (_("No, do nothing."));
choices.push_back (_("Yes, destroy it."));
- Gtkmm2ext::Choice prompter (_("Destroy last capture"), prompt, choices);
+ Choice prompter (_("Destroy last capture"), prompt, choices);
if (prompter.run () == 1) {
_session->remove_last_capture ();
}
}
+void
+Editor::reset_region_gain ()
+{
+ RegionSelection rs = get_regions_from_selection_and_entered ();
+
+ if (!_session || rs.empty()) {
+ return;
+ }
+
+ bool in_command = false;
+
+ for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) {
+ AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
+ if (!arv) {
+ continue;
+ }
+
+ arv->region()->clear_changes ();
+
+ arv->audio_region()->set_scale_amplitude (1.0f);
+
+ if (!in_command) {
+ begin_reversible_command ("reset region gain");
+ in_command = true;
+ }
+ _session->add_command (new StatefulDiffCommand (arv->region()));
+ }
+
+ if (in_command) {
+ commit_reversible_command ();
+ }
+}
void
Editor::reverse_region ()
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*> (*i);
- if (arv) {
+ if (arv) {
audio_only.push_back (arv);
}
}
MidiRegionView* first = dynamic_cast<MidiRegionView*> (rs.front ());
Evoral::PatchChange<Evoral::Beats> empty (Evoral::Beats(), 0, 0, 0);
- PatchChangeDialog d (0, _session, empty, first->instrument_info(), Gtk::Stock::ADD);
+ PatchChangeDialog d (0, _session, empty, first->instrument_info(), Gtk::Stock::ADD);
if (d.run() == RESPONSE_CANCEL) {
return;
return;
}
- begin_reversible_command (_("region lock style"));
+ Glib::RefPtr<ToggleAction> a = Glib::RefPtr<ToggleAction>::cast_dynamic (_region_actions->get_action("toggle-region-lock-style"));
+ vector<Widget*> proxies = a->get_proxies();
+ Gtk::CheckMenuItem* cmi = dynamic_cast<Gtk::CheckMenuItem*> (proxies.front());
+
+ assert (cmi);
+
+ begin_reversible_command (_("toggle region lock style"));
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
(*i)->region()->clear_changes ();
- PositionLockStyle const ns = (*i)->region()->position_lock_style() == AudioTime ? MusicTime : AudioTime;
+ PositionLockStyle const ns = ((*i)->region()->position_lock_style() == AudioTime && !cmi->get_inconsistent()) ? MusicTime : AudioTime;
(*i)->region()->set_position_lock_style (ns);
_session->add_command (new StatefulDiffCommand ((*i)->region()));
}
boost::shared_ptr<ControlList> cl (new ControlList);
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
- RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView *>(*i);
+ StripableTimeAxisView *stav = dynamic_cast<StripableTimeAxisView *>(*i);
- if (!rtav) {
+ if (!stav || !stav->stripable()->solo_control()) {
continue;
}
if (first) {
- new_state = !rtav->route()->soloed ();
+ new_state = !stav->stripable()->solo_control()->soloed ();
first = false;
}
- cl->push_back (rtav->route()->solo_control());
+ cl->push_back (stav->stripable()->solo_control());
}
_session->set_controls (cl, new_state ? 1.0 : 0.0, Controllable::UseGroup);
{
bool new_state = false;
bool first = true;
- boost::shared_ptr<RouteList> rl (new RouteList);
+ boost::shared_ptr<ControlList> cl (new ControlList);
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
- RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView *>(*i);
+ StripableTimeAxisView *stav = dynamic_cast<StripableTimeAxisView *>(*i);
- if (!rtav) {
+ if (!stav || !stav->stripable()->mute_control()) {
continue;
}
if (first) {
- new_state = !rtav->route()->muted();
+ new_state = !stav->stripable()->mute_control()->muted();
first = false;
}
- rl->push_back (rtav->route());
+ cl->push_back (stav->stripable()->mute_control());
}
- _session->set_controls (route_list_to_control_list (rl, &Stripable::mute_control), new_state, Controllable::UseGroup);
+ _session->set_controls (cl, new_state, Controllable::UseGroup);
}
void
void
Editor::set_edit_point ()
{
- framepos_t where;
bool ignored;
+ MusicFrame where (0, 0);
- if (!mouse_frame (where, ignored)) {
+ if (!mouse_frame (where.frame, ignored)) {
return;
}
if (selection->markers.empty()) {
- mouse_add_new_marker (where);
+ mouse_add_new_marker (where.frame);
} else {
bool ignored;
Location* loc = find_location_from_marker (selection->markers.front(), ignored);
if (loc) {
- loc->move_to (where);
+ loc->move_to (where.frame, where.division);
}
}
}
if (entered_marker) {
_session->request_locate (entered_marker->position(), _session->transport_rolling());
} else {
- framepos_t where;
+ MusicFrame where (0, 0);
bool ignored;
- if (!mouse_frame (where, ignored)) {
+ if (!mouse_frame (where.frame, ignored)) {
return;
}
snap_to (where);
if (_session) {
- _session->request_locate (where, _session->transport_rolling());
+ _session->request_locate (where.frame, _session->transport_rolling());
}
}
- if (UIConfiguration::instance().get_follow_edits() && (!_session || !_session->config.get_external_sync())) {
- cancel_time_selection();
- }
+//not sure what this was for; remove it for now.
+// if (UIConfiguration::instance().get_follow_edits() && (!_session || !_session->config.get_external_sync())) {
+// cancel_time_selection();
+// }
+
}
void
if (current_mouse_mode() == MouseObject) { //don't try this for Internal Edit, Stretch, Draw, etc.
RegionSelection rs = get_regions_from_selection_and_edit_point ();
-
- framepos_t where = get_preferred_edit_position ();
+ const framepos_t pos = get_preferred_edit_position();
+ const int32_t division = get_grid_music_divisions (0);
+ MusicFrame where (pos, division);
if (rs.empty()) {
return;
}
- if (snap_musical()) {
- split_regions_at (where, rs, get_grid_music_divisions (0));
- } else {
- split_regions_at (where, rs, 0);
- }
+ split_regions_at (where, rs);
+
}
}
void
-Editor::select_next_route()
+Editor::select_next_stripable (bool routes_only)
{
if (selection->tracks.empty()) {
selection->set (track_views.front());
TimeAxisView* current = selection->tracks.front();
- RouteUI *rui;
+ bool valid;
do {
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
}
}
- rui = dynamic_cast<RouteUI *>(current);
+ if (routes_only) {
+ RouteUI* rui = dynamic_cast<RouteUI *>(current);
+ valid = rui && rui->route()->active();
+ } else {
+ valid = 0 != current->stripable ().get();
+ }
- } while (current->hidden() || (rui == NULL) || !rui->route()->active());
+ } while (current->hidden() || !valid);
selection->set (current);
}
void
-Editor::select_prev_route()
+Editor::select_prev_stripable (bool routes_only)
{
if (selection->tracks.empty()) {
selection->set (track_views.front());
TimeAxisView* current = selection->tracks.front();
- RouteUI *rui;
+ bool valid;
do {
for (TrackViewList::reverse_iterator i = track_views.rbegin(); i != track_views.rend(); ++i) {
break;
}
}
- rui = dynamic_cast<RouteUI *>(current);
+ if (routes_only) {
+ RouteUI* rui = dynamic_cast<RouteUI *>(current);
+ valid = rui && rui->route()->active();
+ } else {
+ valid = 0 != current->stripable ().get();
+ }
- } while (current->hidden() || (rui == NULL) || !rui->route()->active());
+ } while (current->hidden() || !valid);
selection->set (current);
set_punch_range (tpl->start(), now, _("Auto Punch In/Out"));
_session->config.set_punch_out(true);
}
- } else {
+ } else {
if (_session->config.get_punch_out()) {
_session->config.set_punch_out(false);
}
{
if (_session) {
- framepos_t start = 0;
+ MusicFrame start (0, 0);
framepos_t end = max_framepos;
//use the existing punch end, if any
}
if ((_edit_point == EditAtPlayhead) && _session->transport_rolling()) {
- start = _session->audible_frame();
+ start.frame = _session->audible_frame();
} else {
- start = get_preferred_edit_position();
+ start.frame = get_preferred_edit_position();
}
//snap the selection start/end
snap_to(start);
//if there's not already a sensible selection endpoint, go "forever"
- if ( start > end ) {
+ if (start.frame > end ) {
end = max_framepos;
}
- set_punch_range (start, end, _("set punch start from EP"));
+ set_punch_range (start.frame, end, _("set punch start from EP"));
}
}
if (_session) {
framepos_t start = 0;
- framepos_t end = max_framepos;
+ MusicFrame end (max_framepos, 0);
//use the existing punch start, if any
Location* tpl = transport_punch_location();
}
if ((_edit_point == EditAtPlayhead) && _session->transport_rolling()) {
- end = _session->audible_frame();
+ end.frame = _session->audible_frame();
} else {
- end = get_preferred_edit_position();
+ end.frame = get_preferred_edit_position();
}
//snap the selection start/end
- snap_to(end);
+ snap_to (end);
- set_punch_range (start, end, _("set punch end from EP"));
+ set_punch_range (start, end.frame, _("set punch end from EP"));
}
}
{
if (_session) {
- framepos_t start = 0;
+ MusicFrame start (0, 0);
framepos_t end = max_framepos;
//use the existing loop end, if any
}
if ((_edit_point == EditAtPlayhead) && _session->transport_rolling()) {
- start = _session->audible_frame();
+ start.frame = _session->audible_frame();
} else {
- start = get_preferred_edit_position();
+ start.frame = get_preferred_edit_position();
}
//snap the selection start/end
- snap_to(start);
+ snap_to (start);
//if there's not already a sensible selection endpoint, go "forever"
- if ( start > end ) {
+ if (start.frame > end ) {
end = max_framepos;
}
- set_loop_range (start, end, _("set loop start from EP"));
+ set_loop_range (start.frame, end, _("set loop start from EP"));
}
}
if (_session) {
framepos_t start = 0;
- framepos_t end = max_framepos;
+ MusicFrame end (max_framepos, 0);
//use the existing loop start, if any
Location* tpl = transport_loop_location();
}
if ((_edit_point == EditAtPlayhead) && _session->transport_rolling()) {
- end = _session->audible_frame();
+ end.frame = _session->audible_frame();
} else {
- end = get_preferred_edit_position();
+ end.frame = get_preferred_edit_position();
}
//snap the selection start/end
snap_to(end);
- set_loop_range (start, end, _("set loop end from EP"));
+ set_loop_range (start, end.frame, _("set loop end from EP"));
}
}
XMLNode& before (_session->tempo_map().get_state());
if (do_global) {
- _session->tempo_map().change_initial_tempo (beats_per_minute, t.note_type());
+ _session->tempo_map().change_initial_tempo (beats_per_minute, t.note_type(), t.end_note_types_per_minute());
} else if (t.frame() == start) {
- _session->tempo_map().change_existing_tempo_at (start, beats_per_minute, t.note_type());
+ _session->tempo_map().change_existing_tempo_at (start, beats_per_minute, t.note_type(), t.end_note_types_per_minute());
} else {
+ /* constant tempo */
const Tempo tempo (beats_per_minute, t.note_type());
- _session->tempo_map().add_tempo (tempo, 0.0, start, TempoSection::Constant, AudioTime);
+ _session->tempo_map().add_tempo (tempo, 0.0, start, AudioTime);
}
XMLNode& after (_session->tempo_map().get_state());
used_playlists.push_back(pl);
pl->freeze();
}
+ (*r)->region()->clear_changes ();
- framepos_t start_frame = (*r)->region()->first_frame ();
- snap_to (start_frame);
- (*r)->region()->set_position (start_frame);
+ MusicFrame start ((*r)->region()->first_frame (), 0);
+ snap_to (start);
+ (*r)->region()->set_position (start.frame, start.division);
+ _session->add_command(new StatefulDiffCommand ((*r)->region()));
}
while (used_playlists.size() > 0) {
continue;
}
+ (*r)->region()->clear_changes ();
(*r)->region()->trim_front( (position - pull_back_frames));
+
+ last_region->clear_changes ();
last_region->trim_end( (position - pull_back_frames + crossfade_len));
- last_region = (*r)->region();
+ _session->add_command (new StatefulDiffCommand ((*r)->region()));
+ _session->add_command (new StatefulDiffCommand (last_region));
+ last_region = (*r)->region();
idx++;
}
return;
}
- framepos_t pos = playhead_cursor->current_frame ();
- if (pos < max_framepos - 1) {
- pos += 2;
- snap_to_internal (pos, RoundUpAlways, false);
- _session->request_locate (pos);
+ MusicFrame pos (playhead_cursor->current_frame (), 0);
+
+ if (pos.frame < max_framepos - 1) {
+ pos.frame += 2;
+ snap_to_internal (pos, RoundUpAlways, false, true);
+ _session->request_locate (pos.frame);
}
}
return;
}
- framepos_t pos = playhead_cursor->current_frame ();
- if (pos > 2) {
- pos -= 2;
- snap_to_internal (pos, RoundDownAlways, false);
- _session->request_locate (pos);
+ MusicFrame pos (playhead_cursor->current_frame (), 0);
+
+ if (pos.frame > 2) {
+ pos.frame -= 2;
+ snap_to_internal (pos, RoundDownAlways, false, true);
+ _session->request_locate (pos.frame);
}
}
string prompt;
int ntracks = 0;
int nbusses = 0;
+ int nvcas = 0;
const char* trackstr;
const char* busstr;
+ const char* vcastr;
vector<boost::shared_ptr<Route> > routes;
+ vector<boost::shared_ptr<VCA> > vcas;
bool special_bus = false;
for (TrackSelection::iterator x = ts.begin(); x != ts.end(); ++x) {
+ VCATimeAxisView* vtv = dynamic_cast<VCATimeAxisView*> (*x);
+ if (vtv) {
+ vcas.push_back (vtv->vca());
+ ++nvcas;
+ continue;
+ }
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*x);
if (!rtv) {
continue;
}
if (rtv->is_track()) {
- ntracks++;
+ ++ntracks;
} else {
- nbusses++;
+ ++nbusses;
}
routes.push_back (rtv->_route);
return;
}
- if (ntracks + nbusses == 0) {
+ if (ntracks + nbusses + nvcas == 0) {
return;
}
+ string title;
+
trackstr = P_("track", "tracks", ntracks);
busstr = P_("bus", "busses", nbusses);
+ vcastr = P_("VCA", "VCAs", nvcas);
- if (ntracks) {
- if (nbusses) {
- prompt = string_compose (_("Do you really want to remove %1 %2 and %3 %4?\n"
- "(You may also lose the playlists associated with the %2)\n\n"
- "This action cannot be undone, and the session file will be overwritten!"),
- ntracks, trackstr, nbusses, busstr);
- } else {
- prompt = string_compose (_("Do you really want to remove %1 %2?\n"
- "(You may also lose the playlists associated with the %2)\n\n"
- "This action cannot be undone, and the session file will be overwritten!"),
- ntracks, trackstr);
- }
- } else if (nbusses) {
- prompt = string_compose (_("Do you really want to remove %1 %2?\n\n"
- "This action cannot be undone, and the session file will be overwritten"),
- nbusses, busstr);
+ if (ntracks > 0 && nbusses > 0 && nvcas > 0) {
+ title = _("Remove various strips");
+ prompt = string_compose (_("Do you really want to remove %1 %2, %3 %4 and %5 %6?"),
+ ntracks, trackstr, nbusses, busstr, nvcas, vcastr);
+ }
+ else if (ntracks > 0 && nbusses > 0) {
+ title = string_compose (_("Remove %1 and %2"), trackstr, busstr);
+ prompt = string_compose (_("Do you really want to remove %1 %2 and %3 %4?"),
+ ntracks, trackstr, nbusses, busstr);
+ }
+ else if (ntracks > 0 && nvcas > 0) {
+ title = string_compose (_("Remove %1 and %2"), trackstr, vcastr);
+ prompt = string_compose (_("Do you really want to remove %1 %2 and %3 %4?"),
+ ntracks, trackstr, nvcas, vcastr);
+ }
+ else if (nbusses > 0 && nvcas > 0) {
+ title = string_compose (_("Remove %1 and %2"), busstr, vcastr);
+ prompt = string_compose (_("Do you really want to remove %1 %2 and %3 %4?"),
+ nbusses, busstr, nvcas, vcastr);
+ }
+ else if (ntracks > 0) {
+ title = string_compose (_("Remove %1"), trackstr);
+ prompt = string_compose (_("Do you really want to remove %1 %2?"),
+ ntracks, trackstr);
+ }
+ else if (nbusses > 0) {
+ title = string_compose (_("Remove %1"), busstr);
+ prompt = string_compose (_("Do you really want to remove %1 %2?"),
+ nbusses, busstr);
+ }
+ else if (nvcas > 0) {
+ title = string_compose (_("Remove %1"), vcastr);
+ prompt = string_compose (_("Do you really want to remove %1 %2?"),
+ nvcas, vcastr);
+ }
+ else {
+ assert (0);
}
+ if (ntracks > 0) {
+ prompt += "\n" + string_compose ("(You may also lose the playlists associated with the %1)", trackstr) + "\n";
+ }
+
+ prompt += "\n" + string(_("This action cannot be undone, and the session file will be overwritten!"));
+
choices.push_back (_("No, do nothing."));
- if (ntracks + nbusses > 1) {
+ if (ntracks + nbusses + nvcas > 1) {
choices.push_back (_("Yes, remove them."));
} else {
choices.push_back (_("Yes, remove it."));
}
- string title;
- if (ntracks) {
- title = string_compose (_("Remove %1"), trackstr);
- } else {
- title = string_compose (_("Remove %1"), busstr);
- }
-
Choice prompter (title, prompt, choices);
if (prompter.run () != 1) {
return;
}
+ if (current_mixer_strip && routes.size () > 1 && std::find (routes.begin(), routes.end(), current_mixer_strip->route()) != routes.end ()) {
+ /* Route deletion calls Editor::timeaxisview_deleted() iteratively (for each deleted
+ * route). If the deleted route is currently displayed in the Editor-Mixer (highly
+ * likely because deletion requires selection) this will call
+ * Editor::set_selected_mixer_strip () which is expensive ( MixerStrip::set_route() ).
+ * It's likewise likely that the route that has just been displayed in the
+ * Editor-Mixer will be next in line for deletion.
+ *
+ * So simply switch to the master-bus (if present)
+ */
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+ if ((*i)->stripable ()->is_master ()) {
+ set_selected_mixer_strip (*(*i));
+ break;
+ }
+ }
+ }
+
{
+ PresentationInfo::ChangeSuspender cs;
DisplaySuspender ds;
+
boost::shared_ptr<RouteList> rl (new RouteList);
for (vector<boost::shared_ptr<Route> >::iterator x = routes.begin(); x != routes.end(); ++x) {
rl->push_back (*x);
}
_session->remove_routes (rl);
+
+ for (vector<boost::shared_ptr<VCA> >::iterator x = vcas.begin(); x != vcas.end(); ++x) {
+ _session->vca_manager().remove_vca (*x);
+ }
+
}
/* TrackSelection and RouteList leave scope,
* destructors are called,
}
insert_time (
- get_preferred_edit_position (EDIT_IGNORE_MOUSE),
+ d.position(),
d.distance(),
d.intersected_region_action (),
d.all_playlists(),
(*i)->clear_changes ();
(*i)->clear_owned_changes ();
+ if (!in_command) {
+ begin_reversible_command (_("insert time"));
+ in_command = true;
+ }
+
if (opt == SplitIntersected) {
/* non musical split */
- (*i)->split (pos, 0);
+ (*i)->split (MusicFrame (pos, 0));
}
(*i)->shift (pos, frames, (opt == MoveIntersected), ignore_music_glue);
- if (!in_command) {
- begin_reversible_command (_("insert time"));
- in_command = true;
- }
vector<Command*> cmds;
(*i)->rdiff (cmds);
_session->add_commands (cmds);
/* markers */
if (markers_too) {
bool moved = false;
+ const int32_t divisions = get_grid_music_divisions (0);
XMLNode& before (_session->locations()->get_state());
Locations::LocationList copy (_session->locations()->list());
if ((*i)->start() >= pos) {
// move end first, in case we're moving by more than the length of the range
if (!(*i)->is_mark()) {
- (*i)->set_end ((*i)->end() + frames);
+ (*i)->set_end ((*i)->end() + frames, false, true, divisions);
}
- (*i)->set_start ((*i)->start() + frames);
+ (*i)->set_start ((*i)->start() + frames, false, true, divisions);
moved = true;
}
return;
}
- framepos_t pos = get_preferred_edit_position (EDIT_IGNORE_MOUSE);
InsertRemoveTimeDialog d (*this, true);
int response = d.run ();
}
remove_time (
- pos,
+ d.position(),
distance,
SplitIntersected,
d.move_glued(),
void
Editor::remove_time (framepos_t pos, framecnt_t frames, InsertTimeOption opt,
- bool ignore_music_glue, bool markers_too, bool glued_markers_too, bool locked_markers_too, bool tempo_too)
+ bool ignore_music_glue, bool markers_too, bool glued_markers_too, bool locked_markers_too, bool tempo_too)
{
if (Config->get_edit_mode() == Lock) {
error << (_("Cannot insert or delete time when in Lock edit.")) << endmsg;
XMLNode &before = pl->get_state();
+ if (!in_command) {
+ begin_reversible_command (_("remove time"));
+ in_command = true;
+ }
+
std::list<AudioRange> rl;
AudioRange ar(pos, pos+frames, 0);
rl.push_back(ar);
pl->cut (rl);
pl->shift (pos, -frames, true, ignore_music_glue);
- if (!in_command) {
- begin_reversible_command (_("remove time"));
- in_command = true;
- }
XMLNode &after = pl->get_state();
_session->add_command (new MementoCommand<Playlist> (*pl, &before, &after));
}
}
+ const int32_t divisions = get_grid_music_divisions (0);
std::list<Location*> loc_kill_list;
/* markers */
// if we're removing more time than the length of the range
if ((*i)->start() >= pos && (*i)->start() < pos+frames) {
// start is within cut
- (*i)->set_start (pos); // bring the start marker to the beginning of the cut
+ (*i)->set_start (pos, false, true,divisions); // bring the start marker to the beginning of the cut
moved = true;
} else if ((*i)->start() >= pos+frames) {
// start (and thus entire range) lies beyond end of cut
- (*i)->set_start ((*i)->start() - frames); // slip the start marker back
+ (*i)->set_start ((*i)->start() - frames, false, true, divisions); // slip the start marker back
moved = true;
}
if ((*i)->end() >= pos && (*i)->end() < pos+frames) {
// end is inside cut
- (*i)->set_end (pos); // bring the end to the cut
+ (*i)->set_end (pos, false, true, divisions); // bring the end to the cut
moved = true;
} else if ((*i)->end() >= pos+frames) {
// end is beyond end of cut
- (*i)->set_end ((*i)->end() - frames); // slip the end marker back
+ (*i)->set_end ((*i)->end() - frames, false, true, divisions); // slip the end marker back
moved = true;
}
loc_kill_list.push_back(*i);
moved = true;
} else if ((*i)->start() >= pos) {
- (*i)->set_start ((*i)->start() -frames);
+ (*i)->set_start ((*i)->start() -frames, false, true, divisions);
moved = true;
}
void
Editor::fit_selection ()
{
- if (!selection->tracks.empty()) {
- fit_tracks (selection->tracks);
- } else {
- TrackViewList tvl;
-
- /* no selected tracks - use tracks with selected regions */
+ if (!selection->tracks.empty()) {
+ fit_tracks (selection->tracks);
+ } else {
+ TrackViewList tvl;
- if (!selection->regions.empty()) {
- for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
- tvl.push_back (&(*r)->get_time_axis_view ());
- }
+ /* no selected tracks - use tracks with selected regions */
- if (!tvl.empty()) {
- fit_tracks (tvl);
- }
- } else if (internal_editing()) {
- /* no selected tracks, or regions, but in internal edit mode, so follow the mouse and use
- the entered track
- */
- if (entered_track) {
- tvl.push_back (entered_track);
- fit_tracks (tvl);
- }
- }
- }
+ if (!selection->regions.empty()) {
+ for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
+ tvl.push_back (&(*r)->get_time_axis_view ());
+ }
+ if (!tvl.empty()) {
+ fit_tracks (tvl);
+ }
+ } else if (internal_editing()) {
+ /* no selected tracks, or regions, but in internal edit mode, so follow the mouse and use
+ * the entered track
+ */
+ if (entered_track) {
+ tvl.push_back (entered_track);
+ fit_tracks (tvl);
+ }
+ }
+ }
}
void
}
/* compute the per-track height from:
-
- total canvas visible height -
- height that will be taken by visible children of selected
- tracks - height of the ruler/hscroll area
- */
+ *
+ * total canvas visible height
+ * - height that will be taken by visible children of selected tracks
+ * - height of the ruler/hscroll area
+ */
uint32_t h = (uint32_t) floor ((trackviews_height() - child_heights) / visible_tracks);
double first_y_pos = DBL_MAX;
void
Editor::cancel_visual_state_op (uint32_t n)
{
- goto_visual_state (n);
+ goto_visual_state (n);
}
void