#include "editor_regions.h"
#include "quantize_dialog.h"
#include "interthread_progress_window.h"
+#include "insert_time_dialog.h"
#include "i18n.h"
boost::shared_ptr<Playlist> pl = (*a)->region()->playlist();
if (!pl) {
- cerr << "region " << (*a)->region()->name() << " has no playlist!\n";
a = tmp;
continue;
}
}
if (pl) {
- pl->clear_history ();
+ pl->clear_changes ();
pl->split_region ((*a)->region(), where);
_session->add_command (new StatefulDiffCommand (pl));
}
distance = next_distance;
}
- r->clear_history ();
+ r->clear_changes ();
r->set_position (r->position() + distance, this);
_session->add_command (new StatefulDiffCommand (r));
}
distance = next_distance;
}
- r->clear_history ();
+ r->clear_changes ();
if (r->position() > distance) {
r->set_position (r->position() - distance, this);
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
boost::shared_ptr<Region> r ((*i)->region());
- r->clear_history ();
+ r->clear_changes ();
r->set_position (r->position() + distance, this);
_session->add_command(new StatefulDiffCommand (r));
}
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
boost::shared_ptr<Region> r ((*i)->region());
- r->clear_history ();
+ r->clear_changes ();
if (r->position() > distance) {
r->set_position (r->position() - distance, this);
void
Editor::build_region_boundary_cache ()
{
- nframes64_t pos = 0;
+ framepos_t pos = 0;
vector<RegionPoint> interesting_points;
boost::shared_ptr<Region> r;
TrackViewList tracks;
while (pos < _session->current_end_frame() && !at_end) {
- nframes64_t rpos;
- nframes64_t lpos = max_frames;
+ framepos_t rpos;
+ framepos_t lpos = max_frames;
for (vector<RegionPoint>::iterator p = interesting_points.begin(); p != interesting_points.end(); ++p) {
case SyncPoint:
rpos = r->sync_position ();
- //r->adjust_to_sync (r->first_frame());
break;
default:
to sort later.
*/
- vector<nframes64_t>::iterator ri;
+ vector<framepos_t>::iterator ri;
for (ri = region_boundary_cache.begin(); ri != region_boundary_cache.end(); ++ri) {
if (*ri == rpos) {
/* finally sort to be sure that the order is correct */
sort (region_boundary_cache.begin(), region_boundary_cache.end());
+
+ cerr << "RBC contains " << region_boundary_cache.size() << endl;
+
+ for (vector<framepos_t>::iterator x = region_boundary_cache.begin(); x != region_boundary_cache.end(); ++x) {
+ cerr << "Region boundary @ " << *x << endl;
+ }
}
boost::shared_ptr<Region>
-Editor::find_next_region (nframes64_t frame, RegionPoint point, int32_t dir, TrackViewList& tracks, TimeAxisView **ontrack)
+Editor::find_next_region (framepos_t frame, RegionPoint point, int32_t dir, TrackViewList& tracks, TimeAxisView **ontrack)
{
TrackViewList::iterator i;
nframes64_t closest = max_frames;
boost::shared_ptr<Region> ret;
- nframes64_t rpos = 0;
+ framepos_t rpos = 0;
float track_speed;
- nframes64_t track_frame;
+ framepos_t track_frame;
RouteTimeAxisView *rtav;
for (i = tracks.begin(); i != tracks.end(); ++i) {
- nframes64_t distance;
+ framecnt_t distance;
boost::shared_ptr<Region> r;
track_speed = 1.0f;
case SyncPoint:
rpos = r->sync_position ();
- // r->adjust_to_sync (r->first_frame());
break;
}
return ret;
}
-nframes64_t
-Editor::find_next_region_boundary (nframes64_t pos, int32_t dir, const TrackViewList& tracks)
+framepos_t
+Editor::find_next_region_boundary (framepos_t pos, int32_t dir, const TrackViewList& tracks)
{
- nframes64_t distance = max_frames;
- nframes64_t current_nearest = -1;
-
+ framecnt_t distance = max_frames;
+ framepos_t current_nearest = -1;
for (TrackViewList::const_iterator i = tracks.begin(); i != tracks.end(); ++i) {
- nframes64_t contender;
- nframes64_t d;
-
+ framepos_t contender;
+ framecnt_t d;
+
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
if (!rtv) {
return current_nearest;
}
-nframes64_t
-Editor::get_region_boundary (nframes64_t pos, int32_t dir, bool with_selection, bool only_onscreen)
+framepos_t
+Editor::get_region_boundary (framepos_t pos, int32_t dir, bool with_selection, bool only_onscreen)
{
- nframes64_t target;
+ framepos_t target;
TrackViewList tvl;
if (with_selection && Config->get_region_boundaries_from_selected_tracks()) {
case SyncPoint:
pos = r->sync_position ();
- // r->adjust_to_sync (r->first_frame());
break;
}
nframes64_t end = selection->time[clicked_selection].end;
_session->locations()->next_available_name(rangename,"selection");
- Location *location = new Location (start, end, rangename, Location::IsRangeMarker);
+ Location *location = new Location (*_session, start, end, rangename, Location::IsRangeMarker);
_session->begin_reversible_command (_("add marker"));
XMLNode &before = _session->locations()->get_state();
if (!choose_new_marker_name(markername)) {
return;
}
- Location *location = new Location (where, where, markername, Location::IsMark);
+ Location *location = new Location (*_session, where, where, markername, Location::IsMark);
_session->begin_reversible_command (_("add marker"));
XMLNode &before = _session->locations()->get_state();
_session->locations()->add (location, true);
_session->begin_reversible_command (rs.size () > 1 ? _("add markers") : _("add marker"));
XMLNode &before = _session->locations()->get_state();
- cerr << "Add locations\n";
-
for (RegionSelection::iterator i = rs.begin (); i != rs.end (); ++i) {
boost::shared_ptr<Region> region = (*i)->region ();
- Location *location = new Location (region->position(), region->last_frame(), region->name(), Location::IsRangeMarker);
+ Location *location = new Location (*_session, region->position(), region->last_frame(), region->name(), Location::IsRangeMarker);
_session->locations()->add (location, true);
}
return;
}
- cerr << "Add location\n";
-
// single range spanning all selected
- Location *location = new Location (rs.start(), rs.end_frame(), markername, Location::IsRangeMarker);
+ Location *location = new Location (*_session, rs.start(), rs.end_frame(), markername, Location::IsRangeMarker);
_session->locations()->add (location, true);
XMLNode &after = _session->locations()->get_state();
if (!choose_new_marker_name(markername)) {
return;
}
- _session->locations()->add (new Location (pos, 0, markername, Location::IsMark), true);
+ _session->locations()->add (new Location (*_session, pos, 0, markername, Location::IsMark), true);
}
void
snap_to (where);
begin_reversible_command (_("insert dragged region"));
- playlist->clear_history ();
+ playlist->clear_changes ();
playlist->add_region (RegionFactory::create (region), where, 1.0);
_session->add_command(new StatefulDiffCommand (playlist));
commit_reversible_command ();
}
begin_reversible_command (_("insert region"));
- playlist->clear_history ();
+ playlist->clear_changes ();
playlist->add_region ((RegionFactory::create (region)), get_preferred_edit_position(), times);
_session->add_command(new StatefulDiffCommand (playlist));
commit_reversible_command ();
if ((playlist = rtv->playlist()) != 0) {
- playlist->clear_history ();
+ playlist->clear_changes ();
/* XXX need to consider musical time selections here at some point */
sigc::connection c = rtv->view()->RegionViewAdded.connect (
sigc::mem_fun(*this, &Editor::collect_new_region_view));
+
latest_regionviews.clear ();
playlist->partition ((nframes64_t)((*t).start * speed),
- (nframes64_t)((*t).end * speed), true);
+ (nframes64_t)((*t).end * speed), false);
c.disconnect ();
begin_reversible_command (_("separate"));
in_command = true;
}
+
+ /* pick up changes to existing regions */
+
+ vector<Command*> cmds;
+ playlist->rdiff (cmds);
+ _session->add_commands (cmds);
+
+ /* pick up changes to the playlist itself (adds/removes)
+ */
_session->add_command(new StatefulDiffCommand (playlist));
}
}
}
+struct PlaylistState {
+ boost::shared_ptr<Playlist> playlist;
+ XMLNode* before;
+};
+
/** Take tracks from get_tracks_for_range_action and cut any regions
* on those tracks so that the tracks are empty over the time
* selection.
separate_regions_between (ts);
}
+/** Separate regions under the selected region */
+void
+Editor::separate_under_selected_regions ()
+{
+ RegionSelection rs;
+ get_regions_for_action (rs);
+
+ vector<PlaylistState> playlists;
+
+ if (!_session) {
+ return;
+ }
+
+ if (rs.empty()) {
+ return;
+ }
+
+ begin_reversible_command (_("separate region under"));
+
+ list<boost::shared_ptr<Region> > regions_to_remove;
+
+ for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
+ // we can't just remove the region(s) in this loop because
+ // this removes them from the RegionSelection, and they thus
+ // disappear from underneath the iterator, and the ++i above
+ // SEGVs in a puzzling fashion.
+
+ // so, first iterate over the regions to be removed from rs and
+ // add them to the regions_to_remove list, and then
+ // iterate over the list to actually remove them.
+
+ regions_to_remove.push_back ((*i)->region());
+ }
+
+ for (list<boost::shared_ptr<Region> >::iterator rl = regions_to_remove.begin(); rl != regions_to_remove.end(); ++rl) {
+
+ boost::shared_ptr<Playlist> playlist = (*rl)->playlist();
+
+ if (!playlist) {
+ // is this check necessary?
+ continue;
+ }
+
+ vector<PlaylistState>::iterator i;
+
+ //only take state if this is a new playlist.
+ for (i = playlists.begin(); i != playlists.end(); ++i) {
+ if ((*i).playlist == playlist) {
+ break;
+ }
+ }
+
+ if (i == playlists.end()) {
+
+ PlaylistState before;
+ before.playlist = playlist;
+ before.before = &playlist->get_state();
+
+ playlist->freeze ();
+ playlists.push_back(before);
+ }
+
+ //Partition on the region bounds
+ playlist->partition ((*rl)->first_frame() - 1, (*rl)->last_frame() + 1, true);
+
+ //Re-add region that was just removed due to the partition operation
+ playlist->add_region( (*rl), (*rl)->first_frame() );
+ }
+
+ vector<PlaylistState>::iterator pl;
+
+ for (pl = playlists.begin(); pl != playlists.end(); ++pl) {
+ (*pl).playlist->thaw ();
+ _session->add_command(new MementoCommand<Playlist>(*(*pl).playlist, (*pl).before, &(*pl).playlist->get_state()));
+ }
+
+ commit_reversible_command ();
+}
+
void
Editor::crop_region_to_selection ()
{
the_end = min (end, the_end);
cnt = the_end - the_start + 1;
- region->clear_history ();
+ region->clear_changes ();
region->trim_to (the_start, cnt, this);
_session->add_command (new StatefulDiffCommand (region));
}
return;
}
- pl->clear_history ();
+ pl->clear_changes ();
pl->add_region (RegionFactory::create (region), region->last_frame(), times);
_session->add_command (new StatefulDiffCommand (pl));
}
continue;
}
- playlist->clear_history ();
+ playlist->clear_changes ();
playlist->add_region (RegionFactory::create (region), start, times);
_session->add_command (new StatefulDiffCommand (playlist));
}
in_command = true;
}
- region->clear_history ();
+ region->clear_changes ();
region->set_sync_position (where);
_session->add_command(new StatefulDiffCommand (region));
}
begin_reversible_command (_("remove sync"));
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
- (*i)->region()->clear_history ();
+ (*i)->region()->clear_changes ();
(*i)->region()->clear_sync_position ();
_session->add_command(new StatefulDiffCommand ((*i)->region()));
}
begin_reversible_command (_("naturalize"));
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
- (*i)->region()->clear_history ();
+ (*i)->region()->clear_changes ();
(*i)->region()->move_to_natural_position (this);
_session->add_command (new StatefulDiffCommand ((*i)->region()));
}
/* move first one specially */
- r->clear_history ();
+ r->clear_changes ();
r->set_position (pos, this);
_session->add_command(new StatefulDiffCommand (r));
boost::shared_ptr<Region> region ((*i)->region());
- region->clear_history ();
+ region->clear_changes ();
if (dir > 0) {
region->set_position (region->position() + distance, this);
void
Editor::align_region_internal (boost::shared_ptr<Region> region, RegionPoint point, nframes64_t position)
{
- region->clear_history ();
+ region->clear_changes ();
switch (point) {
case SyncPoint:
for (list<RegionView*>::const_iterator i = rs.by_layer().begin(); i != rs.by_layer().end(); ++i) {
if (!(*i)->region()->locked()) {
- (*i)->region()->clear_history ();
+
+ (*i)->region()->clear_changes ();
+
if (front) {
(*i)->region()->trim_front (where, this);
} else {
(*i)->region()->trim_end (where, this);
}
+
_session->add_command (new StatefulDiffCommand ((*i)->region()));
}
}
start = session_frame_to_track_frame (loc.start(), speed);
end = session_frame_to_track_frame (loc.end(), speed);
- rv->region()->clear_history ();
+ rv->region()->clear_changes ();
rv->region()->trim_to (start, (end - start), this);
_session->add_command(new StatefulDiffCommand (rv->region()));
}
speed = tav->track()->speed();
}
- rv->region()->clear_history ();
+ rv->region()->clear_changes ();
rv->region()->trim_end (session_frame_to_track_frame(where, speed), this);
_session->add_command(new StatefulDiffCommand (rv->region()));
}
speed = tav->track()->speed();
}
- rv->region()->clear_history ();
+ rv->region()->clear_changes ();
rv->region()->trim_front (session_frame_to_track_frame(where, speed), this);
_session->add_command(new StatefulDiffCommand (rv->region()));
}
boost::shared_ptr<Region> region = arv->region();
boost::shared_ptr<Playlist> playlist (region->playlist());
- region->clear_history ();
+ region->clear_changes ();
if(forward){
continue;
}
- region->trim_end((nframes64_t) (next_region->first_frame() * speed), this);
+ region->trim_end((nframes64_t) ( (next_region->first_frame() - 1) * speed), this);
arv->region_changed (PropertyChange (ARDOUR::Properties::length));
}
else {
InterThreadInfo itt;
- playlist->clear_history ();
+ playlist->clear_changes ();
+ playlist->clear_owned_changes ();
+
boost::shared_ptr<Region> r = rtv->track()->bounce_range (start, start+cnt, itt, enable_processing);
if (replace) {
playlist->add_region (r, start);
}
- _session->add_command (new StatefulDiffCommand (playlist));
+ vector<Command*> cmds;
+ playlist->rdiff (cmds);
+ _session->add_commands (cmds);
+
+ _session->add_command (new StatefulDiffCommand (playlist));
}
commit_reversible_command ();
}
}
+
+
+struct lt_playlist {
+ bool operator () (const PlaylistState& a, const PlaylistState& b) {
+ return a.playlist < b.playlist;
+ }
+};
+
struct PlaylistMapping {
TimeAxisView* tv;
boost::shared_ptr<Playlist> pl;
boost::shared_ptr<Playlist> playlist = clicked_routeview->playlist();
begin_reversible_command (_("remove region"));
- playlist->clear_history ();
+ playlist->clear_changes ();
playlist->remove_region (clicked_regionview->region());
_session->add_command(new StatefulDiffCommand (playlist));
commit_reversible_command ();
if (i == playlists.end()) {
- playlist->clear_history ();
+ playlist->clear_changes ();
playlist->freeze ();
playlists.push_back (playlist);
}
if (fl == freezelist.end()) {
- pl->clear_history();
+ pl->clear_changes();
pl->freeze ();
freezelist.insert (pl);
}
foo.push_back ((*i).pl);
}
-
if (!foo.empty()) {
cut_buffer->set (foo);
}
+
+ if (pmap.empty()) {
+ _last_cut_copy_source_track = 0;
+ } else {
+ _last_cut_copy_source_track = pmap.front().tv;
+ }
for (FreezeList::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
(*pl)->thaw ();
/* get everything in the correct order */
if (!selection->tracks.empty()) {
+ /* there are some selected tracks, so paste to them */
sort_track_selection ();
ts = selection->tracks;
- } else if (entered_track) {
- ts.push_back (entered_track);
+ } else if (_last_cut_copy_source_track) {
+ /* otherwise paste to the track that the cut/copy came from;
+ see discussion in mants #3333.
+ */
+ ts.push_back (_last_cut_copy_source_track);
}
for (nth = 0, i = ts.begin(); i != ts.end(); ++i, ++nth) {
sigc::connection c = rtv->view()->RegionViewAdded.connect (sigc::mem_fun(*this, &Editor::collect_new_region_view));
playlist = (*i)->region()->playlist();
- playlist->clear_history ();
- playlist->duplicate (r, end_frame + (r->first_frame() - start_frame) + 1, times);
+ playlist->clear_changes ();
+ playlist->duplicate (r, end_frame + (r->first_frame() - start_frame), times);
_session->add_command(new StatefulDiffCommand (playlist));
c.disconnect ();
if ((playlist = (*i)->playlist()) == 0) {
continue;
}
- playlist->clear_history ();
+ playlist->clear_changes ();
playlist->duplicate (*ri, selection->time[clicked_selection].end, times);
_session->add_command (new StatefulDiffCommand (playlist));
Editor::clear_playlist (boost::shared_ptr<Playlist> playlist)
{
begin_reversible_command (_("clear playlist"));
- playlist->clear_history ();
+ playlist->clear_changes ();
playlist->clear ();
_session->add_command (new StatefulDiffCommand (playlist));
commit_reversible_command ();
continue;
}
- playlist->clear_history ();
- playlist->clear_owned_history ();
+ playlist->clear_changes ();
+ playlist->clear_owned_changes ();
playlist->nudge_after (start, distance, forwards);
- vector<StatefulDiffCommand*> cmds;
+ vector<Command*> cmds;
playlist->rdiff (cmds);
-
- for (vector<StatefulDiffCommand*>::iterator c = cmds.begin(); c != cmds.end(); ++c) {
- _session->add_command (*c);
- }
+ _session->add_commands (cmds);
_session->add_command (new StatefulDiffCommand (playlist));
}
if (prompter.run () == 1) {
_session->remove_last_capture ();
+ _regions->redisplay ();
}
} else {
_session->remove_last_capture();
+ _regions->redisplay ();
}
}
}
Dialog dialog (rs.size() > 1 ? _("Normalize regions") : _("Normalize region"));
+
+ VBox vbox;
+ vbox.set_spacing (6);
+ vbox.set_border_width (6);
+
HBox hbox;
hbox.set_spacing (6);
hbox.set_border_width (6);
hbox.pack_start (spin);
spin.set_value (_last_normalization_value);
hbox.pack_start (*manage (new Label (_("dbFS"))));
- hbox.show_all ();
+ vbox.pack_start (hbox);
+
+ CheckButton* normalize_across_all = manage (new CheckButton (_("Normalize across all selected regions")));
+ vbox.pack_start (*normalize_across_all);
+ if (rs.size() <= 1) {
+ normalize_across_all->set_sensitive (false);
+ }
+
+ vbox.show_all ();
+
dialog.get_vbox()->set_spacing (12);
- dialog.get_vbox()->pack_start (hbox);
+ dialog.get_vbox()->pack_start (vbox);
dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
dialog.add_button (_("Normalize"), RESPONSE_ACCEPT);
track_canvas->get_window()->set_cursor (*wait_cursor);
gdk_flush ();
+ double maxamp = 0;
+ if (normalize_across_all->get_active ()) {
+ for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) {
+ AudioRegionView* const arv = dynamic_cast<AudioRegionView*> (*r);
+ if (!arv) {
+ continue;
+ }
+ maxamp = max (maxamp, arv->audio_region()->maximum_amplitude ());
+ }
+ }
+
for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) {
- AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
- if (!arv)
+ AudioRegionView* const arv = dynamic_cast<AudioRegionView*> (*r);
+ if (!arv) {
continue;
- arv->region()->clear_history ();
- arv->audio_region()->normalize_to (spin.get_value());
+ }
+ arv->region()->clear_changes ();
+
+ double const amp = normalize_across_all->get_active() ? maxamp : arv->audio_region()->maximum_amplitude ();
+
+ arv->audio_region()->normalize (amp, spin.get_value ());
_session->add_command (new StatefulDiffCommand (arv->region()));
-
}
commit_reversible_command ();
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
if (!arv)
continue;
- arv->region()->clear_history ();
+ arv->region()->clear_changes ();
arv->audio_region()->set_scale_amplitude (1.0f);
_session->add_command (new StatefulDiffCommand (arv->region()));
}
continue;
}
- arv->region()->clear_history ();
+ arv->region()->clear_changes ();
double fraction = gain_to_slider_position (arv->audio_region()->scale_amplitude ());
Editor::apply_midi_note_edit_op_to_region (MidiOperator& op, MidiRegionView& mrv)
{
Evoral::Sequence<Evoral::MusicalTime>::Notes selected;
- mrv.selection_as_notelist (selected);
+ mrv.selection_as_notelist (selected, true);
vector<Evoral::Sequence<Evoral::MusicalTime>::Notes> v;
v.push_back (selected);
rs.clear ();
}
+void
+Editor::fork_region ()
+{
+ RegionSelection rs;
+
+ get_regions_for_action (rs);
+
+ if (rs.empty()) {
+ return;
+ }
+
+ begin_reversible_command (_("Fork Region(s)"));
+
+ track_canvas->get_window()->set_cursor (*wait_cursor);
+ gdk_flush ();
+
+ for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ) {
+ RegionSelection::iterator tmp = r;
+ ++tmp;
+
+ MidiRegionView* const mrv = dynamic_cast<MidiRegionView*>(*r);
+
+ if (mrv) {
+ boost::shared_ptr<Playlist> playlist = mrv->region()->playlist();
+ boost::shared_ptr<MidiRegion> newregion = mrv->midi_region()->clone ();
+
+ playlist->clear_changes ();
+ playlist->replace_region (mrv->region(), newregion, mrv->region()->position());
+ _session->add_command(new StatefulDiffCommand (playlist));
+ }
+
+ r = tmp;
+ }
+
+ commit_reversible_command ();
+ rs.clear ();
+
+ track_canvas->get_window()->set_cursor (*current_canvas_cursor);
+}
+
void
Editor::quantize_region ()
{
if (arv->audio_region()->apply (filter) == 0) {
- playlist->clear_history ();
+ playlist->clear_changes ();
if (filter.results.empty ()) {
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv) {
- arv->region()->clear_history ();
+ arv->region()->clear_changes ();
arv->set_envelope_visible (!arv->envelope_visible());
_session->add_command (new StatefulDiffCommand (arv->region()));
}
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv) {
- arv->region()->clear_history ();
+ arv->region()->clear_changes ();
arv->audio_region()->set_envelope_active (!arv->audio_region()->envelope_active());
_session->add_command (new StatefulDiffCommand (arv->region()));
}
_session->begin_reversible_command (_("region lock"));
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
- (*i)->region()->clear_history ();
+ (*i)->region()->clear_changes ();
(*i)->region()->set_locked (!(*i)->region()->locked());
_session->add_command (new StatefulDiffCommand ((*i)->region()));
}
_session->begin_reversible_command (_("region lock style"));
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
- (*i)->region()->clear_history ();
- Region::PositionLockStyle const ns = (*i)->region()->positional_lock_style() == Region::AudioTime ? Region::MusicTime : Region::AudioTime;
+ (*i)->region()->clear_changes ();
+ PositionLockStyle const ns = (*i)->region()->position_lock_style() == AudioTime ? MusicTime : AudioTime;
(*i)->region()->set_position_lock_style (ns);
_session->add_command (new StatefulDiffCommand ((*i)->region()));
}
_session->begin_reversible_command (_("region mute"));
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
- (*i)->region()->clear_history ();
+ (*i)->region()->clear_changes ();
(*i)->region()->set_muted (!(*i)->region()->muted());
_session->add_command (new StatefulDiffCommand ((*i)->region()));
}
_session->begin_reversible_command (_("region opacity"));
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
- (*i)->region()->clear_history ();
+ (*i)->region()->clear_changes ();
(*i)->region()->set_opaque (!(*i)->region()->opaque());
_session->add_command (new StatefulDiffCommand ((*i)->region()));
}
first = false;
}
- rtav->track()->set_record_enable(new_state, this);
+ rtav->track()->set_record_enabled (new_state, this);
}
}
have_switch = true;
}
- region->clear_history ();
+ region->clear_changes ();
if (in) {
region->set_fade_in_active (!yn);
boost::shared_ptr<AudioRegion> ar (tmp->audio_region());
- ar->clear_history ();
+ ar->clear_changes ();
ar->set_fade_in_active (yn);
_session->add_command (new StatefulDiffCommand (ar));
}
boost::shared_ptr<AudioRegion> ar (tmp->audio_region());
- ar->clear_history ();
+ ar->clear_changes ();
ar->set_fade_out_active (yn);
_session->add_command(new StatefulDiffCommand (ar));
}
void
Editor::split ()
{
+ if (((mouse_mode == MouseRange) ||
+ (mouse_mode != MouseObject && _join_object_range_state == JOIN_OBJECT_RANGE_RANGE)) &&
+ !selection->time.empty()) {
+ separate_regions_between (selection->time);
+ return;
+ }
+
RegionSelection rs;
get_regions_for_action (rs, true);
int response = msg.run();
msg.hide ();
+
switch (response) {
case RESPONSE_OK:
break;
AnalysisFeatureList::const_iterator x;
- nframes64_t pos = r->position();
-
- pl->clear_history ();
+ pl->clear_changes ();
x = positions.begin();
- while (x != positions.end()) {
- if ((*x) > pos) {
- break;
- }
- ++x;
- }
-
if (x == positions.end()) {
return;
}
pl->freeze ();
pl->remove_region (r);
+ nframes64_t pos = 0;
+
while (x != positions.end()) {
+
+ /* deal with positons that are out of scope of present region bounds */
+ if (*x <= 0 || *x > r->length()){
+ ++x;
+ continue;
+ }
/* file start = original start + how far we from the initial position ?
*/
- nframes64_t file_start = r->start() + (pos - r->position());
+ nframes64_t file_start = r->start() + pos;
/* length = next position - current position
*/
nframes64_t len = (*x) - pos;
-
+
/* XXX we do we really want to allow even single-sample regions?
shouldn't we have some kind of lower limit on region size?
*/
plist.add (ARDOUR::Properties::layer, 0);
boost::shared_ptr<Region> nr = RegionFactory::create (r->sources(), plist, false);
- pl->add_region (nr, pos);
+ pl->add_region (nr, r->position() + pos);
pos += len;
++x;
+ }
- if (*x > r->last_frame()) {
+ string new_name;
- /* add final fragment */
+ RegionFactory::region_name (new_name, r->name());
+
+ /* Add the final region */
+ PropertyList plist;
+
+ plist.add (ARDOUR::Properties::start, r->start() + pos);
+ plist.add (ARDOUR::Properties::length, r->last_frame() - (r->position() + pos) + 1);
+ plist.add (ARDOUR::Properties::name, new_name);
+ plist.add (ARDOUR::Properties::layer, 0);
- file_start = r->start() + (pos - r->position());
- len = r->last_frame() - pos;
+ boost::shared_ptr<Region> nr = RegionFactory::create (r->sources(), plist, false);
+ pl->add_region (nr, r->position() + pos);
- PropertyList plist2;
-
- plist2.add (ARDOUR::Properties::start, file_start);
- plist2.add (ARDOUR::Properties::length, len);
- plist2.add (ARDOUR::Properties::name, new_name);
- plist2.add (ARDOUR::Properties::layer, 0);
+
+ pl->thaw ();
- nr = RegionFactory::create (r->sources(), plist2);
- pl->add_region (nr, pos);
+ _session->add_command (new StatefulDiffCommand (pl));
+}
- break;
- }
+void
+Editor::place_transient()
+{
+ if (!_session) {
+ return;
}
- pl->thaw ();
+ RegionSelection rs;
- _session->add_command (new StatefulDiffCommand (pl));
+ get_regions_for_action (rs);
+
+ if (rs.empty()) {
+ return;
+ }
+
+ nframes64_t where = get_preferred_edit_position();
+
+ _session->begin_reversible_command (_("place transient"));
+
+ for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) {
+ framepos_t position = (*r)->region()->position();
+ (*r)->region()->add_transient(where - position);
+ }
+
+ _session->commit_reversible_command ();
+}
+
+void
+Editor::remove_transient(ArdourCanvas::Item* item)
+{
+ if (!_session) {
+ return;
+ }
+
+ ArdourCanvas::SimpleLine* _line = reinterpret_cast<ArdourCanvas::SimpleLine*> (item);
+ assert (_line);
+
+ AudioRegionView* _arv = reinterpret_cast<AudioRegionView*> (item->get_data ("regionview"));
+ _arv->remove_transient(_line->property_x1());
+}
+
+void
+Editor::snap_regions_to_grid()
+{
+ if (!_session) {
+ return;
+ }
+
+ RegionSelection rs;
+
+ get_regions_for_action (rs);
+
+ if (rs.empty()) {
+ return;
+ }
+
+ _session->begin_reversible_command (_("snap regions to grid"));
+
+ for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) {
+ framepos_t start_frame = (*r)->region()->first_frame ();
+ snap_to (start_frame);
+ (*r)->region()->set_position (start_frame, this);
+ }
+
+ _session->commit_reversible_command ();
+}
+
+void
+Editor::close_region_gaps()
+{
+ if (!_session) {
+ return;
+ }
+
+ RegionSelection rs;
+
+ get_regions_for_action (rs);
+
+ if (rs.empty()) {
+ return;
+ }
+
+ Dialog dialog (rs.size() > 1 ? _("Conform regions") : _("Conform region"));
+
+ HBox hbox_crossfade;
+ hbox_crossfade.set_spacing (10);
+ //hbox_crossfade.set_border_width (3);
+ hbox_crossfade.pack_start (*manage (new Label (_("Crossfade length:"))));
+
+ SpinButton spin_crossfade (1, 0);
+ spin_crossfade.set_range (0, 15);
+ spin_crossfade.set_increments (1, 1);
+ spin_crossfade.set_value (3);
+
+ hbox_crossfade.pack_start (spin_crossfade);
+ hbox_crossfade.pack_start (*manage (new Label (_("ms"))));
+ hbox_crossfade.show_all ();
+
+ HBox hbox_pullback;
+
+ hbox_pullback.set_spacing (10);
+ //hbox_pullback.set_border_width (3);
+ hbox_pullback.pack_start (*manage (new Label (_("Pull-back length:"))));
+
+ SpinButton spin_pullback (1, 0);
+ spin_pullback.set_range (0, 15);
+ spin_pullback.set_increments (1, 1);
+ spin_pullback.set_value (5);
+
+ hbox_pullback.pack_start (spin_pullback);
+ hbox_pullback.pack_start (*manage (new Label (_("ms"))));
+ hbox_pullback.show_all ();
+
+ dialog.get_vbox()->set_spacing (6);
+ dialog.get_vbox()->pack_start (hbox_crossfade);
+ dialog.get_vbox()->pack_start (hbox_pullback);
+ dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
+ dialog.add_button (_("Ok"), RESPONSE_ACCEPT);
+
+ if (dialog.run () == RESPONSE_CANCEL) {
+ return;
+ }
+
+ nframes64_t crossfade_len = spin_crossfade.get_value();
+ nframes64_t pull_back_frames = spin_pullback.get_value();
+
+ crossfade_len = lrintf (crossfade_len * _session->frame_rate()/1000);
+ pull_back_frames = lrintf (pull_back_frames * _session->frame_rate()/1000);
+
+ /* Iterate over the region list and make adjacent regions overlap by crossfade_len_ms */
+
+ _session->begin_reversible_command (_("close region gaps"));
+
+ int idx = 0;
+ boost::shared_ptr<Region> last_region;
+
+ rs.sort_by_position_and_track();
+
+ for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) {
+
+ nframes64_t position = (*r)->region()->position();
+
+ if (idx == 0 || position < last_region->position()){
+ last_region = (*r)->region();
+ idx++;
+ continue;
+ }
+
+ (*r)->region()->trim_front( (position - pull_back_frames), this );
+ last_region->trim_end( (position - pull_back_frames + crossfade_len), this );
+
+ last_region = (*r)->region();
+
+ idx++;
+ }
+
+ _session->commit_reversible_command ();
}
void
}
}
}
+
void
Editor::playhead_forward_to_grid ()
{
}
void
-Editor::set_track_height (uint32_t h)
+Editor::set_track_height (Height h)
{
TrackSelection& ts (selection->tracks);
const char* trackstr;
const char* busstr;
vector<boost::shared_ptr<Route> > routes;
+ bool special_bus = false;
for (TrackSelection::iterator x = ts.begin(); x != ts.end(); ++x) {
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*x);
}
}
routes.push_back (rtv->_route);
- }
+ if (rtv->route()->is_master() || rtv->route()->is_monitor()) {
+ special_bus = true;
+ }
+ }
+
+ if (special_bus && !Config->get_allow_special_bus_removal()) {
+ MessageDialog msg (_("That would be bad news ...."),
+ false,
+ Gtk::MESSAGE_INFO,
+ Gtk::BUTTONS_OK);
+ msg.set_secondary_text (string_compose (_(
+"Removing the master or monitor bus is such a bad idea\n\
+that %1 is not going to allow it.\n\
+\n\
+If you really want to do this sort of thing\n\
+edit your ardour.rc file to set the\n\
+\"allow-special-bus-removal\" option to be \"yes\""), PROGRAM_NAME));
+
+ msg.present ();
+ msg.run ();
+ return;
+ }
+
if (ntracks + nbusses == 0) {
return;
}
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!"),
+ "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!"),
+ "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?"),
+ prompt = string_compose (_("Do you really want to remove %1 %2?\n\n"
+ "This action cannot be undon, and the session file will be overwritten"),
nbusses, busstr);
}
return;
}
- ArdourDialog d (*this, _("Insert Time"));
-
- nframes64_t const pos = get_preferred_edit_position ();
-
- d.get_vbox()->set_border_width (12);
- d.get_vbox()->set_spacing (4);
-
- Table table (2, 2);
- table.set_spacings (4);
-
- Label time_label (_("Time to insert:"));
- time_label.set_alignment (1, 0.5);
- table.attach (time_label, 0, 1, 0, 1, FILL | EXPAND);
- AudioClock clock ("insertTimeClock", true, X_("InsertTimeClock"), true, false, true, true);
- clock.set (0);
- clock.set_session (_session);
- clock.set_bbt_reference (pos);
- table.attach (clock, 1, 2, 0, 1);
-
- Label intersected_label (_("Intersected regions should:"));
- intersected_label.set_alignment (1, 0.5);
- table.attach (intersected_label, 0, 1, 1, 2, FILL | EXPAND);
- ComboBoxText intersected_combo;
- intersected_combo.append_text (_("stay in position"));
- intersected_combo.append_text (_("move"));
- intersected_combo.append_text (_("be split"));
- intersected_combo.set_active (0);
- table.attach (intersected_combo, 1, 2, 1, 2);
-
- d.get_vbox()->pack_start (table);
-
- CheckButton move_glued (_("Move glued regions"));
- d.get_vbox()->pack_start (move_glued);
- CheckButton move_markers (_("Move markers"));
- d.get_vbox()->pack_start (move_markers);
- CheckButton move_tempos (_("Move tempo and meter changes"));
- d.get_vbox()->pack_start (move_tempos);
-
- d.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
- d.add_button (_("Insert time"), Gtk::RESPONSE_OK);
- d.show_all ();
-
+ InsertTimeDialog d (*this);
int response = d.run ();
if (response != RESPONSE_OK) {
return;
}
- nframes64_t distance = clock.current_duration (pos);
-
- if (distance == 0) {
+ if (d.distance() == 0) {
return;
}
- /* only setting this to keep GCC quiet */
- InsertTimeOption opt = LeaveIntersected;
+ InsertTimeOption opt = d.intersected_region_action ();
- switch (intersected_combo.get_active_row_number ()) {
- case 0:
- opt = LeaveIntersected;
- break;
- case 1:
- opt = MoveIntersected;
- break;
- case 2:
- opt = SplitIntersected;
- break;
- }
-
- insert_time (pos, distance, opt, move_glued.get_active(), move_markers.get_active(), move_tempos.get_active());
+ insert_time (
+ get_preferred_edit_position(),
+ d.distance(),
+ opt,
+ d.move_glued(),
+ d.move_markers(),
+ d.move_glued_markers(),
+ d.move_locked_markers(),
+ d.move_tempos()
+ );
}
void
Editor::insert_time (nframes64_t pos, nframes64_t frames, InsertTimeOption opt,
- bool ignore_music_glue, bool markers_too, bool tempo_too)
+ bool ignore_music_glue, bool markers_too, bool glued_markers_too, bool locked_markers_too, bool tempo_too)
{
bool commit = false;
if (pl) {
- pl->clear_history ();
- pl->clear_owned_history ();
+ pl->clear_changes ();
+ pl->clear_owned_changes ();
if (opt == SplitIntersected) {
pl->split (pos);
pl->shift (pos, frames, (opt == MoveIntersected), ignore_music_glue);
- vector<StatefulDiffCommand*> cmds;
-
+ vector<Command*> cmds;
pl->rdiff (cmds);
-
- cerr << "Shift generated " << cmds.size() << " sdc's\n";
-
- for (vector<StatefulDiffCommand*>::iterator c = cmds.begin(); c != cmds.end(); ++c) {
- _session->add_command (*c);
- }
-
+ _session->add_commands (cmds);
+
_session->add_command (new StatefulDiffCommand (pl));
commit = true;
}
Locations::LocationList::const_iterator tmp;
- if ((*i)->start() >= pos) {
- (*i)->set_start ((*i)->start() + frames);
- if (!(*i)->is_mark()) {
- (*i)->set_end ((*i)->end() + frames);
+ bool const was_locked = (*i)->locked ();
+ if (locked_markers_too) {
+ (*i)->unlock ();
+ }
+
+ if ((*i)->position_lock_style() == AudioTime || glued_markers_too) {
+
+ if ((*i)->start() >= pos) {
+ (*i)->set_start ((*i)->start() + frames);
+ if (!(*i)->is_mark()) {
+ (*i)->set_end ((*i)->end() + frames);
+ }
+ moved = true;
}
- moved = true;
+
+ }
+
+ if (was_locked) {
+ (*i)->lock ();
}
}
uint32_t h = (uint32_t) floor ((_canvas_height - child_heights - canvas_timebars_vsize) / tracks.size());
double first_y_pos = DBL_MAX;
- if (h < TimeAxisView::hSmall) {
+ if (h < TimeAxisView::preset_height (HeightSmall)) {
MessageDialog msg (*this, _("There are too many tracks to fit in the current window"));
/* too small to be displayed */
return;
undo_visual_stack.push_back (current_visual_state());
+ /* build a list of all tracks, including children */
+
+ TrackViewList all;
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+ all.push_back (*i);
+ TimeAxisView::Children c = (*i)->get_child_list ();
+ for (TimeAxisView::Children::iterator j = c.begin(); j != c.end(); ++j) {
+ all.push_back (j->get());
+ }
+ }
+
/* operate on all tracks, hide unselected ones that are in the middle of selected ones */
bool prev_was_selected = false;
- bool is_selected = tracks.contains (track_views.front());
+ bool is_selected = tracks.contains (all.front());
bool next_is_selected;
- for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
+ for (TrackViewList::iterator t = all.begin(); t != all.end(); ++t) {
TrackViewList::iterator next;
next = t;
++next;
- if (next != track_views.end()) {
+ if (next != all.end()) {
next_is_selected = tracks.contains (*next);
} else {
next_is_selected = false;