2005-09-25 14:42:24 -04:00
|
|
|
/*
|
2009-10-14 12:10:01 -04:00
|
|
|
Copyright (C) 2000-2004 Paul Davis
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2007-05-11 11:06:12 -04:00
|
|
|
/* Note: public Editor methods are documented in public_editor.h */
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <cmath>
|
|
|
|
#include <string>
|
|
|
|
#include <map>
|
2008-09-10 11:03:30 -04:00
|
|
|
#include <set>
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-02-25 13:26:51 -05:00
|
|
|
#include "pbd/error.h"
|
|
|
|
#include "pbd/basename.h"
|
|
|
|
#include "pbd/pthread_utils.h"
|
|
|
|
#include "pbd/memento_command.h"
|
|
|
|
#include "pbd/whitespace.h"
|
2010-02-11 12:08:34 -05:00
|
|
|
#include "pbd/stateful_diff_command.h"
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2005-09-25 16:33:00 -04:00
|
|
|
#include <gtkmm2ext/utils.h>
|
|
|
|
#include <gtkmm2ext/choice.h>
|
2008-09-10 11:03:30 -04:00
|
|
|
#include <gtkmm2ext/popup.h>
|
|
|
|
|
2009-02-25 13:26:51 -05:00
|
|
|
#include "ardour/audioengine.h"
|
|
|
|
#include "ardour/session.h"
|
|
|
|
#include "ardour/audioplaylist.h"
|
|
|
|
#include "ardour/audioregion.h"
|
|
|
|
#include "ardour/audio_diskstream.h"
|
|
|
|
#include "ardour/utils.h"
|
|
|
|
#include "ardour/location.h"
|
|
|
|
#include "ardour/audio_track.h"
|
|
|
|
#include "ardour/audioplaylist.h"
|
|
|
|
#include "ardour/region_factory.h"
|
|
|
|
#include "ardour/playlist_factory.h"
|
|
|
|
#include "ardour/reverse.h"
|
|
|
|
#include "ardour/transient_detector.h"
|
|
|
|
#include "ardour/dB.h"
|
|
|
|
#include "ardour/quantize.h"
|
2009-04-29 13:01:14 -04:00
|
|
|
#include "ardour/strip_silence.h"
|
2009-06-21 21:01:43 -04:00
|
|
|
#include "ardour/route_group.h"
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
#include "ardour_ui.h"
|
|
|
|
#include "editor.h"
|
|
|
|
#include "time_axis_view.h"
|
2008-02-02 12:22:04 -05:00
|
|
|
#include "route_time_axis.h"
|
2005-09-25 14:42:24 -04:00
|
|
|
#include "audio_time_axis.h"
|
|
|
|
#include "automation_time_axis.h"
|
|
|
|
#include "streamview.h"
|
2008-10-09 17:55:05 -04:00
|
|
|
#include "audio_streamview.h"
|
2006-08-01 13:19:38 -04:00
|
|
|
#include "audio_region_view.h"
|
2007-08-06 01:30:18 -04:00
|
|
|
#include "midi_region_view.h"
|
2005-09-25 14:42:24 -04:00
|
|
|
#include "rgb_macros.h"
|
|
|
|
#include "selection_templates.h"
|
|
|
|
#include "selection.h"
|
|
|
|
#include "editing.h"
|
|
|
|
#include "gtk-custom-hruler.h"
|
2006-04-06 12:51:27 -04:00
|
|
|
#include "gui_thread.h"
|
2008-01-18 22:49:52 -05:00
|
|
|
#include "keyboard.h"
|
2008-01-19 00:06:33 -05:00
|
|
|
#include "utils.h"
|
2009-05-30 14:25:59 -04:00
|
|
|
#include "editor_drag.h"
|
2009-04-29 13:01:14 -04:00
|
|
|
#include "strip_silence_dialog.h"
|
2009-07-03 14:37:15 -04:00
|
|
|
#include "editor_routes.h"
|
2009-07-03 18:42:22 -04:00
|
|
|
#include "editor_regions.h"
|
2009-08-26 23:09:30 -04:00
|
|
|
#include "quantize_dialog.h"
|
2010-04-14 18:16:46 -04:00
|
|
|
#include "interthread_progress_window.h"
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
#include "i18n.h"
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace ARDOUR;
|
Large nasty commit in the form of a 5000 line patch chock-full of completely
unecessary changes. (Sorry, doing a "sprint" based thing, this is the end of the first one)
Achieved MIDI track and bus creation, associated Jack port and diskstream creation, and minimal GUI stuff for creating them. Should be set to start work on actually recording and playing midi to/from disk now.
Relevant (significant) changes:
- Creation of a Buffer class. Base class is type agnostic so things can point to a buffer but not care what kind it is (otherwise it'd be a template). Derived into AudioBuffer and MidiBuffer, with a type tag because checking type is necessary in parts of the code where dynamic_cast wouldn't be wise. Originally I considered this a hack, but passing around a type proved to be a very good solution to all the other problems (below). There is a 1:1 mapping between jack port data types and ardour Buffer types (with a conversion function), but that's easily removed if it ever becomes necessary. Having the type scoped in the Buffer class is maybe not the best spot for it, but whatever (this is proof of concept kinda stuff right now...)
- IO now has a "default" port type (passed to the constructor and stored as a member), used by ensure_io (and similar) to create n ports. IO::register_***_port has a type argument that defaults to the default type if not passed. Rationale: previous IO API is identical, no changes needed to existing code, but path is paved for multiple port types in one IO, which we will need for eg synth plugin inserts, among other things. This is not quite ideal (best would be to only have the two port register functions and have them take a type), but the alternative is a lot of work (namely destroying the 'ensure' functions and everything that uses them) for very little gain. (I am convinced after quite a few tries at the whiteboard that subclassing IO in any way is not a feasible option, look at it's inheritance diagram in Doxygen and you can see why)
- AudioEngine::register_audio_input_port is now register_input_port and takes a type argument. Ditto for output.
- (Most significant change) AudioDiskstream abstracted into Distream, and sibling MidiDiskstream created. Very much still a work in progress, but Diskstream is there to switch references over to (most already are), which is the important part. It is still unclear what the MIDI diskstream's relation to channels is, but I'm pretty sure they will be single channel only (so SMF Type 0) since noone can come up with a reason otherwise.
- MidiTrack creation. Same thing as AudioTrack but with a different default type basically. No big deal here.
- Random cleanups and variable renamings etc. because I have OCD and can't help myself. :)
Known broken: Loading of sessions containing MIDI tracks.
git-svn-id: svn://localhost/ardour2/branches/midi@641 d708f5d6-7413-0410-9779-e7cbd77b26cf
2006-06-26 12:01:34 -04:00
|
|
|
using namespace PBD;
|
2005-09-25 14:42:24 -04:00
|
|
|
using namespace Gtk;
|
2007-03-19 03:07:38 -04:00
|
|
|
using namespace Gtkmm2ext;
|
2005-09-25 14:42:24 -04:00
|
|
|
using namespace Editing;
|
2009-12-04 17:51:32 -05:00
|
|
|
using Gtkmm2ext::Keyboard;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
Editor operations
|
|
|
|
***********************************************************************/
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::undo (uint32_t n)
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (_session) {
|
|
|
|
_session->undo (n);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::redo (uint32_t n)
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (_session) {
|
|
|
|
_session->redo (n);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-09-10 11:03:30 -04:00
|
|
|
Editor::split_regions_at (nframes64_t where, RegionSelection& regions)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
use filechooser widget in export dialog, selected files set format combos, hide progress bar until use in export dialog, speed up 'separate regions in range' operation on larger sessions, ruler scale now calculated separately to mark generation, fix for non-stacked layering regression, try not to generate 'buried' crossfades, use playlist->freeze() to speed up copying/moving regions on large playlists (not done for undo), width dependent items now reset on regionview init, get rid of jack_port_ensure_monitor check, remove audiosourse _length (only source has a length.. i think), make overlapend differ to overlapexternal where start points coincide.
git-svn-id: svn://localhost/ardour2/trunk@2576 d708f5d6-7413-0410-9779-e7cbd77b26cf
2007-10-26 09:32:24 -04:00
|
|
|
list <boost::shared_ptr<Playlist > > used_playlists;
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (regions.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
begin_reversible_command (_("split"));
|
|
|
|
|
2007-10-11 18:07:47 -04:00
|
|
|
// if splitting a single region, and snap-to is using
|
|
|
|
// region boundaries, don't pay attention to them
|
|
|
|
|
|
|
|
if (regions.size() == 1) {
|
2009-10-26 19:43:04 -04:00
|
|
|
switch (_snap_type) {
|
2007-10-11 18:07:47 -04:00
|
|
|
case SnapToRegionStart:
|
|
|
|
case SnapToRegionSync:
|
|
|
|
case SnapToRegionEnd:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
snap_to (where);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
snap_to (where);
|
|
|
|
}
|
|
|
|
|
2007-11-07 20:40:25 -05:00
|
|
|
for (RegionSelection::iterator a = regions.begin(); a != regions.end(); ) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-11-07 20:40:25 -05:00
|
|
|
RegionSelection::iterator tmp;
|
|
|
|
|
|
|
|
/* XXX this test needs to be more complicated, to make sure we really
|
|
|
|
have something to split.
|
|
|
|
*/
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-11-07 20:40:25 -05:00
|
|
|
if (!(*a)->region()->covers (where)) {
|
|
|
|
++a;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp = a;
|
|
|
|
++tmp;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-01-09 18:24:54 -05:00
|
|
|
boost::shared_ptr<Playlist> pl = (*a)->region()->playlist();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2010-03-04 08:15:04 -05:00
|
|
|
if (!pl) {
|
|
|
|
a = tmp;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pl->frozen()) {
|
use filechooser widget in export dialog, selected files set format combos, hide progress bar until use in export dialog, speed up 'separate regions in range' operation on larger sessions, ruler scale now calculated separately to mark generation, fix for non-stacked layering regression, try not to generate 'buried' crossfades, use playlist->freeze() to speed up copying/moving regions on large playlists (not done for undo), width dependent items now reset on regionview init, get rid of jack_port_ensure_monitor check, remove audiosourse _length (only source has a length.. i think), make overlapend differ to overlapexternal where start points coincide.
git-svn-id: svn://localhost/ardour2/trunk@2576 d708f5d6-7413-0410-9779-e7cbd77b26cf
2007-10-26 09:32:24 -04:00
|
|
|
/* we haven't seen this playlist before */
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
/* remember used playlists so we can thaw them later */
|
use filechooser widget in export dialog, selected files set format combos, hide progress bar until use in export dialog, speed up 'separate regions in range' operation on larger sessions, ruler scale now calculated separately to mark generation, fix for non-stacked layering regression, try not to generate 'buried' crossfades, use playlist->freeze() to speed up copying/moving regions on large playlists (not done for undo), width dependent items now reset on regionview init, get rid of jack_port_ensure_monitor check, remove audiosourse _length (only source has a length.. i think), make overlapend differ to overlapexternal where start points coincide.
git-svn-id: svn://localhost/ardour2/trunk@2576 d708f5d6-7413-0410-9779-e7cbd77b26cf
2007-10-26 09:32:24 -04:00
|
|
|
used_playlists.push_back(pl);
|
|
|
|
pl->freeze();
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (pl) {
|
2010-03-01 19:00:00 -05:00
|
|
|
pl->clear_history ();
|
2006-07-23 08:03:19 -04:00
|
|
|
pl->split_region ((*a)->region(), where);
|
2010-03-01 19:00:00 -05:00
|
|
|
_session->add_command (new StatefulDiffCommand (pl));
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2007-11-07 20:40:25 -05:00
|
|
|
a = tmp;
|
use filechooser widget in export dialog, selected files set format combos, hide progress bar until use in export dialog, speed up 'separate regions in range' operation on larger sessions, ruler scale now calculated separately to mark generation, fix for non-stacked layering regression, try not to generate 'buried' crossfades, use playlist->freeze() to speed up copying/moving regions on large playlists (not done for undo), width dependent items now reset on regionview init, get rid of jack_port_ensure_monitor check, remove audiosourse _length (only source has a length.. i think), make overlapend differ to overlapexternal where start points coincide.
git-svn-id: svn://localhost/ardour2/trunk@2576 d708f5d6-7413-0410-9779-e7cbd77b26cf
2007-10-26 09:32:24 -04:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-02-16 02:04:27 -05:00
|
|
|
while (used_playlists.size() > 0) {
|
use filechooser widget in export dialog, selected files set format combos, hide progress bar until use in export dialog, speed up 'separate regions in range' operation on larger sessions, ruler scale now calculated separately to mark generation, fix for non-stacked layering regression, try not to generate 'buried' crossfades, use playlist->freeze() to speed up copying/moving regions on large playlists (not done for undo), width dependent items now reset on regionview init, get rid of jack_port_ensure_monitor check, remove audiosourse _length (only source has a length.. i think), make overlapend differ to overlapexternal where start points coincide.
git-svn-id: svn://localhost/ardour2/trunk@2576 d708f5d6-7413-0410-9779-e7cbd77b26cf
2007-10-26 09:32:24 -04:00
|
|
|
list <boost::shared_ptr<Playlist > >::iterator i = used_playlists.begin();
|
|
|
|
(*i)->thaw();
|
|
|
|
used_playlists.pop_front();
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
boost::shared_ptr<Region>
|
2009-07-21 11:55:17 -04:00
|
|
|
Editor::select_region_for_operation (int /*dir*/, TimeAxisView **tv)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2006-07-23 08:03:19 -04:00
|
|
|
RegionView* rv;
|
2006-08-29 17:21:48 -04:00
|
|
|
boost::shared_ptr<Region> region;
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t start = 0;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (selection->time.start () == selection->time.end_frame ()) {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
/* no current selection-> is there a selected regionview? */
|
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
if (selection->regions.empty()) {
|
2006-08-29 17:21:48 -04:00
|
|
|
return region;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
if (!selection->regions.empty()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
rv = *(selection->regions.begin());
|
2009-07-09 13:58:13 -04:00
|
|
|
(*tv) = &rv->get_time_axis_view();
|
2006-08-29 17:21:48 -04:00
|
|
|
region = rv->region();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
} else if (!selection->tracks.empty()) {
|
|
|
|
|
|
|
|
(*tv) = selection->tracks.front();
|
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
RouteTimeAxisView* rtv;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
if ((rtv = dynamic_cast<RouteTimeAxisView*> (*tv)) != 0) {
|
2007-01-09 18:24:54 -05:00
|
|
|
boost::shared_ptr<Playlist> pl;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
if ((pl = rtv->playlist()) == 0) {
|
2006-08-29 17:21:48 -04:00
|
|
|
return region;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
region = pl->top_region_at (start);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
return region;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
|
|
|
Editor::extend_selection_to_end_of_region (bool next)
|
|
|
|
{
|
2009-07-09 13:58:13 -04:00
|
|
|
TimeAxisView *tv;
|
2006-08-29 17:21:48 -04:00
|
|
|
boost::shared_ptr<Region> region;
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t start;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if ((region = select_region_for_operation (next ? 1 : 0, &tv)) == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (region && selection->time.start () == selection->time.end_frame ()) {
|
|
|
|
start = region->position();
|
|
|
|
} else {
|
|
|
|
start = selection->time.start ();
|
|
|
|
}
|
|
|
|
|
|
|
|
begin_reversible_command (_("extend selection"));
|
2009-12-13 16:27:19 -05:00
|
|
|
selection->set (start, region->position() + region->length());
|
2005-09-25 14:42:24 -04:00
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::extend_selection_to_start_of_region (bool previous)
|
|
|
|
{
|
2009-07-09 13:58:13 -04:00
|
|
|
TimeAxisView *tv;
|
2006-08-29 17:21:48 -04:00
|
|
|
boost::shared_ptr<Region> region;
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t end;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if ((region = select_region_for_operation (previous ? -1 : 0, &tv)) == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (region && selection->time.start () == selection->time.end_frame ()) {
|
|
|
|
end = region->position() + region->length();
|
|
|
|
} else {
|
|
|
|
end = selection->time.end_frame ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Try to leave the selection with the same route if possible */
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
begin_reversible_command (_("extend selection"));
|
2009-12-13 16:27:19 -05:00
|
|
|
selection->set (region->position(), end);
|
2005-09-25 14:42:24 -04:00
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
|
2008-01-18 22:49:52 -05:00
|
|
|
bool
|
|
|
|
Editor::nudge_forward_release (GdkEventButton* ev)
|
|
|
|
{
|
|
|
|
if (ev->state & Keyboard::PrimaryModifier) {
|
|
|
|
nudge_forward (false, true);
|
|
|
|
} else {
|
|
|
|
nudge_forward (false, false);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Editor::nudge_backward_release (GdkEventButton* ev)
|
|
|
|
{
|
|
|
|
if (ev->state & Keyboard::PrimaryModifier) {
|
|
|
|
nudge_backward (false, true);
|
|
|
|
} else {
|
|
|
|
nudge_backward (false, false);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
void
|
2008-01-18 22:49:52 -05:00
|
|
|
Editor::nudge_forward (bool next, bool force_playhead)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t distance;
|
|
|
|
nframes64_t next_distance;
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) return;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
if (!force_playhead && !rs.empty()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
begin_reversible_command (_("nudge regions forward"));
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
|
2006-08-29 17:21:48 -04:00
|
|
|
boost::shared_ptr<Region> r ((*i)->region());
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
distance = get_nudge_distance (r->position(), next_distance);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (next) {
|
|
|
|
distance = next_distance;
|
|
|
|
}
|
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
r->clear_history ();
|
2006-08-29 17:21:48 -04:00
|
|
|
r->set_position (r->position() + distance, this);
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command (new StatefulDiffCommand (r));
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
commit_reversible_command ();
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-01-18 22:49:52 -05:00
|
|
|
} else if (!force_playhead && !selection->markers.empty()) {
|
2008-01-10 16:20:59 -05:00
|
|
|
|
|
|
|
bool is_start;
|
|
|
|
|
2008-09-19 10:38:46 -04:00
|
|
|
begin_reversible_command (_("nudge location forward"));
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-09-19 10:38:46 -04:00
|
|
|
for (MarkerSelection::iterator i = selection->markers.begin(); i != selection->markers.end(); ++i) {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-09-19 10:38:46 -04:00
|
|
|
Location* loc = find_location_from_marker ((*i), is_start);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-09-19 10:38:46 -04:00
|
|
|
if (loc) {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-09-19 10:38:46 -04:00
|
|
|
XMLNode& before (loc->get_state());
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-09-19 10:38:46 -04:00
|
|
|
if (is_start) {
|
|
|
|
distance = get_nudge_distance (loc->start(), next_distance);
|
|
|
|
if (next) {
|
|
|
|
distance = next_distance;
|
|
|
|
}
|
|
|
|
if (max_frames - distance > loc->start() + loc->length()) {
|
|
|
|
loc->set_start (loc->start() + distance);
|
|
|
|
} else {
|
|
|
|
loc->set_start (max_frames - loc->length());
|
|
|
|
}
|
2008-01-10 16:20:59 -05:00
|
|
|
} else {
|
2008-09-19 10:38:46 -04:00
|
|
|
distance = get_nudge_distance (loc->end(), next_distance);
|
|
|
|
if (next) {
|
|
|
|
distance = next_distance;
|
|
|
|
}
|
|
|
|
if (max_frames - distance > loc->end()) {
|
|
|
|
loc->set_end (loc->end() + distance);
|
|
|
|
} else {
|
|
|
|
loc->set_end (max_frames);
|
|
|
|
}
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
2008-09-19 10:38:46 -04:00
|
|
|
XMLNode& after (loc->get_state());
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->add_command (new MementoCommand<Location>(*loc, &before, &after));
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-09-19 10:38:46 -04:00
|
|
|
commit_reversible_command ();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
|
|
|
distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_locate (playhead_cursor->current_frame + distance);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
2008-01-18 22:49:52 -05:00
|
|
|
Editor::nudge_backward (bool next, bool force_playhead)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t distance;
|
|
|
|
nframes64_t next_distance;
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) return;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
if (!force_playhead && !rs.empty()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
begin_reversible_command (_("nudge regions backward"));
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
|
2006-08-29 17:21:48 -04:00
|
|
|
boost::shared_ptr<Region> r ((*i)->region());
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
distance = get_nudge_distance (r->position(), next_distance);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (next) {
|
|
|
|
distance = next_distance;
|
|
|
|
}
|
2010-03-02 13:05:26 -05:00
|
|
|
|
|
|
|
r->clear_history ();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
if (r->position() > distance) {
|
|
|
|
r->set_position (r->position() - distance, this);
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2006-08-29 17:21:48 -04:00
|
|
|
r->set_position (0, this);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command (new StatefulDiffCommand (r));
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
commit_reversible_command ();
|
|
|
|
|
2008-01-18 22:49:52 -05:00
|
|
|
} else if (!force_playhead && !selection->markers.empty()) {
|
2008-01-10 16:20:59 -05:00
|
|
|
|
|
|
|
bool is_start;
|
|
|
|
|
2008-09-19 10:38:46 -04:00
|
|
|
begin_reversible_command (_("nudge location forward"));
|
2008-01-10 16:20:59 -05:00
|
|
|
|
2008-09-19 10:38:46 -04:00
|
|
|
for (MarkerSelection::iterator i = selection->markers.begin(); i != selection->markers.end(); ++i) {
|
2008-01-10 16:20:59 -05:00
|
|
|
|
2008-09-19 10:38:46 -04:00
|
|
|
Location* loc = find_location_from_marker ((*i), is_start);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-09-19 10:38:46 -04:00
|
|
|
if (loc) {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-09-19 10:38:46 -04:00
|
|
|
XMLNode& before (loc->get_state());
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-09-19 10:38:46 -04:00
|
|
|
if (is_start) {
|
|
|
|
distance = get_nudge_distance (loc->start(), next_distance);
|
|
|
|
if (next) {
|
|
|
|
distance = next_distance;
|
|
|
|
}
|
|
|
|
if (distance < loc->start()) {
|
|
|
|
loc->set_start (loc->start() - distance);
|
|
|
|
} else {
|
|
|
|
loc->set_start (0);
|
|
|
|
}
|
2008-01-10 16:20:59 -05:00
|
|
|
} else {
|
2008-09-19 10:38:46 -04:00
|
|
|
distance = get_nudge_distance (loc->end(), next_distance);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-09-19 10:38:46 -04:00
|
|
|
if (next) {
|
|
|
|
distance = next_distance;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-09-19 10:38:46 -04:00
|
|
|
if (distance < loc->end() - loc->length()) {
|
|
|
|
loc->set_end (loc->end() - distance);
|
|
|
|
} else {
|
|
|
|
loc->set_end (loc->length());
|
|
|
|
}
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-09-19 10:38:46 -04:00
|
|
|
XMLNode& after (loc->get_state());
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->add_command (new MementoCommand<Location>(*loc, &before, &after));
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
}
|
2008-09-19 10:38:46 -04:00
|
|
|
|
|
|
|
commit_reversible_command ();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
|
|
|
|
|
|
|
distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
|
|
|
|
|
|
|
|
if (playhead_cursor->current_frame > distance) {
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_locate (playhead_cursor->current_frame - distance);
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->goto_start();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::nudge_forward_capture_offset ()
|
|
|
|
{
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t distance;
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) return;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
if (!rs.empty()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
begin_reversible_command (_("nudge forward"));
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
distance = _session->worst_output_latency();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
|
2006-08-29 17:21:48 -04:00
|
|
|
boost::shared_ptr<Region> r ((*i)->region());
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
r->clear_history ();
|
2006-08-29 17:21:48 -04:00
|
|
|
r->set_position (r->position() + distance, this);
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command(new StatefulDiffCommand (r));
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
commit_reversible_command ();
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
|
|
|
Editor::nudge_backward_capture_offset ()
|
|
|
|
{
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t distance;
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) return;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
if (!rs.empty()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
begin_reversible_command (_("nudge forward"));
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
distance = _session->worst_output_latency();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
|
2006-08-29 17:21:48 -04:00
|
|
|
boost::shared_ptr<Region> r ((*i)->region());
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
r->clear_history ();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
if (r->position() > distance) {
|
|
|
|
r->set_position (r->position() - distance, this);
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2006-08-29 17:21:48 -04:00
|
|
|
r->set_position (0, this);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command(new StatefulDiffCommand (r));
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* DISPLAY MOTION */
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::move_to_start ()
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->goto_start ();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::move_to_end ()
|
|
|
|
{
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_locate (_session->current_end_frame());
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::build_region_boundary_cache ()
|
|
|
|
{
|
2010-07-06 07:33:27 -04:00
|
|
|
framepos_t pos = 0;
|
2007-04-12 19:20:37 -04:00
|
|
|
vector<RegionPoint> interesting_points;
|
2006-08-29 17:21:48 -04:00
|
|
|
boost::shared_ptr<Region> r;
|
2005-09-25 14:42:24 -04:00
|
|
|
TrackViewList tracks;
|
2007-04-12 19:20:37 -04:00
|
|
|
bool at_end = false;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
region_boundary_cache.clear ();
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (_session == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-10-26 19:43:04 -04:00
|
|
|
switch (_snap_type) {
|
2005-09-25 14:42:24 -04:00
|
|
|
case SnapToRegionStart:
|
2007-04-12 19:20:37 -04:00
|
|
|
interesting_points.push_back (Start);
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
case SnapToRegionEnd:
|
2007-04-12 19:20:37 -04:00
|
|
|
interesting_points.push_back (End);
|
2009-10-14 12:10:01 -04:00
|
|
|
break;
|
2005-09-25 14:42:24 -04:00
|
|
|
case SnapToRegionSync:
|
2007-04-12 19:20:37 -04:00
|
|
|
interesting_points.push_back (SyncPoint);
|
2009-10-14 12:10:01 -04:00
|
|
|
break;
|
2005-09-25 14:42:24 -04:00
|
|
|
case SnapToRegionBoundary:
|
2007-04-12 19:20:37 -04:00
|
|
|
interesting_points.push_back (Start);
|
|
|
|
interesting_points.push_back (End);
|
2009-10-14 12:10:01 -04:00
|
|
|
break;
|
2005-09-25 14:42:24 -04:00
|
|
|
default:
|
2009-10-26 19:43:04 -04:00
|
|
|
fatal << string_compose (_("build_region_boundary_cache called with snap_type = %1"), _snap_type) << endmsg;
|
2005-09-25 14:42:24 -04:00
|
|
|
/*NOTREACHED*/
|
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
TimeAxisView *ontrack = 0;
|
2007-04-12 19:20:37 -04:00
|
|
|
TrackViewList tlist;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
if (!selection->tracks.empty()) {
|
|
|
|
tlist = selection->tracks;
|
|
|
|
} else {
|
|
|
|
tlist = track_views;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
while (pos < _session->current_end_frame() && !at_end) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2010-07-06 07:33:27 -04:00
|
|
|
framepos_t rpos;
|
|
|
|
framepos_t lpos = max_frames;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
for (vector<RegionPoint>::iterator p = interesting_points.begin(); p != interesting_points.end(); ++p) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
if ((r = find_next_region (pos, *p, 1, tlist, &ontrack)) == 0) {
|
2007-10-11 18:07:47 -04:00
|
|
|
if (*p == interesting_points.back()) {
|
|
|
|
at_end = true;
|
|
|
|
}
|
2007-04-12 19:20:37 -04:00
|
|
|
/* move to next point type */
|
|
|
|
continue;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
switch (*p) {
|
|
|
|
case Start:
|
|
|
|
rpos = r->first_frame();
|
|
|
|
break;
|
2008-01-10 16:20:59 -05:00
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
case End:
|
|
|
|
rpos = r->last_frame();
|
2009-10-14 12:10:01 -04:00
|
|
|
break;
|
2008-01-10 16:20:59 -05:00
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
case SyncPoint:
|
2009-04-15 14:04:23 -04:00
|
|
|
rpos = r->sync_position ();
|
|
|
|
//r->adjust_to_sync (r->first_frame());
|
2007-04-12 19:20:37 -04:00
|
|
|
break;
|
2008-01-10 16:20:59 -05:00
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
default:
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
float speed = 1.0f;
|
2009-07-09 13:58:13 -04:00
|
|
|
RouteTimeAxisView *rtav;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
if (ontrack != 0 && (rtav = dynamic_cast<RouteTimeAxisView*>(ontrack)) != 0 ) {
|
2010-04-21 16:42:22 -04:00
|
|
|
if (rtav->track() != 0) {
|
|
|
|
speed = rtav->track()->speed();
|
2007-04-12 19:20:37 -04:00
|
|
|
}
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
rpos = track_frame_to_session_frame (rpos, speed);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
if (rpos < lpos) {
|
|
|
|
lpos = rpos;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
/* prevent duplicates, but we don't use set<> because we want to be able
|
|
|
|
to sort later.
|
|
|
|
*/
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2010-07-06 07:33:27 -04:00
|
|
|
vector<framepos_t>::iterator ri;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
for (ri = region_boundary_cache.begin(); ri != region_boundary_cache.end(); ++ri) {
|
|
|
|
if (*ri == rpos) {
|
|
|
|
break;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
if (ri == region_boundary_cache.end()) {
|
|
|
|
region_boundary_cache.push_back (rpos);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
pos = lpos + 1;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2007-04-12 19:20:37 -04:00
|
|
|
|
|
|
|
/* finally sort to be sure that the order is correct */
|
|
|
|
|
|
|
|
sort (region_boundary_cache.begin(), region_boundary_cache.end());
|
2010-07-06 07:33:27 -04:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
boost::shared_ptr<Region>
|
2010-07-06 07:33:27 -04:00
|
|
|
Editor::find_next_region (framepos_t frame, RegionPoint point, int32_t dir, TrackViewList& tracks, TimeAxisView **ontrack)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
TrackViewList::iterator i;
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t closest = max_frames;
|
2006-08-29 17:21:48 -04:00
|
|
|
boost::shared_ptr<Region> ret;
|
2010-07-06 07:33:27 -04:00
|
|
|
framepos_t rpos = 0;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
float track_speed;
|
2010-07-06 07:33:27 -04:00
|
|
|
framepos_t track_frame;
|
2009-07-09 13:58:13 -04:00
|
|
|
RouteTimeAxisView *rtav;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
for (i = tracks.begin(); i != tracks.end(); ++i) {
|
|
|
|
|
2010-07-06 07:33:27 -04:00
|
|
|
framecnt_t distance;
|
2006-08-29 17:21:48 -04:00
|
|
|
boost::shared_ptr<Region> r;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
track_speed = 1.0f;
|
2009-07-09 13:58:13 -04:00
|
|
|
if ( (rtav = dynamic_cast<RouteTimeAxisView*>(*i)) != 0 ) {
|
2010-04-21 16:42:22 -04:00
|
|
|
if (rtav->track()!=0)
|
|
|
|
track_speed = rtav->track()->speed();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2005-11-14 10:44:23 -05:00
|
|
|
track_frame = session_frame_to_track_frame(frame, track_speed);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if ((r = (*i)->find_next_region (track_frame, point, dir)) == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (point) {
|
|
|
|
case Start:
|
|
|
|
rpos = r->first_frame ();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case End:
|
|
|
|
rpos = r->last_frame ();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SyncPoint:
|
2009-04-15 14:04:23 -04:00
|
|
|
rpos = r->sync_position ();
|
|
|
|
// r->adjust_to_sync (r->first_frame());
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
}
|
2008-01-10 16:20:59 -05:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
// rpos is a "track frame", converting it to "_session frame"
|
2005-11-14 10:44:23 -05:00
|
|
|
rpos = track_frame_to_session_frame(rpos, track_speed);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (rpos > frame) {
|
|
|
|
distance = rpos - frame;
|
|
|
|
} else {
|
|
|
|
distance = frame - rpos;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (distance < closest) {
|
|
|
|
closest = distance;
|
|
|
|
if (ontrack != 0)
|
|
|
|
*ontrack = (*i);
|
|
|
|
ret = r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-07-06 07:33:27 -04:00
|
|
|
framepos_t
|
|
|
|
Editor::find_next_region_boundary (framepos_t pos, int32_t dir, const TrackViewList& tracks)
|
2008-01-10 16:20:59 -05:00
|
|
|
{
|
2010-07-06 07:33:27 -04:00
|
|
|
framecnt_t distance = max_frames;
|
|
|
|
framepos_t current_nearest = -1;
|
2009-04-15 14:04:23 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
for (TrackViewList::const_iterator i = tracks.begin(); i != tracks.end(); ++i) {
|
2010-07-06 07:33:27 -04:00
|
|
|
framepos_t contender;
|
|
|
|
framecnt_t d;
|
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
|
2008-01-10 16:20:59 -05:00
|
|
|
|
|
|
|
if (!rtv) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((contender = rtv->find_next_region_boundary (pos, dir)) < 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
d = ::llabs (pos - contender);
|
|
|
|
|
|
|
|
if (d < distance) {
|
|
|
|
current_nearest = contender;
|
|
|
|
distance = d;
|
|
|
|
}
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
return current_nearest;
|
|
|
|
}
|
|
|
|
|
2010-07-06 07:33:27 -04:00
|
|
|
framepos_t
|
|
|
|
Editor::get_region_boundary (framepos_t pos, int32_t dir, bool with_selection, bool only_onscreen)
|
2009-04-15 14:04:23 -04:00
|
|
|
{
|
2010-07-06 07:33:27 -04:00
|
|
|
framepos_t target;
|
2009-04-15 14:04:23 -04:00
|
|
|
TrackViewList tvl;
|
|
|
|
|
|
|
|
if (with_selection && Config->get_region_boundaries_from_selected_tracks()) {
|
|
|
|
|
|
|
|
if (!selection->tracks.empty()) {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-04-15 14:04:23 -04:00
|
|
|
target = find_next_region_boundary (pos, dir, selection->tracks);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-04-15 14:04:23 -04:00
|
|
|
} else {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-04-15 14:04:23 -04:00
|
|
|
if (only_onscreen || Config->get_region_boundaries_from_onscreen_tracks()) {
|
|
|
|
get_onscreen_tracks (tvl);
|
|
|
|
target = find_next_region_boundary (pos, dir, tvl);
|
|
|
|
} else {
|
|
|
|
target = find_next_region_boundary (pos, dir, track_views);
|
|
|
|
}
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-04-15 14:04:23 -04:00
|
|
|
} else {
|
|
|
|
|
|
|
|
if (only_onscreen || Config->get_region_boundaries_from_onscreen_tracks()) {
|
|
|
|
get_onscreen_tracks (tvl);
|
|
|
|
target = find_next_region_boundary (pos, dir, tvl);
|
|
|
|
} else {
|
|
|
|
target = find_next_region_boundary (pos, dir, track_views);
|
|
|
|
}
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-04-15 14:04:23 -04:00
|
|
|
return target;
|
|
|
|
}
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
void
|
2009-04-15 14:04:23 -04:00
|
|
|
Editor::cursor_to_region_boundary (bool with_selection, int32_t dir)
|
2008-01-10 16:20:59 -05:00
|
|
|
{
|
2009-04-15 14:04:23 -04:00
|
|
|
nframes64_t pos = playhead_cursor->current_frame;
|
2008-01-10 16:20:59 -05:00
|
|
|
nframes64_t target;
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) {
|
2008-01-10 16:20:59 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// so we don't find the current region again..
|
|
|
|
if (dir > 0 || pos > 0) {
|
|
|
|
pos += dir;
|
|
|
|
}
|
|
|
|
|
2009-04-15 14:04:23 -04:00
|
|
|
if ((target = get_region_boundary (pos, dir, with_selection, false)) < 0) {
|
2008-01-10 16:20:59 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_locate (target);
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-04-15 14:04:23 -04:00
|
|
|
Editor::cursor_to_next_region_boundary (bool with_selection)
|
2008-01-10 16:20:59 -05:00
|
|
|
{
|
2009-04-15 14:04:23 -04:00
|
|
|
cursor_to_region_boundary (with_selection, 1);
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-04-15 14:04:23 -04:00
|
|
|
Editor::cursor_to_previous_region_boundary (bool with_selection)
|
2008-01-10 16:20:59 -05:00
|
|
|
{
|
2009-04-15 14:04:23 -04:00
|
|
|
cursor_to_region_boundary (with_selection, -1);
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
2009-05-30 14:25:59 -04:00
|
|
|
Editor::cursor_to_region_point (EditorCursor* cursor, RegionPoint point, int32_t dir)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2006-08-29 17:21:48 -04:00
|
|
|
boost::shared_ptr<Region> r;
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t pos = cursor->current_frame;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
TimeAxisView *ontrack = 0;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
// so we don't find the current region again..
|
|
|
|
if (dir>0 || pos>0)
|
|
|
|
pos+=dir;
|
|
|
|
|
|
|
|
if (!selection->tracks.empty()) {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
r = find_next_region (pos, point, dir, selection->tracks, &ontrack);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2006-08-16 16:36:14 -04:00
|
|
|
} else if (clicked_axisview) {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
TrackViewList t;
|
2006-08-16 16:36:14 -04:00
|
|
|
t.push_back (clicked_axisview);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
r = find_next_region (pos, point, dir, t, &ontrack);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
r = find_next_region (pos, point, dir, track_views, &ontrack);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (r == 0) {
|
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
switch (point){
|
|
|
|
case Start:
|
|
|
|
pos = r->first_frame ();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case End:
|
|
|
|
pos = r->last_frame ();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SyncPoint:
|
2009-04-15 14:04:23 -04:00
|
|
|
pos = r->sync_position ();
|
|
|
|
// r->adjust_to_sync (r->first_frame());
|
2009-10-14 12:10:01 -04:00
|
|
|
break;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
float speed = 1.0f;
|
2009-07-09 13:58:13 -04:00
|
|
|
RouteTimeAxisView *rtav;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
if ( ontrack != 0 && (rtav = dynamic_cast<RouteTimeAxisView*>(ontrack)) != 0 ) {
|
2010-04-21 16:42:22 -04:00
|
|
|
if (rtav->track() != 0) {
|
|
|
|
speed = rtav->track()->speed();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-14 10:44:23 -05:00
|
|
|
pos = track_frame_to_session_frame(pos, speed);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (cursor == playhead_cursor) {
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_locate (pos);
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
|
|
|
cursor->set_position (pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-05-30 14:25:59 -04:00
|
|
|
Editor::cursor_to_next_region_point (EditorCursor* cursor, RegionPoint point)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
cursor_to_region_point (cursor, point, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-05-30 14:25:59 -04:00
|
|
|
Editor::cursor_to_previous_region_point (EditorCursor* cursor, RegionPoint point)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
cursor_to_region_point (cursor, point, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-05-30 14:25:59 -04:00
|
|
|
Editor::cursor_to_selection_start (EditorCursor *cursor)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t pos = 0;
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
switch (mouse_mode) {
|
|
|
|
case MouseObject:
|
2008-02-16 17:43:18 -05:00
|
|
|
if (!rs.empty()) {
|
|
|
|
pos = rs.start();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseRange:
|
|
|
|
if (!selection->time.empty()) {
|
|
|
|
pos = selection->time.start ();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cursor == playhead_cursor) {
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_locate (pos);
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
|
|
|
cursor->set_position (pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-05-30 14:25:59 -04:00
|
|
|
Editor::cursor_to_selection_end (EditorCursor *cursor)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t pos = 0;
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
switch (mouse_mode) {
|
|
|
|
case MouseObject:
|
2008-02-16 17:43:18 -05:00
|
|
|
if (!rs.empty()) {
|
|
|
|
pos = rs.end_frame();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseRange:
|
|
|
|
if (!selection->time.empty()) {
|
|
|
|
pos = selection->time.end_frame ();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cursor == playhead_cursor) {
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_locate (pos);
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
|
|
|
cursor->set_position (pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
void
|
2009-04-15 14:04:23 -04:00
|
|
|
Editor::selected_marker_to_region_boundary (bool with_selection, int32_t dir)
|
2008-01-10 16:20:59 -05:00
|
|
|
{
|
|
|
|
nframes64_t target;
|
|
|
|
Location* loc;
|
|
|
|
bool ignored;
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) {
|
2008-01-10 16:20:59 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (selection->markers.empty()) {
|
|
|
|
nframes64_t mouse;
|
|
|
|
bool ignored;
|
|
|
|
|
|
|
|
if (!mouse_frame (mouse, ignored)) {
|
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
add_location_mark (mouse);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((loc = find_location_from_marker (selection->markers.front(), ignored)) == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nframes64_t pos = loc->start();
|
|
|
|
|
|
|
|
// so we don't find the current region again..
|
|
|
|
if (dir > 0 || pos > 0) {
|
|
|
|
pos += dir;
|
|
|
|
}
|
|
|
|
|
2009-04-15 14:04:23 -04:00
|
|
|
if ((target = get_region_boundary (pos, dir, with_selection, false)) < 0) {
|
2008-01-10 16:20:59 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
loc->move_to (target);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-04-15 14:04:23 -04:00
|
|
|
Editor::selected_marker_to_next_region_boundary (bool with_selection)
|
2008-01-10 16:20:59 -05:00
|
|
|
{
|
2009-04-15 14:04:23 -04:00
|
|
|
selected_marker_to_region_boundary (with_selection, 1);
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-04-15 14:04:23 -04:00
|
|
|
Editor::selected_marker_to_previous_region_boundary (bool with_selection)
|
2008-01-10 16:20:59 -05:00
|
|
|
{
|
2009-04-15 14:04:23 -04:00
|
|
|
selected_marker_to_region_boundary (with_selection, -1);
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::selected_marker_to_region_point (RegionPoint point, int32_t dir)
|
2007-11-12 17:23:01 -05:00
|
|
|
{
|
|
|
|
boost::shared_ptr<Region> r;
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t pos;
|
2007-11-12 17:23:01 -05:00
|
|
|
Location* loc;
|
|
|
|
bool ignored;
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session || selection->markers.empty()) {
|
2007-11-12 17:23:01 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((loc = find_location_from_marker (selection->markers.front(), ignored)) == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
TimeAxisView *ontrack = 0;
|
2007-11-12 17:23:01 -05:00
|
|
|
|
|
|
|
pos = loc->start();
|
|
|
|
|
|
|
|
// so we don't find the current region again..
|
|
|
|
if (dir>0 || pos>0)
|
|
|
|
pos+=dir;
|
|
|
|
|
|
|
|
if (!selection->tracks.empty()) {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
r = find_next_region (pos, point, dir, selection->tracks, &ontrack);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
} else {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
r = find_next_region (pos, point, dir, track_views, &ontrack);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (r == 0) {
|
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
switch (point){
|
|
|
|
case Start:
|
|
|
|
pos = r->first_frame ();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case End:
|
|
|
|
pos = r->last_frame ();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SyncPoint:
|
|
|
|
pos = r->adjust_to_sync (r->first_frame());
|
2009-10-14 12:10:01 -04:00
|
|
|
break;
|
2007-11-12 17:23:01 -05:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
float speed = 1.0f;
|
2009-07-09 13:58:13 -04:00
|
|
|
RouteTimeAxisView *rtav;
|
2007-11-12 17:23:01 -05:00
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
if (ontrack != 0 && (rtav = dynamic_cast<RouteTimeAxisView*>(ontrack)) != 0) {
|
2010-04-21 16:42:22 -04:00
|
|
|
if (rtav->track() != 0) {
|
|
|
|
speed = rtav->track()->speed();
|
2007-11-12 17:23:01 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pos = track_frame_to_session_frame(pos, speed);
|
|
|
|
|
|
|
|
loc->move_to (pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-01-10 16:20:59 -05:00
|
|
|
Editor::selected_marker_to_next_region_point (RegionPoint point)
|
2007-11-12 17:23:01 -05:00
|
|
|
{
|
2008-01-10 16:20:59 -05:00
|
|
|
selected_marker_to_region_point (point, 1);
|
2007-11-12 17:23:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-01-10 16:20:59 -05:00
|
|
|
Editor::selected_marker_to_previous_region_point (RegionPoint point)
|
2007-11-12 17:23:01 -05:00
|
|
|
{
|
2008-01-10 16:20:59 -05:00
|
|
|
selected_marker_to_region_point (point, -1);
|
2007-11-12 17:23:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-01-10 16:20:59 -05:00
|
|
|
Editor::selected_marker_to_selection_start ()
|
2007-11-12 17:23:01 -05:00
|
|
|
{
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t pos = 0;
|
2007-11-12 17:23:01 -05:00
|
|
|
Location* loc;
|
|
|
|
bool ignored;
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session || selection->markers.empty()) {
|
2007-11-12 17:23:01 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((loc = find_location_from_marker (selection->markers.front(), ignored)) == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
switch (mouse_mode) {
|
|
|
|
case MouseObject:
|
2008-02-16 17:43:18 -05:00
|
|
|
if (!rs.empty()) {
|
|
|
|
pos = rs.start();
|
2007-11-12 17:23:01 -05:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseRange:
|
|
|
|
if (!selection->time.empty()) {
|
|
|
|
pos = selection->time.start ();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
loc->move_to (pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-01-10 16:20:59 -05:00
|
|
|
Editor::selected_marker_to_selection_end ()
|
2007-11-12 17:23:01 -05:00
|
|
|
{
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t pos = 0;
|
2007-11-12 17:23:01 -05:00
|
|
|
Location* loc;
|
|
|
|
bool ignored;
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session || selection->markers.empty()) {
|
2007-11-12 17:23:01 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((loc = find_location_from_marker (selection->markers.front(), ignored)) == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
switch (mouse_mode) {
|
|
|
|
case MouseObject:
|
2008-02-16 17:43:18 -05:00
|
|
|
if (!rs.empty()) {
|
|
|
|
pos = rs.end_frame();
|
2007-11-12 17:23:01 -05:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseRange:
|
|
|
|
if (!selection->time.empty()) {
|
|
|
|
pos = selection->time.end_frame ();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
loc->move_to (pos);
|
|
|
|
}
|
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
void
|
|
|
|
Editor::scroll_playhead (bool forward)
|
|
|
|
{
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t pos = playhead_cursor->current_frame;
|
|
|
|
nframes64_t delta = (nframes64_t) floor (current_page_frames() / 0.8);
|
2007-01-28 12:44:13 -05:00
|
|
|
|
|
|
|
if (forward) {
|
|
|
|
if (pos == max_frames) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pos < max_frames - delta) {
|
|
|
|
pos += delta ;
|
|
|
|
} else {
|
|
|
|
pos = max_frames;
|
2009-10-14 12:10:01 -04:00
|
|
|
}
|
2007-01-28 12:44:13 -05:00
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if (pos == 0) {
|
|
|
|
return;
|
2009-10-14 12:10:01 -04:00
|
|
|
}
|
2007-01-28 12:44:13 -05:00
|
|
|
|
|
|
|
if (pos > delta) {
|
|
|
|
pos -= delta;
|
|
|
|
} else {
|
|
|
|
pos = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_locate (pos);
|
2007-01-28 12:44:13 -05:00
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
|
|
|
Editor::playhead_backward ()
|
|
|
|
{
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t pos;
|
|
|
|
nframes64_t cnt;
|
2005-09-25 14:42:24 -04:00
|
|
|
float prefix;
|
|
|
|
bool was_floating;
|
|
|
|
|
|
|
|
if (get_prefix (prefix, was_floating)) {
|
|
|
|
cnt = 1;
|
|
|
|
} else {
|
|
|
|
if (was_floating) {
|
2009-12-17 13:24:23 -05:00
|
|
|
cnt = (nframes64_t) floor (prefix * _session->frame_rate ());
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2008-09-10 11:03:30 -04:00
|
|
|
cnt = (nframes64_t) prefix;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pos = playhead_cursor->current_frame;
|
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
if ((nframes64_t) pos < cnt) {
|
2005-09-25 14:42:24 -04:00
|
|
|
pos = 0;
|
|
|
|
} else {
|
|
|
|
pos -= cnt;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
/* XXX this is completely insane. with the current buffering
|
|
|
|
design, we'll force a complete track buffer flush and
|
|
|
|
reload, just to move 1 sample !!!
|
|
|
|
*/
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_locate (pos);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::playhead_forward ()
|
|
|
|
{
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t pos;
|
|
|
|
nframes64_t cnt;
|
2005-09-25 14:42:24 -04:00
|
|
|
bool was_floating;
|
|
|
|
float prefix;
|
|
|
|
|
|
|
|
if (get_prefix (prefix, was_floating)) {
|
|
|
|
cnt = 1;
|
|
|
|
} else {
|
|
|
|
if (was_floating) {
|
2009-12-17 13:24:23 -05:00
|
|
|
cnt = (nframes64_t) floor (prefix * _session->frame_rate ());
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2008-09-10 11:03:30 -04:00
|
|
|
cnt = (nframes64_t) floor (prefix);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pos = playhead_cursor->current_frame;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
/* XXX this is completely insane. with the current buffering
|
|
|
|
design, we'll force a complete track buffer flush and
|
|
|
|
reload, just to move 1 sample !!!
|
|
|
|
*/
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_locate (pos+cnt);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::cursor_align (bool playhead_to_edit)
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) {
|
2007-11-12 17:23:01 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (playhead_to_edit) {
|
2007-11-12 17:23:01 -05:00
|
|
|
|
|
|
|
if (selection->markers.empty()) {
|
|
|
|
return;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_locate (selection->markers.front()->position(), _session->transport_rolling());
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2007-11-12 17:23:01 -05:00
|
|
|
/* move selected markers to playhead */
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
for (MarkerSelection::iterator i = selection->markers.begin(); i != selection->markers.end(); ++i) {
|
|
|
|
bool ignored;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
Location* loc = find_location_from_marker (*i, ignored);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
if (loc->is_mark()) {
|
|
|
|
loc->set_start (playhead_cursor->current_frame);
|
|
|
|
} else {
|
|
|
|
loc->set (playhead_cursor->current_frame,
|
|
|
|
playhead_cursor->current_frame + loc->length());
|
|
|
|
}
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::edit_cursor_backward ()
|
|
|
|
{
|
2007-11-07 20:40:25 -05:00
|
|
|
nframes64_t pos;
|
|
|
|
nframes64_t cnt;
|
2005-09-25 14:42:24 -04:00
|
|
|
float prefix;
|
|
|
|
bool was_floating;
|
|
|
|
|
|
|
|
if (get_prefix (prefix, was_floating)) {
|
|
|
|
cnt = 1;
|
|
|
|
} else {
|
|
|
|
if (was_floating) {
|
2009-12-17 13:24:23 -05:00
|
|
|
cnt = (nframes64_t) floor (prefix * _session->frame_rate ());
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2008-09-10 11:03:30 -04:00
|
|
|
cnt = (nframes64_t) prefix;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-07 20:40:25 -05:00
|
|
|
if ((pos = get_preferred_edit_position()) < 0) {
|
|
|
|
return;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-11-07 20:40:25 -05:00
|
|
|
if (pos < cnt) {
|
2005-09-25 14:42:24 -04:00
|
|
|
pos = 0;
|
|
|
|
} else {
|
|
|
|
pos -= cnt;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
// EDIT CURSOR edit_cursor->set_position (pos);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::edit_cursor_forward ()
|
|
|
|
{
|
2008-09-10 11:03:30 -04:00
|
|
|
//nframes64_t pos;
|
|
|
|
nframes64_t cnt;
|
2005-09-25 14:42:24 -04:00
|
|
|
bool was_floating;
|
|
|
|
float prefix;
|
|
|
|
|
|
|
|
if (get_prefix (prefix, was_floating)) {
|
|
|
|
cnt = 1;
|
|
|
|
} else {
|
|
|
|
if (was_floating) {
|
2009-12-17 13:24:23 -05:00
|
|
|
cnt = (nframes64_t) floor (prefix * _session->frame_rate ());
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2008-09-10 11:03:30 -04:00
|
|
|
cnt = (nframes64_t) floor (prefix);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
// pos = edit_cursor->current_frame;
|
|
|
|
// EDIT CURSOR edit_cursor->set_position (pos+cnt);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::goto_frame ()
|
|
|
|
{
|
|
|
|
float prefix;
|
|
|
|
bool was_floating;
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t frame;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (get_prefix (prefix, was_floating)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (was_floating) {
|
2009-12-17 13:24:23 -05:00
|
|
|
frame = (nframes64_t) floor (prefix * _session->frame_rate());
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2008-09-10 11:03:30 -04:00
|
|
|
frame = (nframes64_t) floor (prefix);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_locate (frame);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::scroll_backward (float pages)
|
|
|
|
{
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t frame;
|
2009-06-13 13:52:51 -04:00
|
|
|
nframes64_t one_page = (nframes64_t) rint (_canvas_width * frames_per_unit);
|
2005-09-25 14:42:24 -04:00
|
|
|
bool was_floating;
|
|
|
|
float prefix;
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t cnt;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (get_prefix (prefix, was_floating)) {
|
2008-09-10 11:03:30 -04:00
|
|
|
cnt = (nframes64_t) floor (pages * one_page);
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
|
|
|
if (was_floating) {
|
2009-12-17 13:24:23 -05:00
|
|
|
cnt = (nframes64_t) floor (prefix * _session->frame_rate());
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2008-09-10 11:03:30 -04:00
|
|
|
cnt = (nframes64_t) floor (prefix * one_page);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (leftmost_frame < cnt) {
|
|
|
|
frame = 0;
|
|
|
|
} else {
|
|
|
|
frame = leftmost_frame - cnt;
|
|
|
|
}
|
|
|
|
|
2007-01-11 15:36:35 -05:00
|
|
|
reset_x_origin (frame);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::scroll_forward (float pages)
|
|
|
|
{
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t frame;
|
2009-06-13 13:52:51 -04:00
|
|
|
nframes64_t one_page = (nframes64_t) rint (_canvas_width * frames_per_unit);
|
2005-09-25 14:42:24 -04:00
|
|
|
bool was_floating;
|
|
|
|
float prefix;
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t cnt;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (get_prefix (prefix, was_floating)) {
|
2008-09-10 11:03:30 -04:00
|
|
|
cnt = (nframes64_t) floor (pages * one_page);
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
|
|
|
if (was_floating) {
|
2009-12-17 13:24:23 -05:00
|
|
|
cnt = (nframes64_t) floor (prefix * _session->frame_rate());
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2008-09-10 11:03:30 -04:00
|
|
|
cnt = (nframes64_t) floor (prefix * one_page);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-10-21 15:01:50 -04:00
|
|
|
if (max_frames - cnt < leftmost_frame) {
|
|
|
|
frame = max_frames - cnt;
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
|
|
|
frame = leftmost_frame + cnt;
|
|
|
|
}
|
|
|
|
|
2007-01-11 15:36:35 -05:00
|
|
|
reset_x_origin (frame);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::scroll_tracks_down ()
|
|
|
|
{
|
|
|
|
float prefix;
|
|
|
|
bool was_floating;
|
|
|
|
int cnt;
|
|
|
|
|
|
|
|
if (get_prefix (prefix, was_floating)) {
|
|
|
|
cnt = 1;
|
|
|
|
} else {
|
|
|
|
cnt = (int) floor (prefix);
|
|
|
|
}
|
|
|
|
|
2006-04-09 22:14:05 -04:00
|
|
|
double vert_value = vertical_adjustment.get_value() + (cnt *
|
|
|
|
vertical_adjustment.get_page_size());
|
2009-06-13 13:52:51 -04:00
|
|
|
if (vert_value > vertical_adjustment.get_upper() - _canvas_height) {
|
|
|
|
vert_value = vertical_adjustment.get_upper() - _canvas_height;
|
2006-04-09 22:14:05 -04:00
|
|
|
}
|
|
|
|
vertical_adjustment.set_value (vert_value);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::scroll_tracks_up ()
|
|
|
|
{
|
|
|
|
float prefix;
|
|
|
|
bool was_floating;
|
|
|
|
int cnt;
|
|
|
|
|
|
|
|
if (get_prefix (prefix, was_floating)) {
|
|
|
|
cnt = 1;
|
|
|
|
} else {
|
|
|
|
cnt = (int) floor (prefix);
|
|
|
|
}
|
|
|
|
|
2005-12-12 15:54:55 -05:00
|
|
|
vertical_adjustment.set_value (vertical_adjustment.get_value() - (cnt * vertical_adjustment.get_page_size()));
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::scroll_tracks_down_line ()
|
|
|
|
{
|
2009-12-01 13:38:24 -05:00
|
|
|
double vert_value = vertical_adjustment.get_value() + 60;
|
2006-04-09 22:14:05 -04:00
|
|
|
|
2009-12-01 13:38:24 -05:00
|
|
|
if (vert_value > vertical_adjustment.get_upper() - _canvas_height) {
|
|
|
|
vert_value = vertical_adjustment.get_upper() - _canvas_height;
|
2006-04-09 22:14:05 -04:00
|
|
|
}
|
2009-12-01 13:38:24 -05:00
|
|
|
|
|
|
|
vertical_adjustment.set_value (vert_value);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::scroll_tracks_up_line ()
|
|
|
|
{
|
2009-12-01 13:38:24 -05:00
|
|
|
reset_y_origin (vertical_adjustment.get_value() - 60);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ZOOM */
|
|
|
|
|
2009-08-24 18:28:00 -04:00
|
|
|
void
|
|
|
|
Editor::tav_zoom_step (bool coarser)
|
|
|
|
{
|
2009-12-11 18:29:48 -05:00
|
|
|
ENSURE_GUI_THREAD (*this, &Editor::temporal_zoom_step, coarser)
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-08-24 18:28:00 -04:00
|
|
|
_routes->suspend_redisplay ();
|
|
|
|
|
|
|
|
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
|
|
|
TimeAxisView *tv = (static_cast<TimeAxisView*>(*i));
|
|
|
|
tv->step_height (coarser);
|
|
|
|
}
|
|
|
|
|
|
|
|
_routes->resume_redisplay ();
|
2009-10-14 12:10:01 -04:00
|
|
|
}
|
2009-08-24 18:28:00 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
|
|
|
Editor::temporal_zoom_step (bool coarser)
|
|
|
|
{
|
2009-12-11 18:29:48 -05:00
|
|
|
ENSURE_GUI_THREAD (*this, &Editor::temporal_zoom_step, coarser)
|
2006-04-06 12:51:27 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
double nfpu;
|
|
|
|
|
|
|
|
nfpu = frames_per_unit;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
|
|
|
if (coarser) {
|
2006-09-18 23:29:16 -04:00
|
|
|
nfpu *= 1.61803399;
|
2009-10-14 12:10:01 -04:00
|
|
|
} else {
|
2006-09-18 23:29:16 -04:00
|
|
|
nfpu = max(1.0,(nfpu/1.61803399));
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
temporal_zoom (nfpu);
|
2009-10-14 12:10:01 -04:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
void
|
|
|
|
Editor::temporal_zoom (gdouble fpu)
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) return;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-11-07 20:40:25 -05:00
|
|
|
nframes64_t current_page = current_page_frames();
|
|
|
|
nframes64_t current_leftmost = leftmost_frame;
|
|
|
|
nframes64_t current_rightmost;
|
|
|
|
nframes64_t current_center;
|
2008-01-10 16:20:59 -05:00
|
|
|
nframes64_t new_page_size;
|
|
|
|
nframes64_t half_page_size;
|
2007-11-07 20:40:25 -05:00
|
|
|
nframes64_t leftmost_after_zoom = 0;
|
|
|
|
nframes64_t where;
|
|
|
|
bool in_track_canvas;
|
2005-09-25 14:42:24 -04:00
|
|
|
double nfpu;
|
2008-01-10 16:20:59 -05:00
|
|
|
double l;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-01-15 12:23:57 -05:00
|
|
|
/* XXX this limit is also in ::set_frames_per_unit() */
|
|
|
|
|
2010-03-16 11:33:04 -04:00
|
|
|
if (frames_per_unit <= 1.0 && fpu <= frames_per_unit) {
|
2008-01-15 12:23:57 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
nfpu = fpu;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-06-13 13:52:51 -04:00
|
|
|
new_page_size = (nframes64_t) floor (_canvas_width * nfpu);
|
2008-01-10 16:20:59 -05:00
|
|
|
half_page_size = new_page_size / 2;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
switch (zoom_focus) {
|
|
|
|
case ZoomFocusLeft:
|
|
|
|
leftmost_after_zoom = current_leftmost;
|
|
|
|
break;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
case ZoomFocusRight:
|
|
|
|
current_rightmost = leftmost_frame + current_page;
|
2008-01-10 16:20:59 -05:00
|
|
|
if (current_rightmost < new_page_size) {
|
2005-09-25 14:42:24 -04:00
|
|
|
leftmost_after_zoom = 0;
|
2008-01-10 16:20:59 -05:00
|
|
|
} else {
|
|
|
|
leftmost_after_zoom = current_rightmost - new_page_size;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
break;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
case ZoomFocusCenter:
|
2009-10-14 12:10:01 -04:00
|
|
|
current_center = current_leftmost + (current_page/2);
|
2008-01-10 16:20:59 -05:00
|
|
|
if (current_center < half_page_size) {
|
2005-09-25 14:42:24 -04:00
|
|
|
leftmost_after_zoom = 0;
|
2008-01-10 16:20:59 -05:00
|
|
|
} else {
|
|
|
|
leftmost_after_zoom = current_center - half_page_size;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
break;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
case ZoomFocusPlayhead:
|
2010-01-14 20:06:13 -05:00
|
|
|
/* centre playhead */
|
|
|
|
l = playhead_cursor->current_frame - (new_page_size * 0.5);
|
2008-01-15 12:23:57 -05:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (l < 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
leftmost_after_zoom = 0;
|
2009-10-14 12:10:01 -04:00
|
|
|
} else if (l > max_frames) {
|
2008-01-10 16:20:59 -05:00
|
|
|
leftmost_after_zoom = max_frames - new_page_size;
|
|
|
|
} else {
|
|
|
|
leftmost_after_zoom = (nframes64_t) l;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2007-11-07 20:40:25 -05:00
|
|
|
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;
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (where < half_page_size) {
|
2007-11-07 20:40:25 -05:00
|
|
|
leftmost_after_zoom = 0;
|
2008-01-10 16:20:59 -05:00
|
|
|
} else {
|
|
|
|
leftmost_after_zoom = where - half_page_size;
|
2007-11-07 20:40:25 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
l = - ((new_page_size * ((where - current_leftmost)/(double)current_page)) - where);
|
2007-11-07 20:40:25 -05:00
|
|
|
|
|
|
|
if (l < 0) {
|
|
|
|
leftmost_after_zoom = 0;
|
2009-10-14 12:10:01 -04:00
|
|
|
} else if (l > max_frames) {
|
2008-01-10 16:20:59 -05:00
|
|
|
leftmost_after_zoom = max_frames - new_page_size;
|
2007-11-07 20:40:25 -05:00
|
|
|
} else {
|
|
|
|
leftmost_after_zoom = (nframes64_t) l;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
case ZoomFocusEdit:
|
2008-01-10 16:20:59 -05:00
|
|
|
/* try to keep the edit point in the same place */
|
|
|
|
where = get_preferred_edit_position ();
|
|
|
|
|
|
|
|
if (where > 0) {
|
|
|
|
|
|
|
|
double l = - ((new_page_size * ((where - current_leftmost)/(double)current_page)) - where);
|
|
|
|
|
|
|
|
if (l < 0) {
|
|
|
|
leftmost_after_zoom = 0;
|
2009-10-14 12:10:01 -04:00
|
|
|
} else if (l > max_frames) {
|
2008-01-10 16:20:59 -05:00
|
|
|
leftmost_after_zoom = max_frames - new_page_size;
|
|
|
|
} else {
|
|
|
|
leftmost_after_zoom = (nframes64_t) l;
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2008-01-10 16:20:59 -05:00
|
|
|
/* edit point not defined */
|
|
|
|
return;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
break;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
// leftmost_after_zoom = min (leftmost_after_zoom, _session->current_end_frame());
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
reposition_and_zoom (leftmost_after_zoom, nfpu);
|
2009-10-14 12:10:01 -04:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
void
|
2008-09-10 11:03:30 -04:00
|
|
|
Editor::temporal_zoom_region (bool both_axes)
|
2008-01-10 16:20:59 -05:00
|
|
|
{
|
|
|
|
|
|
|
|
nframes64_t start = max_frames;
|
|
|
|
nframes64_t end = 0;
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2009-07-09 13:58:13 -04:00
|
|
|
set<TimeAxisView*> tracks;
|
2008-01-10 16:20:59 -05:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
get_regions_for_action (rs);
|
2008-01-10 16:20:59 -05:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
if (rs.empty()) {
|
2008-01-10 16:20:59 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
|
2008-09-10 11:03:30 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if ((*i)->region()->position() < start) {
|
|
|
|
start = (*i)->region()->position();
|
|
|
|
}
|
2008-09-10 11:03:30 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if ((*i)->region()->last_frame() + 1 > end) {
|
|
|
|
end = (*i)->region()->last_frame() + 1;
|
|
|
|
}
|
2008-09-10 11:03:30 -04:00
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
tracks.insert (&((*i)->get_time_axis_view()));
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* now comes an "interesting" hack ... make sure we leave a little space
|
|
|
|
at each end of the editor so that the zoom doesn't fit the region
|
|
|
|
precisely to the screen.
|
|
|
|
*/
|
|
|
|
|
|
|
|
GdkScreen* screen = gdk_screen_get_default ();
|
|
|
|
gint pixwidth = gdk_screen_get_width (screen);
|
|
|
|
gint mmwidth = gdk_screen_get_width_mm (screen);
|
|
|
|
double pix_per_mm = (double) pixwidth/ (double) mmwidth;
|
|
|
|
double one_centimeter_in_pixels = pix_per_mm * 10.0;
|
2008-09-10 11:03:30 -04:00
|
|
|
|
|
|
|
if ((start == 0 && end == 0) || end < start) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nframes64_t range = end - start;
|
2009-06-13 13:52:51 -04:00
|
|
|
double new_fpu = (double)range / (double)_canvas_width;
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t extra_samples = (nframes64_t) floor (one_centimeter_in_pixels * new_fpu);
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (start > extra_samples) {
|
|
|
|
start -= extra_samples;
|
|
|
|
} else {
|
|
|
|
start = 0;
|
2009-10-14 12:10:01 -04:00
|
|
|
}
|
2008-01-10 16:20:59 -05:00
|
|
|
|
|
|
|
if (max_frames - extra_samples > end) {
|
|
|
|
end += extra_samples;
|
|
|
|
} else {
|
|
|
|
end = max_frames;
|
|
|
|
}
|
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
if (both_axes) {
|
|
|
|
/* save visual state with track states included, and prevent
|
|
|
|
set_frames_per_unit() from doing it again.
|
|
|
|
*/
|
|
|
|
undo_visual_stack.push_back (current_visual_state(true));
|
|
|
|
no_save_visual = true;
|
|
|
|
}
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
temporal_zoom_by_frame (start, end, "zoom to region");
|
2008-09-10 11:03:30 -04:00
|
|
|
|
|
|
|
if (both_axes) {
|
2009-06-13 13:52:51 -04:00
|
|
|
uint32_t per_track_height = (uint32_t) floor ((_canvas_height - canvas_timebars_vsize - 10.0) / tracks.size());
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
/* set visible track heights appropriately */
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
for (set<TimeAxisView*>::iterator t = tracks.begin(); t != tracks.end(); ++t) {
|
2008-09-10 11:03:30 -04:00
|
|
|
(*t)->set_height (per_track_height);
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
/* hide irrelevant tracks */
|
2009-07-01 19:20:18 -04:00
|
|
|
|
2009-07-03 14:37:15 -04:00
|
|
|
_routes->suspend_redisplay ();
|
2008-09-10 11:03:30 -04:00
|
|
|
|
|
|
|
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
|
|
|
if (find (tracks.begin(), tracks.end(), (*i)) == tracks.end()) {
|
2010-05-09 21:37:35 -04:00
|
|
|
hide_track_in_display (*i, true);
|
2008-09-10 11:03:30 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-03 14:37:15 -04:00
|
|
|
_routes->resume_redisplay ();
|
2008-09-10 11:03:30 -04:00
|
|
|
|
2008-10-22 14:24:30 -04:00
|
|
|
vertical_adjustment.set_value (0.0);
|
2008-09-10 11:03:30 -04:00
|
|
|
no_save_visual = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
redo_visual_stack.push_back (current_visual_state());
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-10-20 14:20:38 -04:00
|
|
|
Editor::zoom_to_region (bool both_axes)
|
2008-01-10 16:20:59 -05:00
|
|
|
{
|
2009-10-20 14:20:38 -04:00
|
|
|
temporal_zoom_region (both_axes);
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
|
|
|
Editor::temporal_zoom_selection ()
|
|
|
|
{
|
|
|
|
if (!selection) return;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (selection->time.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t start = selection->time[clicked_selection].start;
|
|
|
|
nframes64_t end = selection->time[clicked_selection].end;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
temporal_zoom_by_frame (start, end, "zoom to selection");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::temporal_zoom_session ()
|
|
|
|
{
|
2009-12-11 18:29:48 -05:00
|
|
|
ENSURE_GUI_THREAD (*this, &Editor::temporal_zoom_session)
|
2006-04-06 12:51:27 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (_session) {
|
2010-05-09 20:48:42 -04:00
|
|
|
nframes_t const l = _session->current_end_frame() - _session->current_start_frame();
|
|
|
|
double s = _session->current_start_frame() - l * 0.01;
|
|
|
|
if (s < 0) {
|
|
|
|
s = 0;
|
|
|
|
}
|
|
|
|
nframes_t const e = _session->current_end_frame() + l * 0.01;
|
|
|
|
temporal_zoom_by_frame (nframes_t (s), e, "zoom to _session");
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-07-21 11:55:17 -04:00
|
|
|
Editor::temporal_zoom_by_frame (nframes64_t start, nframes64_t end, const string & /*op*/)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) return;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if ((start == 0 && end == 0) || end < start) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t range = end - start;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-06-13 13:52:51 -04:00
|
|
|
double new_fpu = (double)range / (double)_canvas_width;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-06-13 13:52:51 -04:00
|
|
|
nframes64_t new_page = (nframes64_t) floor (_canvas_width * new_fpu);
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t middle = (nframes64_t) floor( (double)start + ((double)range / 2.0f ));
|
|
|
|
nframes64_t new_leftmost = (nframes64_t) floor( (double)middle - ((double)new_page/2.0f));
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
if (new_leftmost > middle) {
|
|
|
|
new_leftmost = 0;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
reposition_and_zoom (new_leftmost, new_fpu);
|
|
|
|
}
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
void
|
2008-09-10 11:03:30 -04:00
|
|
|
Editor::temporal_zoom_to_frame (bool coarser, nframes64_t frame)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) {
|
2008-09-10 17:27:39 -04:00
|
|
|
return;
|
|
|
|
}
|
2006-09-18 23:29:16 -04:00
|
|
|
double range_before = frame - leftmost_frame;
|
2005-09-25 14:42:24 -04:00
|
|
|
double new_fpu;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
new_fpu = frames_per_unit;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
|
|
|
if (coarser) {
|
2006-09-18 23:29:16 -04:00
|
|
|
new_fpu *= 1.61803399;
|
|
|
|
range_before *= 1.61803399;
|
2009-10-14 12:10:01 -04:00
|
|
|
} else {
|
2006-09-18 23:29:16 -04:00
|
|
|
new_fpu = max(1.0,(new_fpu/1.61803399));
|
|
|
|
range_before /= 1.61803399;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2008-09-10 17:27:39 -04:00
|
|
|
if (new_fpu == frames_per_unit) {
|
|
|
|
return;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t new_leftmost = frame - (nframes64_t)range_before;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-09-10 17:27:39 -04:00
|
|
|
if (new_leftmost > frame) {
|
|
|
|
new_leftmost = 0;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
// begin_reversible_command (_("zoom to frame"));
|
2009-12-17 13:24:23 -05:00
|
|
|
// _session->add_undo (sigc::bind (sigc::mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
|
|
|
|
// _session->add_redo (sigc::bind (sigc::mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
|
2005-09-25 14:42:24 -04:00
|
|
|
// commit_reversible_command ();
|
|
|
|
|
|
|
|
reposition_and_zoom (new_leftmost, new_fpu);
|
|
|
|
}
|
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
|
|
|
|
bool
|
|
|
|
Editor::choose_new_marker_name(string &name) {
|
|
|
|
|
|
|
|
if (!Config->get_name_new_markers()) {
|
|
|
|
/* don't prompt user for a new name */
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
ArdourPrompter dialog (true);
|
|
|
|
|
|
|
|
dialog.set_prompt (_("New Name:"));
|
|
|
|
|
2009-10-19 13:25:37 -04:00
|
|
|
dialog.set_title (_("New Location Marker"));
|
2008-09-10 11:03:30 -04:00
|
|
|
|
|
|
|
dialog.set_name ("MarkNameWindow");
|
|
|
|
dialog.set_size_request (250, -1);
|
|
|
|
dialog.set_position (Gtk::WIN_POS_MOUSE);
|
|
|
|
|
|
|
|
dialog.add_button (Stock::OK, RESPONSE_ACCEPT);
|
|
|
|
dialog.set_initial_text (name);
|
|
|
|
|
|
|
|
dialog.show ();
|
|
|
|
|
|
|
|
switch (dialog.run ()) {
|
|
|
|
case RESPONSE_ACCEPT:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
dialog.get_result(name);
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-03-31 18:00:40 -05:00
|
|
|
void
|
|
|
|
Editor::add_location_from_selection ()
|
|
|
|
{
|
2007-01-09 18:24:54 -05:00
|
|
|
string rangename;
|
|
|
|
|
2006-03-31 18:00:40 -05:00
|
|
|
if (selection->time.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (_session == 0 || clicked_axisview == 0) {
|
2006-03-31 18:00:40 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t start = selection->time[clicked_selection].start;
|
|
|
|
nframes64_t end = selection->time[clicked_selection].end;
|
2006-03-31 18:00:40 -05:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->locations()->next_available_name(rangename,"selection");
|
2007-01-09 18:24:54 -05:00
|
|
|
Location *location = new Location (start, end, rangename, Location::IsRangeMarker);
|
2006-03-31 18:00:40 -05:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->begin_reversible_command (_("add marker"));
|
|
|
|
XMLNode &before = _session->locations()->get_state();
|
|
|
|
_session->locations()->add (location, true);
|
|
|
|
XMLNode &after = _session->locations()->get_state();
|
|
|
|
_session->add_command(new MementoCommand<Locations>(*(_session->locations()), &before, &after));
|
|
|
|
_session->commit_reversible_command ();
|
2006-03-31 18:00:40 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-01-10 16:20:59 -05:00
|
|
|
Editor::add_location_mark (nframes64_t where)
|
2006-03-31 18:00:40 -05:00
|
|
|
{
|
2007-01-09 18:24:54 -05:00
|
|
|
string markername;
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
select_new_marker = true;
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->locations()->next_available_name(markername,"mark");
|
2008-09-10 11:03:30 -04:00
|
|
|
if (!choose_new_marker_name(markername)) {
|
|
|
|
return;
|
|
|
|
}
|
2007-01-09 18:24:54 -05:00
|
|
|
Location *location = new Location (where, where, markername, Location::IsMark);
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->begin_reversible_command (_("add marker"));
|
|
|
|
XMLNode &before = _session->locations()->get_state();
|
|
|
|
_session->locations()->add (location, true);
|
|
|
|
XMLNode &after = _session->locations()->get_state();
|
|
|
|
_session->add_command(new MementoCommand<Locations>(*(_session->locations()), &before, &after));
|
|
|
|
_session->commit_reversible_command ();
|
2006-03-31 18:00:40 -05:00
|
|
|
}
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
void
|
|
|
|
Editor::add_location_from_playhead_cursor ()
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
add_location_mark (_session->audible_frame());
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
|
2006-03-31 18:00:40 -05:00
|
|
|
void
|
2008-12-12 09:43:24 -05:00
|
|
|
Editor::add_locations_from_audio_region ()
|
2006-03-31 18:00:40 -05:00
|
|
|
{
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
|
|
|
if (rs.empty()) {
|
2006-03-31 18:00:40 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->begin_reversible_command (rs.size () > 1 ? _("add markers") : _("add marker"));
|
|
|
|
XMLNode &before = _session->locations()->get_state();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-12-12 09:43:24 -05:00
|
|
|
for (RegionSelection::iterator i = rs.begin (); i != rs.end (); ++i) {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-12-12 09:43:24 -05:00
|
|
|
boost::shared_ptr<Region> region = (*i)->region ();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-12-12 09:43:24 -05:00
|
|
|
Location *location = new Location (region->position(), region->last_frame(), region->name(), Location::IsRangeMarker);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->locations()->add (location, true);
|
2008-12-12 09:43:24 -05:00
|
|
|
}
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
XMLNode &after = _session->locations()->get_state();
|
|
|
|
_session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
|
|
|
|
_session->commit_reversible_command ();
|
2008-12-12 09:43:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::add_location_from_audio_region ()
|
|
|
|
{
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-12-12 09:43:24 -05:00
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
|
|
|
if (rs.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->begin_reversible_command (_("add marker"));
|
|
|
|
XMLNode &before = _session->locations()->get_state();
|
2008-12-12 09:43:24 -05:00
|
|
|
|
|
|
|
string markername;
|
|
|
|
|
|
|
|
if (rs.size() > 1) { // more than one region selected
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->locations()->next_available_name(markername, "regions");
|
2008-12-12 09:43:24 -05:00
|
|
|
} else {
|
|
|
|
RegionView* rv = *(rs.begin());
|
|
|
|
boost::shared_ptr<Region> region = rv->region();
|
|
|
|
markername = region->name();
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-12-12 09:43:24 -05:00
|
|
|
if (!choose_new_marker_name(markername)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
// single range spanning all selected
|
2008-12-12 09:43:24 -05:00
|
|
|
Location *location = new Location (rs.start(), rs.end_frame(), markername, Location::IsRangeMarker);
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->locations()->add (location, true);
|
2008-12-12 09:43:24 -05:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
XMLNode &after = _session->locations()->get_state();
|
|
|
|
_session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
|
|
|
|
_session->commit_reversible_command ();
|
2006-03-31 18:00:40 -05:00
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
|
|
|
Editor::amplitude_zoom_step (bool in)
|
|
|
|
{
|
|
|
|
gdouble zoom = 1.0;
|
|
|
|
|
|
|
|
if (in) {
|
|
|
|
zoom *= 2.0;
|
|
|
|
} else {
|
|
|
|
if (zoom > 2.0) {
|
|
|
|
zoom /= 2.0;
|
|
|
|
} else {
|
|
|
|
zoom = 1.0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef FIX_FOR_CANVAS
|
|
|
|
/* XXX DO SOMETHING */
|
|
|
|
#endif
|
2009-10-14 12:10:01 -04:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
|
|
|
|
/* DELETION */
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::delete_sample_forward ()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::delete_sample_backward ()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::delete_screen ()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/* SEARCH */
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::search_backwards ()
|
|
|
|
{
|
|
|
|
/* what ? */
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::search_forwards ()
|
|
|
|
{
|
|
|
|
/* what ? */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* MARKS */
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::jump_forward_to_mark ()
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
Location *location = _session->locations()->first_location_after (playhead_cursor->current_frame);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (location) {
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_locate (location->start(), _session->transport_rolling());
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_locate (_session->current_end_frame());
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::jump_backward_to_mark ()
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
Location *location = _session->locations()->first_location_before (playhead_cursor->current_frame);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (location) {
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_locate (location->start(), _session->transport_rolling());
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->goto_start ();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::set_mark ()
|
|
|
|
{
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t pos;
|
2005-09-25 14:42:24 -04:00
|
|
|
float prefix;
|
|
|
|
bool was_floating;
|
2007-01-09 18:24:54 -05:00
|
|
|
string markername;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (get_prefix (prefix, was_floating)) {
|
2009-12-17 13:24:23 -05:00
|
|
|
pos = _session->audible_frame ();
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
|
|
|
if (was_floating) {
|
2009-12-17 13:24:23 -05:00
|
|
|
pos = (nframes64_t) floor (prefix * _session->frame_rate ());
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2008-09-10 11:03:30 -04:00
|
|
|
pos = (nframes64_t) floor (prefix);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->locations()->next_available_name(markername,"mark");
|
2008-09-10 11:03:30 -04:00
|
|
|
if (!choose_new_marker_name(markername)) {
|
|
|
|
return;
|
|
|
|
}
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->locations()->add (new Location (pos, 0, markername, Location::IsMark), true);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::clear_markers ()
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (_session) {
|
|
|
|
_session->begin_reversible_command (_("clear markers"));
|
|
|
|
XMLNode &before = _session->locations()->get_state();
|
|
|
|
_session->locations()->clear_markers ();
|
|
|
|
XMLNode &after = _session->locations()->get_state();
|
|
|
|
_session->add_command(new MementoCommand<Locations>(*(_session->locations()), &before, &after));
|
|
|
|
_session->commit_reversible_command ();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::clear_ranges ()
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (_session) {
|
|
|
|
_session->begin_reversible_command (_("clear ranges"));
|
|
|
|
XMLNode &before = _session->locations()->get_state();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
Location * looploc = _session->locations()->auto_loop_location();
|
|
|
|
Location * punchloc = _session->locations()->auto_punch_location();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->locations()->clear_ranges ();
|
2005-09-25 14:42:24 -04:00
|
|
|
// re-add these
|
2009-12-17 13:24:23 -05:00
|
|
|
if (looploc) _session->locations()->add (looploc);
|
|
|
|
if (punchloc) _session->locations()->add (punchloc);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
XMLNode &after = _session->locations()->get_state();
|
|
|
|
_session->add_command(new MementoCommand<Locations>(*(_session->locations()), &before, &after));
|
|
|
|
_session->commit_reversible_command ();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::clear_locations ()
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->begin_reversible_command (_("clear locations"));
|
|
|
|
XMLNode &before = _session->locations()->get_state();
|
|
|
|
_session->locations()->clear ();
|
|
|
|
XMLNode &after = _session->locations()->get_state();
|
|
|
|
_session->add_command(new MementoCommand<Locations>(*(_session->locations()), &before, &after));
|
|
|
|
_session->commit_reversible_command ();
|
|
|
|
_session->locations()->clear ();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2007-01-09 18:24:54 -05:00
|
|
|
void
|
|
|
|
Editor::unhide_markers ()
|
|
|
|
{
|
|
|
|
for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
|
|
|
|
Location *l = (*i).first;
|
|
|
|
if (l->is_hidden() && l->is_mark()) {
|
|
|
|
l->set_hidden(false, this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::unhide_ranges ()
|
|
|
|
{
|
|
|
|
for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
|
|
|
|
Location *l = (*i).first;
|
2009-10-14 12:10:01 -04:00
|
|
|
if (l->is_hidden() && l->is_range_marker()) {
|
2007-01-09 18:24:54 -05:00
|
|
|
l->set_hidden(false, this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
/* INSERT/REPLACE */
|
|
|
|
|
|
|
|
void
|
2006-08-29 17:21:48 -04:00
|
|
|
Editor::insert_region_list_drag (boost::shared_ptr<Region> region, int x, int y)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
double wx, wy;
|
|
|
|
double cx, cy;
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t where;
|
2009-07-09 13:58:13 -04:00
|
|
|
RouteTimeAxisView *rtv = 0;
|
2007-01-09 18:24:54 -05:00
|
|
|
boost::shared_ptr<Playlist> playlist;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-03-17 16:54:03 -04:00
|
|
|
track_canvas->window_to_world (x, y, wx, wy);
|
2005-11-12 22:53:51 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
GdkEvent event;
|
|
|
|
event.type = GDK_BUTTON_RELEASE;
|
|
|
|
event.button.x = wx;
|
|
|
|
event.button.y = wy;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
where = event_frame (&event, &cx, &cy);
|
|
|
|
|
|
|
|
if (where < leftmost_frame || where > leftmost_frame + current_page_frames()) {
|
|
|
|
/* clearly outside canvas area */
|
|
|
|
return;
|
|
|
|
}
|
2009-01-05 22:18:09 -05:00
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
std::pair<TimeAxisView*, int> tv = trackview_by_y_position (cy);
|
2009-01-05 22:18:09 -05:00
|
|
|
if (tv.first == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
if ((rtv = dynamic_cast<RouteTimeAxisView*> (tv.first)) == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
if ((playlist = rtv->playlist()) == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
snap_to (where);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
begin_reversible_command (_("insert dragged region"));
|
2010-03-02 13:05:26 -05:00
|
|
|
playlist->clear_history ();
|
2006-08-29 17:21:48 -04:00
|
|
|
playlist->add_region (RegionFactory::create (region), where, 1.0);
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command(new StatefulDiffCommand (playlist));
|
2005-09-25 14:42:24 -04:00
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
|
2008-02-10 13:16:25 -05:00
|
|
|
void
|
2010-05-09 16:48:21 -04:00
|
|
|
Editor::insert_route_list_drag (boost::shared_ptr<Route> route, int x, int y)
|
|
|
|
{
|
2008-02-10 13:16:25 -05:00
|
|
|
double wx, wy;
|
|
|
|
double cx, cy;
|
|
|
|
nframes_t where;
|
2009-07-09 13:58:13 -04:00
|
|
|
RouteTimeAxisView *dest_rtv = 0;
|
|
|
|
RouteTimeAxisView *source_rtv = 0;
|
2008-02-10 13:16:25 -05:00
|
|
|
|
2008-03-17 16:54:03 -04:00
|
|
|
track_canvas->window_to_world (x, y, wx, wy);
|
2010-05-09 16:48:21 -04:00
|
|
|
wx += horizontal_position ();
|
2008-02-10 13:16:25 -05:00
|
|
|
wy += vertical_adjustment.get_value();
|
|
|
|
|
|
|
|
GdkEvent event;
|
|
|
|
event.type = GDK_BUTTON_RELEASE;
|
|
|
|
event.button.x = wx;
|
|
|
|
event.button.y = wy;
|
|
|
|
|
|
|
|
where = event_frame (&event, &cx, &cy);
|
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
std::pair<TimeAxisView*, int> const tv = trackview_by_y_position (cy);
|
2009-01-05 22:18:09 -05:00
|
|
|
if (tv.first == 0) {
|
2008-02-10 13:16:25 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
if ((dest_rtv = dynamic_cast<RouteTimeAxisView*> (tv.first)) == 0) {
|
2008-02-10 13:16:25 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
/* use this drag source to add underlay to a track. But we really don't care
|
2008-02-10 13:16:25 -05:00
|
|
|
about the Route, only the view of the route, so find it first */
|
|
|
|
for(TrackViewList::iterator it = track_views.begin(); it != track_views.end(); ++it) {
|
2009-07-09 13:58:13 -04:00
|
|
|
if((source_rtv = dynamic_cast<RouteTimeAxisView*>(*it)) == 0) {
|
2008-02-10 13:16:25 -05:00
|
|
|
continue;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-10 13:16:25 -05:00
|
|
|
if(source_rtv->route() == route && source_rtv != dest_rtv) {
|
|
|
|
dest_rtv->add_underlay(source_rtv->view());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
|
|
|
Editor::insert_region_list_selection (float times)
|
|
|
|
{
|
2009-07-09 13:58:13 -04:00
|
|
|
RouteTimeAxisView *tv = 0;
|
2007-01-09 18:24:54 -05:00
|
|
|
boost::shared_ptr<Playlist> playlist;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (clicked_routeview != 0) {
|
|
|
|
tv = clicked_routeview;
|
|
|
|
} else if (!selection->tracks.empty()) {
|
2009-07-09 13:58:13 -04:00
|
|
|
if ((tv = dynamic_cast<RouteTimeAxisView*>(selection->tracks.front())) == 0) {
|
2008-01-10 16:20:59 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if (entered_track != 0) {
|
2009-07-09 13:58:13 -04:00
|
|
|
if ((tv = dynamic_cast<RouteTimeAxisView*>(entered_track)) == 0) {
|
2008-01-10 16:20:59 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((playlist = tv->playlist()) == 0) {
|
|
|
|
return;
|
|
|
|
}
|
2009-07-03 18:42:22 -04:00
|
|
|
|
|
|
|
boost::shared_ptr<Region> region = _regions->get_single_selection ();
|
|
|
|
if (region == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-07-03 18:42:22 -04:00
|
|
|
begin_reversible_command (_("insert region"));
|
2010-03-02 13:05:26 -05:00
|
|
|
playlist->clear_history ();
|
2009-07-03 18:42:22 -04:00
|
|
|
playlist->add_region ((RegionFactory::create (region)), get_preferred_edit_position(), times);
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command(new StatefulDiffCommand (playlist));
|
2009-07-03 18:42:22 -04:00
|
|
|
commit_reversible_command ();
|
2006-10-21 15:01:50 -04:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
/* BUILT-IN EFFECTS */
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::reverse_selection ()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* GAIN ENVELOPE EDITING */
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::edit_envelope ()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/* PLAYBACK */
|
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
void
|
|
|
|
Editor::transition_to_rolling (bool fwd)
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) {
|
2007-01-28 12:44:13 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (_session->config.get_external_sync()) {
|
|
|
|
switch (_session->config.get_sync_source()) {
|
2009-11-09 15:05:18 -05:00
|
|
|
case JACK:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* transport controlled by the master */
|
|
|
|
return;
|
|
|
|
}
|
2007-01-28 12:44:13 -05:00
|
|
|
}
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (_session->is_auditioning()) {
|
|
|
|
_session->cancel_audition ();
|
2007-01-28 12:44:13 -05:00
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_transport_speed (fwd ? 1.0f : -1.0f);
|
2007-01-28 12:44:13 -05:00
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
|
|
|
Editor::play_from_start ()
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_locate (_session->current_start_frame(), true);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2006-11-19 11:45:16 -05:00
|
|
|
void
|
2007-11-12 17:23:01 -05:00
|
|
|
Editor::play_from_edit_point ()
|
2006-11-19 11:45:16 -05:00
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_locate (get_preferred_edit_position(), true);
|
2006-11-19 11:45:16 -05:00
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
2008-01-10 16:20:59 -05:00
|
|
|
Editor::play_from_edit_point_and_return ()
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2008-01-10 16:20:59 -05:00
|
|
|
nframes64_t start_frame;
|
|
|
|
nframes64_t return_frame;
|
|
|
|
|
2008-03-17 16:54:03 -04:00
|
|
|
start_frame = get_preferred_edit_position (true);
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (_session->transport_rolling()) {
|
|
|
|
_session->request_locate (start_frame, false);
|
2008-03-17 16:54:03 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
/* don't reset the return frame if its already set */
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if ((return_frame = _session->requested_return_frame()) < 0) {
|
|
|
|
return_frame = _session->audible_frame();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (start_frame >= 0) {
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_roll_at_and_return (start_frame, return_frame);
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-01-10 16:20:59 -05:00
|
|
|
Editor::play_selection ()
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2008-01-10 16:20:59 -05:00
|
|
|
if (selection->time.empty()) {
|
|
|
|
return;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2008-01-10 16:20:59 -05:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_play_range (&selection->time, true);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::loop_selected_region ()
|
|
|
|
{
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
|
|
|
if (!rs.empty()) {
|
|
|
|
RegionView *rv = *(rs.begin());
|
2005-09-25 14:42:24 -04:00
|
|
|
Location* tll;
|
|
|
|
|
|
|
|
if ((tll = transport_loop_location()) != 0) {
|
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
tll->set (rv->region()->position(), rv->region()->last_frame());
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
// enable looping, reposition and start rolling
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_play_loop (true);
|
|
|
|
_session->request_locate (tll->start(), false);
|
|
|
|
_session->request_transport_speed (1.0f);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::play_location (Location& location)
|
|
|
|
{
|
|
|
|
if (location.start() <= location.end()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_bounded_roll (location.start(), location.end());
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::loop_location (Location& location)
|
|
|
|
{
|
|
|
|
if (location.start() <= location.end()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Location* tll;
|
|
|
|
|
|
|
|
if ((tll = transport_loop_location()) != 0) {
|
|
|
|
tll->set (location.start(), location.end());
|
|
|
|
|
|
|
|
// enable looping, reposition and start rolling
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_play_loop (true);
|
|
|
|
_session->request_locate (tll->start(), true);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
void
|
|
|
|
Editor::raise_region ()
|
|
|
|
{
|
|
|
|
selection->foreach_region (&Region::raise);
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
|
|
|
Editor::raise_region_to_top ()
|
|
|
|
{
|
2006-07-23 08:03:19 -04:00
|
|
|
selection->foreach_region (&Region::raise_to_top);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
void
|
|
|
|
Editor::lower_region ()
|
|
|
|
{
|
|
|
|
selection->foreach_region (&Region::lower);
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
|
|
|
Editor::lower_region_to_bottom ()
|
|
|
|
{
|
2006-07-23 08:03:19 -04:00
|
|
|
selection->foreach_region (&Region::lower_to_bottom);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2007-05-10 07:53:35 -04:00
|
|
|
/** Show the region editor for the selected regions */
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
|
|
|
Editor::edit_region ()
|
|
|
|
{
|
2007-05-10 07:53:35 -04:00
|
|
|
selection->foreach_regionview (&RegionView::show_region_editor);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2009-08-26 23:09:30 -04:00
|
|
|
/** Show the midi list editor for the selected MIDI regions */
|
|
|
|
void
|
|
|
|
Editor::show_midi_list_editor ()
|
|
|
|
{
|
|
|
|
selection->foreach_midi_regionview (&MidiRegionView::show_list_editor);
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
2008-01-10 16:20:59 -05:00
|
|
|
Editor::rename_region()
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
|
|
|
if (rs.empty()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-10-19 13:25:37 -04:00
|
|
|
ArdourDialog d (*this, _("Rename Region"), true, false);
|
2008-01-10 16:20:59 -05:00
|
|
|
Entry entry;
|
|
|
|
Label label (_("New name:"));
|
|
|
|
HBox hbox;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
hbox.set_spacing (6);
|
|
|
|
hbox.pack_start (label, false, false);
|
|
|
|
hbox.pack_start (entry, true, true);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
d.get_vbox()->set_border_width (12);
|
|
|
|
d.get_vbox()->pack_start (hbox, false, false);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
d.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
|
2010-03-16 11:33:04 -04:00
|
|
|
d.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
d.set_size_request (300, -1);
|
|
|
|
d.set_position (Gtk::WIN_POS_MOUSE);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
entry.set_text (rs.front()->region()->name());
|
2008-01-10 16:20:59 -05:00
|
|
|
entry.select_region (0, -1);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-12-11 18:29:48 -05:00
|
|
|
entry.signal_activate().connect (sigc::bind (sigc::mem_fun (d, &Dialog::response), RESPONSE_OK));
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
d.show_all ();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
entry.grab_focus();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
int ret = d.run();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
d.hide ();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (ret == RESPONSE_OK) {
|
|
|
|
std::string str = entry.get_text();
|
|
|
|
strip_whitespace_edges (str);
|
|
|
|
if (!str.empty()) {
|
2008-02-16 17:43:18 -05:00
|
|
|
rs.front()->region()->set_name (str);
|
2009-07-03 18:42:22 -04:00
|
|
|
_regions->redisplay ();
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2006-08-29 17:21:48 -04:00
|
|
|
Editor::audition_playlist_region_via_route (boost::shared_ptr<Region> region, Route& route)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (_session->is_auditioning()) {
|
|
|
|
_session->cancel_audition ();
|
2009-10-14 12:10:01 -04:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
// note: some potential for creativity here, because region doesn't
|
|
|
|
// have to belong to the playlist that Route is handling
|
|
|
|
|
|
|
|
// bool was_soloed = route.soloed();
|
|
|
|
|
|
|
|
route.set_solo (true, this);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_bounded_roll (region->position(), region->position() + region->length());
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
/* XXX how to unset the solo state ? */
|
|
|
|
}
|
|
|
|
|
2007-05-10 07:53:35 -04:00
|
|
|
/** Start an audition of the first selected region */
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
2008-01-10 16:20:59 -05:00
|
|
|
Editor::play_edit_range ()
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2008-01-10 16:20:59 -05:00
|
|
|
nframes64_t start, end;
|
|
|
|
|
|
|
|
if (get_edit_op_range (start, end)) {
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_bounded_roll (start, end);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-01-10 16:20:59 -05:00
|
|
|
Editor::play_selected_region ()
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2008-01-10 16:20:59 -05:00
|
|
|
nframes64_t start = max_frames;
|
|
|
|
nframes64_t end = 0;
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
get_regions_for_action (rs);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
if (rs.empty()) {
|
2008-01-10 16:20:59 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
|
2008-01-10 16:20:59 -05:00
|
|
|
if ((*i)->region()->position() < start) {
|
|
|
|
start = (*i)->region()->position();
|
|
|
|
}
|
|
|
|
if ((*i)->region()->last_frame() + 1 > end) {
|
|
|
|
end = (*i)->region()->last_frame() + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_bounded_roll (start, end);
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::audition_playlist_region_standalone (boost::shared_ptr<Region> region)
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->audition_region (region);
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
|
|
|
Editor::region_from_selection ()
|
|
|
|
{
|
2006-08-16 16:36:14 -04:00
|
|
|
if (clicked_axisview == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (selection->time.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t start = selection->time[clicked_selection].start;
|
|
|
|
nframes64_t end = selection->time[clicked_selection].end;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-12-13 14:09:52 -05:00
|
|
|
TrackViewList tracks = get_tracks_for_range_action ();
|
2009-07-21 15:55:12 -04:00
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t selection_cnt = end - start + 1;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-07-21 15:55:12 -04:00
|
|
|
for (TrackSelection::iterator i = tracks.begin(); i != tracks.end(); ++i) {
|
2009-02-16 02:04:27 -05:00
|
|
|
boost::shared_ptr<Region> current;
|
2007-01-09 18:24:54 -05:00
|
|
|
boost::shared_ptr<Playlist> pl;
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t internal_start;
|
2005-09-25 14:42:24 -04:00
|
|
|
string new_name;
|
|
|
|
|
|
|
|
if ((pl = (*i)->playlist()) == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2009-02-16 02:04:27 -05:00
|
|
|
if ((current = pl->top_region_at (start)) == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2009-02-16 02:04:27 -05:00
|
|
|
internal_start = start - current->position();
|
2010-03-30 19:40:28 -04:00
|
|
|
RegionFactory::region_name (new_name, current->name(), true);
|
2010-02-18 08:59:49 -05:00
|
|
|
|
|
|
|
PropertyList plist;
|
|
|
|
|
2010-03-02 16:08:37 -05:00
|
|
|
plist.add (ARDOUR::Properties::start, current->start() + internal_start);
|
2010-02-18 08:59:49 -05:00
|
|
|
plist.add (ARDOUR::Properties::length, selection_cnt);
|
|
|
|
plist.add (ARDOUR::Properties::name, new_name);
|
|
|
|
plist.add (ARDOUR::Properties::layer, 0);
|
|
|
|
|
|
|
|
boost::shared_ptr<Region> region (RegionFactory::create (current, plist));
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
void
|
2008-02-16 17:43:18 -05:00
|
|
|
Editor::create_region_from_selection (vector<boost::shared_ptr<Region> >& new_regions)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
if (selection->time.empty() || selection->tracks.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t start = selection->time[clicked_selection].start;
|
|
|
|
nframes64_t end = selection->time[clicked_selection].end;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
sort_track_selection ();
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
|
2009-02-16 02:04:27 -05:00
|
|
|
boost::shared_ptr<Region> current;
|
2007-01-09 18:24:54 -05:00
|
|
|
boost::shared_ptr<Playlist> playlist;
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t internal_start;
|
2005-09-25 14:42:24 -04:00
|
|
|
string new_name;
|
|
|
|
|
|
|
|
if ((playlist = (*i)->playlist()) == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2009-02-16 02:04:27 -05:00
|
|
|
if ((current = playlist->top_region_at(start)) == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal_start = start - current->position();
|
2010-03-30 19:40:28 -04:00
|
|
|
RegionFactory::region_name (new_name, current->name(), true);
|
2009-05-30 14:25:59 -04:00
|
|
|
|
2010-02-18 08:59:49 -05:00
|
|
|
PropertyList plist;
|
|
|
|
|
2010-03-02 16:08:37 -05:00
|
|
|
plist.add (ARDOUR::Properties::start, current->start() + internal_start);
|
2010-02-18 08:59:49 -05:00
|
|
|
plist.add (ARDOUR::Properties::length, end - start + 1);
|
|
|
|
plist.add (ARDOUR::Properties::name, new_name);
|
|
|
|
|
|
|
|
new_regions.push_back (RegionFactory::create (current, plist));
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::split_multichannel_region ()
|
|
|
|
{
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
|
|
|
if (rs.empty()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-02-16 02:04:27 -05:00
|
|
|
vector< boost::shared_ptr<Region> > v;
|
2007-01-28 12:44:13 -05:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (list<RegionView*>::iterator x = rs.begin(); x != rs.end(); ++x) {
|
2009-12-17 13:24:23 -05:00
|
|
|
(*x)->region()->separate_by_channel (*_session, v);
|
2007-01-28 12:44:13 -05:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::new_region_from_selection ()
|
|
|
|
{
|
|
|
|
region_from_selection ();
|
|
|
|
cancel_selection ();
|
|
|
|
}
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
static void
|
|
|
|
add_if_covered (RegionView* rv, const AudioRange* ar, RegionSelection* rs)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2008-01-10 16:20:59 -05:00
|
|
|
switch (rv->region()->coverage (ar->start, ar->end - 1)) {
|
|
|
|
case OverlapNone:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
rs->push_back (rv);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-07-21 15:55:12 -04:00
|
|
|
/** Return either:
|
|
|
|
* - selected tracks, or if there are none...
|
|
|
|
* - tracks containing selected regions, or if there are none...
|
|
|
|
* - all tracks
|
|
|
|
* @return tracks.
|
|
|
|
*/
|
2009-12-13 14:09:52 -05:00
|
|
|
TrackViewList
|
2009-07-21 15:55:12 -04:00
|
|
|
Editor::get_tracks_for_range_action () const
|
2008-01-10 16:20:59 -05:00
|
|
|
{
|
2009-12-13 14:09:52 -05:00
|
|
|
TrackViewList t;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-01-10 17:22:29 -05:00
|
|
|
if (selection->tracks.empty()) {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-01-10 17:22:29 -05:00
|
|
|
/* use tracks with selected regions */
|
2007-01-28 12:44:13 -05:00
|
|
|
|
2009-07-21 15:55:12 -04:00
|
|
|
RegionSelection rs = selection->regions;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
|
2009-07-09 13:58:13 -04:00
|
|
|
TimeAxisView* tv = &(*i)->get_time_axis_view();
|
2008-01-10 17:22:29 -05:00
|
|
|
|
2009-07-21 15:55:12 -04:00
|
|
|
if (!t.contains (tv)) {
|
|
|
|
t.push_back (tv);
|
2008-01-10 17:22:29 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-21 15:55:12 -04:00
|
|
|
if (t.empty()) {
|
|
|
|
/* no regions and no tracks: use all tracks */
|
|
|
|
t = track_views;
|
2008-01-10 17:22:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
2009-07-21 15:55:12 -04:00
|
|
|
t = selection->tracks;
|
2008-01-10 17:22:29 -05:00
|
|
|
}
|
|
|
|
|
2009-07-21 15:55:12 -04:00
|
|
|
return t;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::separate_regions_between (const TimeSelection& ts)
|
|
|
|
{
|
|
|
|
bool in_command = false;
|
|
|
|
boost::shared_ptr<Playlist> playlist;
|
|
|
|
RegionSelection new_selection;
|
|
|
|
|
2009-12-13 14:09:52 -05:00
|
|
|
TrackViewList tmptracks = get_tracks_for_range_action ();
|
2008-01-10 17:22:29 -05:00
|
|
|
sort_track_selection (&tmptracks);
|
|
|
|
|
|
|
|
for (TrackSelection::iterator i = tmptracks.begin(); i != tmptracks.end(); ++i) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
RouteTimeAxisView* rtv;
|
2008-01-10 17:22:29 -05:00
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
if ((rtv = dynamic_cast<RouteTimeAxisView*> ((*i))) != 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-01-10 17:22:29 -05:00
|
|
|
if (rtv->is_track()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-01-10 17:22:29 -05:00
|
|
|
/* no edits to destructive tracks */
|
2008-01-10 16:20:59 -05:00
|
|
|
|
2010-04-21 16:42:22 -04:00
|
|
|
if (rtv->track()->destructive()) {
|
2008-01-10 17:22:29 -05:00
|
|
|
continue;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-01-10 17:22:29 -05:00
|
|
|
if ((playlist = rtv->playlist()) != 0) {
|
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
playlist->clear_history ();
|
2008-01-10 17:22:29 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
/* XXX need to consider musical time selections here at some point */
|
|
|
|
|
2010-04-21 16:42:22 -04:00
|
|
|
double speed = rtv->track()->speed();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
|
|
|
|
for (list<AudioRange>::const_iterator t = ts.begin(); t != ts.end(); ++t) {
|
|
|
|
|
2009-02-16 02:04:27 -05:00
|
|
|
sigc::connection c = rtv->view()->RegionViewAdded.connect (
|
2009-12-11 18:29:48 -05:00
|
|
|
sigc::mem_fun(*this, &Editor::collect_new_region_view));
|
2010-07-06 07:33:27 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
latest_regionviews.clear ();
|
|
|
|
|
2009-02-16 02:04:27 -05:00
|
|
|
playlist->partition ((nframes64_t)((*t).start * speed),
|
2010-06-28 11:01:14 -04:00
|
|
|
(nframes64_t)((*t).end * speed), false);
|
2008-01-10 16:20:59 -05:00
|
|
|
|
|
|
|
c.disconnect ();
|
|
|
|
|
|
|
|
if (!latest_regionviews.empty()) {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-12-11 18:29:48 -05:00
|
|
|
rtv->view()->foreach_regionview (sigc::bind (
|
2009-02-16 02:04:27 -05:00
|
|
|
sigc::ptr_fun (add_if_covered),
|
|
|
|
&(*t), &new_selection));
|
2010-03-02 13:05:26 -05:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (!in_command) {
|
|
|
|
begin_reversible_command (_("separate"));
|
|
|
|
in_command = true;
|
|
|
|
}
|
2010-06-28 11:01:14 -04:00
|
|
|
|
|
|
|
/* pick up changes to existing regions */
|
|
|
|
|
|
|
|
vector<StatefulDiffCommand*> cmds;
|
|
|
|
playlist->rdiff (cmds);
|
|
|
|
for (vector<StatefulDiffCommand*>::iterator j = cmds.begin(); j != cmds.end(); ++j) {
|
|
|
|
_session->add_command (*j);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* pick up changes to the playlist itself (adds/removes)
|
|
|
|
*/
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command(new StatefulDiffCommand (playlist));
|
2009-10-14 12:10:01 -04:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (in_command) {
|
|
|
|
selection->set (new_selection);
|
|
|
|
set_mouse_mode (MouseObject);
|
|
|
|
|
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
2006-03-31 19:21:25 -05:00
|
|
|
}
|
|
|
|
|
2010-07-06 07:33:27 -04:00
|
|
|
struct PlaylistState {
|
|
|
|
boost::shared_ptr<Playlist> playlist;
|
|
|
|
XMLNode* before;
|
|
|
|
};
|
|
|
|
|
2009-07-21 15:55:12 -04:00
|
|
|
/** 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.
|
|
|
|
*/
|
2006-03-31 19:21:25 -05:00
|
|
|
void
|
2008-01-10 16:20:59 -05:00
|
|
|
Editor::separate_region_from_selection ()
|
2006-03-31 19:21:25 -05:00
|
|
|
{
|
2008-01-10 16:20:59 -05:00
|
|
|
/* preferentially use *all* ranges in the time selection if we're in range mode
|
|
|
|
to allow discontiguous operation, since get_edit_op_range() currently
|
|
|
|
returns a single range.
|
2006-03-31 19:21:25 -05:00
|
|
|
*/
|
2008-04-11 10:06:50 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (mouse_mode == MouseRange && !selection->time.empty()) {
|
2006-03-31 19:21:25 -05:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
separate_regions_between (selection->time);
|
2006-03-31 19:21:25 -05:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
} else {
|
|
|
|
|
|
|
|
nframes64_t start;
|
|
|
|
nframes64_t end;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (get_edit_op_range (start, end)) {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
AudioRange ar (start, end, 1);
|
|
|
|
TimeSelection ts;
|
|
|
|
ts.push_back (ar);
|
2006-03-31 19:21:25 -05:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
separate_regions_between (ts);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-03-31 19:21:25 -05:00
|
|
|
|
2008-02-19 17:10:27 -05:00
|
|
|
void
|
|
|
|
Editor::separate_region_from_punch ()
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
Location* loc = _session->locations()->auto_punch_location();
|
2008-02-19 17:10:27 -05:00
|
|
|
if (loc) {
|
|
|
|
separate_regions_using_location (*loc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::separate_region_from_loop ()
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
Location* loc = _session->locations()->auto_loop_location();
|
2008-02-19 17:10:27 -05:00
|
|
|
if (loc) {
|
|
|
|
separate_regions_using_location (*loc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
void
|
|
|
|
Editor::separate_regions_using_location (Location& loc)
|
|
|
|
{
|
|
|
|
if (loc.is_mark()) {
|
|
|
|
return;
|
|
|
|
}
|
2006-03-31 19:21:25 -05:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
AudioRange ar (loc.start(), loc.end(), 1);
|
|
|
|
TimeSelection ts;
|
2006-03-31 19:21:25 -05:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
ts.push_back (ar);
|
2006-03-31 19:21:25 -05:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
separate_regions_between (ts);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2010-07-06 07:33:27 -04:00
|
|
|
/** 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 ();
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
|
|
|
Editor::crop_region_to_selection ()
|
|
|
|
{
|
2007-11-12 17:23:01 -05:00
|
|
|
if (!selection->time.empty()) {
|
|
|
|
|
|
|
|
crop_region_to (selection->time.start(), selection->time.end_frame());
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
} else {
|
2007-11-12 17:23:01 -05:00
|
|
|
|
|
|
|
nframes64_t start;
|
|
|
|
nframes64_t end;
|
|
|
|
|
|
|
|
if (get_edit_op_range (start, end)) {
|
|
|
|
crop_region_to (start, end);
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
void
|
2008-09-10 11:03:30 -04:00
|
|
|
Editor::crop_region_to (nframes64_t start, nframes64_t end)
|
2007-11-12 17:23:01 -05:00
|
|
|
{
|
2007-01-09 18:24:54 -05:00
|
|
|
vector<boost::shared_ptr<Playlist> > playlists;
|
|
|
|
boost::shared_ptr<Playlist> playlist;
|
2009-12-13 14:09:52 -05:00
|
|
|
TrackViewList* ts;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
if (selection->tracks.empty()) {
|
|
|
|
ts = &track_views;
|
|
|
|
} else {
|
|
|
|
sort_track_selection ();
|
|
|
|
ts = &selection->tracks;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
for (TrackSelection::iterator i = ts->begin(); i != ts->end(); ++i) {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
RouteTimeAxisView* rtv;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
if ((rtv = dynamic_cast<RouteTimeAxisView*> ((*i))) != 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-06-15 18:05:07 -04:00
|
|
|
boost::shared_ptr<Track> t = rtv->track();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2010-04-21 16:42:22 -04:00
|
|
|
if (t != 0 && ! t->destructive()) {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2006-08-14 04:44:14 -04:00
|
|
|
if ((playlist = rtv->playlist()) != 0) {
|
|
|
|
playlists.push_back (playlist);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
if (playlists.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t the_start;
|
|
|
|
nframes64_t the_end;
|
|
|
|
nframes64_t cnt;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
begin_reversible_command (_("trim to selection"));
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
for (vector<boost::shared_ptr<Playlist> >::iterator i = playlists.begin(); i != playlists.end(); ++i) {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
boost::shared_ptr<Region> region;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
the_start = start;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
if ((region = (*i)->top_region_at(the_start)) == 0) {
|
2007-04-12 19:20:37 -04:00
|
|
|
continue;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
/* now adjust lengths to that we do the right thing
|
|
|
|
if the selection extends beyond the region
|
|
|
|
*/
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
the_start = max (the_start, (nframes64_t) region->position());
|
2007-11-12 17:23:01 -05:00
|
|
|
if (max_frames - the_start < region->length()) {
|
|
|
|
the_end = the_start + region->length() - 1;
|
2007-04-12 19:20:37 -04:00
|
|
|
} else {
|
2007-11-12 17:23:01 -05:00
|
|
|
the_end = max_frames;
|
2007-04-12 19:20:37 -04:00
|
|
|
}
|
2007-11-12 17:23:01 -05:00
|
|
|
the_end = min (end, the_end);
|
|
|
|
cnt = the_end - the_start + 1;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
region->clear_history ();
|
2007-11-12 17:23:01 -05:00
|
|
|
region->trim_to (the_start, cnt, this);
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command (new StatefulDiffCommand (region));
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
commit_reversible_command ();
|
2009-10-14 12:10:01 -04:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
void
|
|
|
|
Editor::region_fill_track ()
|
|
|
|
{
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t end;
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session || rs.empty()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
end = _session->current_end_frame ();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
begin_reversible_command (_("region fill"));
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
|
2006-07-23 08:03:19 -04:00
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
boost::shared_ptr<Region> region ((*i)->region());
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-01-09 18:24:54 -05:00
|
|
|
boost::shared_ptr<Playlist> pl = region->playlist();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
if (end <= region->last_frame()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
double times = (double) (end - region->last_frame()) / (double) region->length();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (times == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
pl->clear_history ();
|
2009-10-21 12:56:58 -04:00
|
|
|
pl->add_region (RegionFactory::create (region), region->last_frame(), times);
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command (new StatefulDiffCommand (pl));
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::region_fill_selection ()
|
|
|
|
{
|
2009-10-21 12:56:58 -04:00
|
|
|
if (clicked_routeview == 0 || !clicked_routeview->is_audio_track()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (selection->time.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-07-03 18:42:22 -04:00
|
|
|
boost::shared_ptr<Region> region = _regions->get_single_selection ();
|
|
|
|
if (region == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t start = selection->time[clicked_selection].start;
|
|
|
|
nframes64_t end = selection->time[clicked_selection].end;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
boost::shared_ptr<Playlist> playlist;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (selection->tracks.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t selection_length = end - start;
|
2005-09-25 14:42:24 -04:00
|
|
|
float times = (float)selection_length / region->length();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
begin_reversible_command (_("fill selection"));
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
|
|
|
|
|
|
|
|
if ((playlist = (*i)->playlist()) == 0) {
|
|
|
|
continue;
|
2009-10-14 12:10:01 -04:00
|
|
|
}
|
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
playlist->clear_history ();
|
2006-08-29 17:21:48 -04:00
|
|
|
playlist->add_region (RegionFactory::create (region), start, times);
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command (new StatefulDiffCommand (playlist));
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
|
|
|
commit_reversible_command ();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2006-01-23 15:39:58 -05:00
|
|
|
|
|
|
|
void
|
2008-01-10 16:20:59 -05:00
|
|
|
Editor::set_region_sync_from_edit_point ()
|
2006-01-23 15:39:58 -05:00
|
|
|
{
|
2008-01-10 16:20:59 -05:00
|
|
|
nframes64_t where = get_preferred_edit_position ();
|
2008-02-16 17:43:18 -05:00
|
|
|
RegionSelection rs;
|
|
|
|
get_regions_for_action (rs);
|
|
|
|
set_sync_point (where, rs);
|
2006-01-23 15:39:58 -05:00
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
2008-01-10 16:20:59 -05:00
|
|
|
Editor::set_sync_point (nframes64_t where, const RegionSelection& rs)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2008-01-10 16:20:59 -05:00
|
|
|
bool in_command = false;
|
2007-11-07 20:40:25 -05:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
for (RegionSelection::const_iterator r = rs.begin(); r != rs.end(); ++r) {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (!(*r)->region()->covers (where)) {
|
|
|
|
continue;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
boost::shared_ptr<Region> region ((*r)->region());
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (!in_command) {
|
|
|
|
begin_reversible_command (_("set sync point"));
|
|
|
|
in_command = true;
|
|
|
|
}
|
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
region->clear_history ();
|
2009-10-19 21:05:33 -04:00
|
|
|
region->set_sync_position (where);
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command(new StatefulDiffCommand (region));
|
2007-05-10 07:53:35 -04:00
|
|
|
}
|
2007-11-07 20:40:25 -05:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (in_command) {
|
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2007-05-10 07:53:35 -04:00
|
|
|
/** Remove the sync positions of the selection */
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
|
|
|
Editor::remove_region_sync ()
|
|
|
|
{
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2007-05-10 07:53:35 -04:00
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
|
|
|
if (rs.empty()) {
|
|
|
|
return;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2007-05-10 07:53:35 -04:00
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
begin_reversible_command (_("remove sync"));
|
|
|
|
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
|
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
(*i)->region()->clear_history ();
|
2008-09-10 11:03:30 -04:00
|
|
|
(*i)->region()->clear_sync_position ();
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command(new StatefulDiffCommand ((*i)->region()));
|
2008-09-10 11:03:30 -04:00
|
|
|
}
|
2007-05-10 07:53:35 -04:00
|
|
|
commit_reversible_command ();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::naturalize ()
|
|
|
|
{
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
|
|
|
if (rs.empty()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
2008-02-16 17:43:18 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
begin_reversible_command (_("naturalize"));
|
2008-02-16 17:43:18 -05:00
|
|
|
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
|
2010-02-11 12:08:34 -05:00
|
|
|
(*i)->region()->clear_history ();
|
2006-08-29 17:21:48 -04:00
|
|
|
(*i)->region()->move_to_natural_position (this);
|
2010-02-11 18:10:29 -05:00
|
|
|
_session->add_command (new StatefulDiffCommand ((*i)->region()));
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::align (RegionPoint what)
|
|
|
|
{
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-01-07 16:12:29 -05:00
|
|
|
|
2008-03-17 16:54:03 -04:00
|
|
|
get_regions_for_action (rs);
|
2007-11-12 17:23:01 -05:00
|
|
|
nframes64_t where = get_preferred_edit_position();
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
if (!rs.empty()) {
|
|
|
|
align_selection (what, where, rs);
|
2007-11-12 17:23:01 -05:00
|
|
|
} else {
|
|
|
|
|
|
|
|
RegionSelection rs;
|
2008-02-16 17:43:18 -05:00
|
|
|
get_regions_at (rs, where, selection->tracks);
|
2007-11-12 17:23:01 -05:00
|
|
|
align_selection (what, where, rs);
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::align_relative (RegionPoint what)
|
|
|
|
{
|
2007-11-12 17:23:01 -05:00
|
|
|
nframes64_t where = get_preferred_edit_position();
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2007-11-12 17:23:01 -05:00
|
|
|
|
2008-03-17 16:54:03 -04:00
|
|
|
get_regions_for_action (rs);
|
2007-11-12 17:23:01 -05:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
if (!rs.empty()) {
|
2007-11-12 17:23:01 -05:00
|
|
|
align_selection_relative (what, where, rs);
|
2009-10-14 12:10:01 -04:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
struct RegionSortByTime {
|
2006-08-14 04:44:14 -04:00
|
|
|
bool operator() (const RegionView* a, const RegionView* b) {
|
2006-08-29 17:21:48 -04:00
|
|
|
return a->region()->position() < b->region()->position();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
2008-09-10 11:03:30 -04:00
|
|
|
Editor::align_selection_relative (RegionPoint point, nframes64_t position, const RegionSelection& rs)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2007-11-12 17:23:01 -05:00
|
|
|
if (rs.empty()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-10-03 14:24:38 -04:00
|
|
|
nframes64_t distance = 0;
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t pos = 0;
|
2008-10-03 14:24:38 -04:00
|
|
|
int dir = 1;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
list<RegionView*> sorted;
|
2007-11-12 17:23:01 -05:00
|
|
|
rs.by_position (sorted);
|
2008-09-10 11:03:30 -04:00
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
boost::shared_ptr<Region> r ((*sorted.begin())->region());
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
switch (point) {
|
|
|
|
case Start:
|
2008-01-10 17:22:29 -05:00
|
|
|
pos = position;
|
|
|
|
if (position > r->position()) {
|
|
|
|
distance = position - r->position();
|
|
|
|
} else {
|
|
|
|
distance = r->position() - position;
|
|
|
|
dir = -1;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
case End:
|
2008-01-10 17:22:29 -05:00
|
|
|
if (position > r->last_frame()) {
|
|
|
|
distance = position - r->last_frame();
|
|
|
|
pos = r->position() + distance;
|
|
|
|
} else {
|
|
|
|
distance = r->last_frame() - position;
|
|
|
|
pos = r->position() - distance;
|
|
|
|
dir = -1;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SyncPoint:
|
2008-01-10 17:22:29 -05:00
|
|
|
pos = r->adjust_to_sync (position);
|
|
|
|
if (pos > r->position()) {
|
|
|
|
distance = pos - r->position();
|
|
|
|
} else {
|
|
|
|
distance = r->position() - pos;
|
|
|
|
dir = -1;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
break;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2008-01-10 17:22:29 -05:00
|
|
|
if (pos == r->position()) {
|
|
|
|
return;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
begin_reversible_command (_("align selection (relative)"));
|
|
|
|
|
2008-01-10 17:22:29 -05:00
|
|
|
/* move first one specially */
|
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
r->clear_history ();
|
2008-01-10 17:22:29 -05:00
|
|
|
r->set_position (pos, this);
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command(new StatefulDiffCommand (r));
|
2008-01-10 17:22:29 -05:00
|
|
|
|
|
|
|
/* move rest by the same amount */
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
sorted.pop_front();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (list<RegionView*>::iterator i = sorted.begin(); i != sorted.end(); ++i) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
boost::shared_ptr<Region> region ((*i)->region());
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
region->clear_history ();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (dir > 0) {
|
2006-08-29 17:21:48 -04:00
|
|
|
region->set_position (region->position() + distance, this);
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2006-08-29 17:21:48 -04:00
|
|
|
region->set_position (region->position() - distance, this);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2010-03-02 13:05:26 -05:00
|
|
|
|
|
|
|
_session->add_command(new StatefulDiffCommand (region));
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-09-10 11:03:30 -04:00
|
|
|
Editor::align_selection (RegionPoint point, nframes64_t position, const RegionSelection& rs)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2007-11-12 17:23:01 -05:00
|
|
|
if (rs.empty()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
begin_reversible_command (_("align selection"));
|
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
for (RegionSelection::const_iterator i = rs.begin(); i != rs.end(); ++i) {
|
2006-07-23 08:03:19 -04:00
|
|
|
align_region_internal ((*i)->region(), point, position);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-09-10 11:03:30 -04:00
|
|
|
Editor::align_region (boost::shared_ptr<Region> region, RegionPoint point, nframes64_t position)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
begin_reversible_command (_("align region"));
|
|
|
|
align_region_internal (region, point, position);
|
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-09-10 11:03:30 -04:00
|
|
|
Editor::align_region_internal (boost::shared_ptr<Region> region, RegionPoint point, nframes64_t position)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2010-03-02 13:05:26 -05:00
|
|
|
region->clear_history ();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
switch (point) {
|
|
|
|
case SyncPoint:
|
2006-08-29 17:21:48 -04:00
|
|
|
region->set_position (region->adjust_to_sync (position), this);
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case End:
|
2006-08-29 17:21:48 -04:00
|
|
|
if (position > region->length()) {
|
|
|
|
region->set_position (position - region->length(), this);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Start:
|
2006-08-29 17:21:48 -04:00
|
|
|
region->set_position (position, this);
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command(new StatefulDiffCommand (region));
|
2009-10-14 12:10:01 -04:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-04-20 17:02:46 -04:00
|
|
|
void
|
|
|
|
Editor::trim_region_front ()
|
|
|
|
{
|
|
|
|
trim_region (true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::trim_region_back ()
|
|
|
|
{
|
|
|
|
trim_region (false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::trim_region (bool front)
|
|
|
|
{
|
|
|
|
nframes64_t where = get_preferred_edit_position();
|
|
|
|
RegionSelection rs;
|
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
|
|
|
if (rs.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
begin_reversible_command (front ? _("trim front") : _("trim back"));
|
|
|
|
|
|
|
|
for (list<RegionView*>::const_iterator i = rs.by_layer().begin(); i != rs.by_layer().end(); ++i) {
|
|
|
|
if (!(*i)->region()->locked()) {
|
2010-07-06 07:33:27 -04:00
|
|
|
|
|
|
|
(*i)->region()->clear_history ();
|
|
|
|
|
2009-04-20 17:02:46 -04:00
|
|
|
if (front) {
|
2009-10-14 12:10:01 -04:00
|
|
|
(*i)->region()->trim_front (where, this);
|
2009-04-20 17:02:46 -04:00
|
|
|
} else {
|
2009-10-14 12:10:01 -04:00
|
|
|
(*i)->region()->trim_end (where, this);
|
2009-04-20 17:02:46 -04:00
|
|
|
}
|
2010-07-06 07:33:27 -04:00
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command (new StatefulDiffCommand ((*i)->region()));
|
2009-04-20 17:02:46 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
|
2007-05-10 07:53:35 -04:00
|
|
|
/** Trim the end of the selected regions to the position of the edit cursor */
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
2007-11-12 17:23:01 -05:00
|
|
|
Editor::trim_region_to_loop ()
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
Location* loc = _session->locations()->auto_loop_location();
|
2007-11-12 17:23:01 -05:00
|
|
|
if (!loc) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
2007-11-12 17:23:01 -05:00
|
|
|
trim_region_to_location (*loc, _("trim to loop"));
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
void
|
|
|
|
Editor::trim_region_to_punch ()
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
Location* loc = _session->locations()->auto_punch_location();
|
2007-11-12 17:23:01 -05:00
|
|
|
if (!loc) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
trim_region_to_location (*loc, _("trim to punch"));
|
|
|
|
}
|
|
|
|
void
|
|
|
|
Editor::trim_region_to_location (const Location& loc, const char* str)
|
|
|
|
{
|
2008-02-16 17:43:18 -05:00
|
|
|
RegionSelection rs;
|
2008-01-07 16:12:29 -05:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
get_regions_for_action (rs);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
begin_reversible_command (str);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ++x) {
|
2009-02-16 02:04:27 -05:00
|
|
|
RegionView* rv = (*x);
|
2007-11-12 17:23:01 -05:00
|
|
|
|
|
|
|
/* require region to span proposed trim */
|
2009-02-16 02:04:27 -05:00
|
|
|
switch (rv->region()->coverage (loc.start(), loc.end())) {
|
2007-11-12 17:23:01 -05:00
|
|
|
case OverlapInternal:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
RouteTimeAxisView* tav = dynamic_cast<RouteTimeAxisView*> (&rv->get_time_axis_view());
|
2009-02-16 02:04:27 -05:00
|
|
|
if (!tav) {
|
2007-11-12 17:23:01 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
float speed = 1.0;
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t start;
|
|
|
|
nframes64_t end;
|
2007-11-12 17:23:01 -05:00
|
|
|
|
2010-04-21 16:42:22 -04:00
|
|
|
if (tav->track() != 0) {
|
|
|
|
speed = tav->track()->speed();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
start = session_frame_to_track_frame (loc.start(), speed);
|
|
|
|
end = session_frame_to_track_frame (loc.end(), speed);
|
2010-03-02 13:05:26 -05:00
|
|
|
|
|
|
|
rv->region()->clear_history ();
|
2009-02-16 02:04:27 -05:00
|
|
|
rv->region()->trim_to (start, (end - start), this);
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command(new StatefulDiffCommand (rv->region()));
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2007-11-12 17:23:01 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-11-12 17:23:01 -05:00
|
|
|
Editor::trim_region_to_edit_point ()
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2008-02-16 17:43:18 -05:00
|
|
|
RegionSelection rs;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
get_regions_for_action (rs);
|
2008-01-10 17:22:29 -05:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
nframes64_t where = get_preferred_edit_position();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
begin_reversible_command (_("trim region start to edit point"));
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ++x) {
|
2009-02-16 02:04:27 -05:00
|
|
|
RegionView* rv = (*x);
|
2007-11-12 17:23:01 -05:00
|
|
|
|
|
|
|
/* require region to cover trim */
|
2009-02-16 02:04:27 -05:00
|
|
|
if (!rv->region()->covers (where)) {
|
2007-11-12 17:23:01 -05:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
RouteTimeAxisView* tav = dynamic_cast<RouteTimeAxisView*> (&rv->get_time_axis_view());
|
2009-02-16 02:04:27 -05:00
|
|
|
if (!tav) {
|
2007-11-12 17:23:01 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
float speed = 1.0;
|
|
|
|
|
2010-04-21 16:42:22 -04:00
|
|
|
if (tav->track() != 0) {
|
|
|
|
speed = tav->track()->speed();
|
2007-11-12 17:23:01 -05:00
|
|
|
}
|
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
rv->region()->clear_history ();
|
2009-12-17 13:24:23 -05:00
|
|
|
rv->region()->trim_end (session_frame_to_track_frame(where, speed), this);
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command(new StatefulDiffCommand (rv->region()));
|
2007-11-12 17:23:01 -05:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
void
|
|
|
|
Editor::trim_region_from_edit_point ()
|
|
|
|
{
|
2008-02-16 17:43:18 -05:00
|
|
|
RegionSelection rs;
|
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
2008-01-10 17:22:29 -05:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
nframes64_t where = get_preferred_edit_position();
|
|
|
|
|
|
|
|
begin_reversible_command (_("trim region end to edit point"));
|
|
|
|
|
|
|
|
for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ++x) {
|
2009-02-16 02:04:27 -05:00
|
|
|
RegionView* rv = (*x);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
/* require region to cover trim */
|
2009-02-16 02:04:27 -05:00
|
|
|
if (!rv->region()->covers (where)) {
|
2007-11-12 17:23:01 -05:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
RouteTimeAxisView* tav = dynamic_cast<RouteTimeAxisView*> (&rv->get_time_axis_view());
|
2009-02-16 02:04:27 -05:00
|
|
|
if (!tav) {
|
2007-11-12 17:23:01 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
float speed = 1.0;
|
|
|
|
|
2010-04-21 16:42:22 -04:00
|
|
|
if (tav->track() != 0) {
|
|
|
|
speed = tav->track()->speed();
|
2007-11-12 17:23:01 -05:00
|
|
|
}
|
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
rv->region()->clear_history ();
|
2009-12-17 13:24:23 -05:00
|
|
|
rv->region()->trim_front (session_frame_to_track_frame(where, speed), this);
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command(new StatefulDiffCommand (rv->region()));
|
2007-05-10 07:53:35 -04:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
commit_reversible_command ();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2009-04-20 17:02:46 -04:00
|
|
|
void
|
|
|
|
Editor::trim_region_to_previous_region_end ()
|
|
|
|
{
|
|
|
|
return trim_to_region(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::trim_region_to_next_region_start ()
|
|
|
|
{
|
|
|
|
return trim_to_region(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::trim_to_region(bool forward)
|
|
|
|
{
|
|
|
|
RegionSelection rs;
|
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
|
|
|
begin_reversible_command (_("trim to region"));
|
|
|
|
|
|
|
|
boost::shared_ptr<Region> next_region;
|
|
|
|
|
|
|
|
for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ++x) {
|
|
|
|
|
|
|
|
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*x);
|
|
|
|
|
|
|
|
if (!arv) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
AudioTimeAxisView* atav = dynamic_cast<AudioTimeAxisView*> (&arv->get_time_axis_view());
|
2009-04-20 17:02:46 -04:00
|
|
|
|
|
|
|
if (!atav) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
float speed = 1.0;
|
|
|
|
|
2010-04-21 16:42:22 -04:00
|
|
|
if (atav->track() != 0) {
|
|
|
|
speed = atav->track()->speed();
|
2009-04-20 17:02:46 -04:00
|
|
|
}
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-04-20 17:02:46 -04:00
|
|
|
boost::shared_ptr<Region> region = arv->region();
|
|
|
|
boost::shared_ptr<Playlist> playlist (region->playlist());
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
region->clear_history ();
|
2009-04-20 17:02:46 -04:00
|
|
|
|
|
|
|
if(forward){
|
|
|
|
|
|
|
|
next_region = playlist->find_next_region (region->first_frame(), Start, 1);
|
|
|
|
|
|
|
|
if(!next_region){
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2010-07-06 07:33:27 -04:00
|
|
|
region->trim_end((nframes64_t) ( (next_region->first_frame() - 1) * speed), this);
|
2010-02-19 13:09:08 -05:00
|
|
|
arv->region_changed (PropertyChange (ARDOUR::Properties::length));
|
2009-04-20 17:02:46 -04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
next_region = playlist->find_next_region (region->first_frame(), Start, 0);
|
|
|
|
|
|
|
|
if(!next_region){
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
region->trim_front((nframes64_t) ((next_region->last_frame() + 1) * speed), this);
|
2010-02-19 13:09:08 -05:00
|
|
|
|
|
|
|
arv->region_changed (ARDOUR::bounds_change);
|
2009-04-20 17:02:46 -04:00
|
|
|
}
|
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command(new StatefulDiffCommand (region));
|
2009-04-20 17:02:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
2008-01-12 18:45:50 -05:00
|
|
|
Editor::unfreeze_route ()
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2009-02-16 02:04:27 -05:00
|
|
|
if (clicked_routeview == 0 || !clicked_routeview->is_track()) {
|
2008-01-12 18:45:50 -05:00
|
|
|
return;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-02-16 02:04:27 -05:00
|
|
|
clicked_routeview->track()->unfreeze ();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void*
|
|
|
|
Editor::_freeze_thread (void* arg)
|
|
|
|
{
|
2009-12-04 14:24:09 -05:00
|
|
|
SessionEvent::create_per_thread_pool ("freeze events", 64);
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
return static_cast<Editor*>(arg)->freeze_thread ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void*
|
|
|
|
Editor::freeze_thread ()
|
|
|
|
{
|
2010-03-02 13:05:26 -05:00
|
|
|
clicked_routeview->audio_track()->freeze_me (*current_interthread_info);
|
2009-02-27 18:26:10 -05:00
|
|
|
current_interthread_info->done = true;
|
2005-09-25 14:42:24 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-01-12 18:45:50 -05:00
|
|
|
Editor::freeze_route ()
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2008-01-12 18:45:50 -05:00
|
|
|
if (clicked_routeview == 0 || !clicked_routeview->is_audio_track()) {
|
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
InterThreadInfo itt;
|
|
|
|
current_interthread_info = &itt;
|
|
|
|
|
2010-04-14 18:16:46 -04:00
|
|
|
InterthreadProgressWindow ipw (current_interthread_info, _("Freeze"), _("Cancel Freeze"));
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-12-08 22:05:14 -05:00
|
|
|
pthread_create_and_store (X_("freezer"), &itt.thread, _freeze_thread, this);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-03-17 16:54:03 -04:00
|
|
|
track_canvas->get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
while (!itt.done && !itt.cancel) {
|
|
|
|
gtk_main_iteration ();
|
|
|
|
}
|
|
|
|
|
|
|
|
current_interthread_info = 0;
|
2008-03-17 16:54:03 -04:00
|
|
|
track_canvas->get_window()->set_cursor (*current_canvas_cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-03-06 14:28:39 -05:00
|
|
|
Editor::bounce_range_selection (bool replace, bool enable_processing)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
if (selection->time.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
TrackSelection views = selection->tracks;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t start = selection->time[clicked_selection].start;
|
|
|
|
nframes64_t end = selection->time[clicked_selection].end;
|
|
|
|
nframes64_t cnt = end - start + 1;
|
2007-04-12 19:20:37 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
begin_reversible_command (_("bounce range"));
|
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
for (TrackViewList::iterator i = views.begin(); i != views.end(); ++i) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
RouteTimeAxisView* rtv;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
if ((rtv = dynamic_cast<RouteTimeAxisView*> (*i)) == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
continue;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-01-09 18:24:54 -05:00
|
|
|
boost::shared_ptr<Playlist> playlist;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
if ((playlist = rtv->playlist()) == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
InterThreadInfo itt;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
playlist->clear_history ();
|
2010-06-10 18:56:46 -04:00
|
|
|
playlist->clear_owned_history ();
|
|
|
|
|
2009-03-06 14:28:39 -05:00
|
|
|
boost::shared_ptr<Region> r = rtv->track()->bounce_range (start, start+cnt, itt, enable_processing);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
if (replace) {
|
|
|
|
list<AudioRange> ranges;
|
|
|
|
ranges.push_back (AudioRange (start, start+cnt, 0));
|
|
|
|
playlist->cut (ranges); // discard result
|
|
|
|
playlist->add_region (r, start);
|
|
|
|
}
|
|
|
|
|
2010-06-10 18:56:46 -04:00
|
|
|
vector<StatefulDiffCommand*> cmds;
|
|
|
|
playlist->rdiff (cmds);
|
|
|
|
for (vector<StatefulDiffCommand*>::iterator j = cmds.begin(); j != cmds.end(); ++j) {
|
|
|
|
_session->add_command (*j);
|
|
|
|
}
|
|
|
|
|
|
|
|
_session->add_command (new StatefulDiffCommand (playlist));
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
|
2007-05-10 07:53:35 -04:00
|
|
|
/** Cut selected regions, automation points or a time range */
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
|
|
|
Editor::cut ()
|
|
|
|
{
|
|
|
|
cut_copy (Cut);
|
|
|
|
}
|
|
|
|
|
2007-05-10 07:53:35 -04:00
|
|
|
/** Copy selected regions, automation points or a time range */
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
|
|
|
Editor::copy ()
|
|
|
|
{
|
|
|
|
cut_copy (Copy);
|
|
|
|
}
|
|
|
|
|
2007-05-10 07:53:35 -04:00
|
|
|
|
|
|
|
/** @return true if a Cut, Copy or Clear is possible */
|
|
|
|
bool
|
|
|
|
Editor::can_cut_copy () const
|
|
|
|
{
|
|
|
|
switch (current_mouse_mode()) {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-05-10 07:53:35 -04:00
|
|
|
case MouseObject:
|
|
|
|
if (!selection->regions.empty() || !selection->points.empty()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-05-10 07:53:35 -04:00
|
|
|
case MouseRange:
|
|
|
|
if (!selection->time.empty()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-05-10 07:53:35 -04:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Cut, copy or clear selected regions, automation points or a time range.
|
|
|
|
* @param op Operation (Cut, Copy or Clear)
|
|
|
|
*/
|
2009-10-14 12:10:01 -04:00
|
|
|
void
|
2005-09-25 14:42:24 -04:00
|
|
|
Editor::cut_copy (CutCopyOp op)
|
|
|
|
{
|
|
|
|
/* only cancel selection if cut/copy is successful.*/
|
|
|
|
|
|
|
|
string opname;
|
|
|
|
|
|
|
|
switch (op) {
|
|
|
|
case Cut:
|
|
|
|
opname = _("cut");
|
|
|
|
break;
|
|
|
|
case Copy:
|
|
|
|
opname = _("copy");
|
|
|
|
break;
|
|
|
|
case Clear:
|
|
|
|
opname = _("clear");
|
|
|
|
break;
|
|
|
|
}
|
2008-09-10 11:03:30 -04:00
|
|
|
|
|
|
|
/* if we're deleting something, and the mouse is still pressed,
|
|
|
|
the thing we started a drag for will be gone when we release
|
|
|
|
the mouse button(s). avoid this. see part 2 at the end of
|
|
|
|
this function.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (op == Cut || op == Clear) {
|
2010-01-12 11:14:49 -05:00
|
|
|
if (_drags->active ()) {
|
|
|
|
_drags->abort ();
|
2008-09-10 11:03:30 -04:00
|
|
|
}
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
cut_buffer->clear ();
|
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
if (entered_marker) {
|
|
|
|
|
|
|
|
/* cut/delete op while pointing at a marker */
|
|
|
|
|
|
|
|
bool ignored;
|
|
|
|
Location* loc = find_location_from_marker (entered_marker, ignored);
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (_session && loc) {
|
2009-12-11 18:29:48 -05:00
|
|
|
Glib::signal_idle().connect (sigc::bind (sigc::mem_fun(*this, &Editor::really_remove_marker), loc));
|
2007-11-12 17:23:01 -05:00
|
|
|
}
|
|
|
|
|
2010-05-05 18:09:07 -04:00
|
|
|
_drags->abort ();
|
2007-11-12 17:23:01 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-08-10 15:29:29 -04:00
|
|
|
if (internal_editing()) {
|
2008-03-17 16:54:03 -04:00
|
|
|
|
2009-08-10 15:29:29 -04:00
|
|
|
switch (current_mouse_mode()) {
|
|
|
|
case MouseObject:
|
|
|
|
case MouseRange:
|
|
|
|
cut_copy_midi (op);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-08-10 15:29:29 -04:00
|
|
|
} else {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
|
|
|
RegionSelection rs;
|
|
|
|
|
2009-08-10 15:29:29 -04:00
|
|
|
/* we only want to cut regions if some are selected */
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-08-10 15:29:29 -04:00
|
|
|
if (!selection->regions.empty()) {
|
2009-08-24 16:56:24 -04:00
|
|
|
get_regions_for_action (rs, false, false);
|
2009-08-10 15:29:29 -04:00
|
|
|
}
|
2009-08-24 16:56:24 -04:00
|
|
|
|
2009-08-10 15:29:29 -04:00
|
|
|
switch (current_mouse_mode()) {
|
2009-10-14 12:10:01 -04:00
|
|
|
case MouseObject:
|
2009-08-10 15:29:29 -04:00
|
|
|
if (!rs.empty() || !selection->points.empty()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-08-10 15:29:29 -04:00
|
|
|
begin_reversible_command (opname + _(" objects"));
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-08-10 15:29:29 -04:00
|
|
|
if (!rs.empty()) {
|
|
|
|
cut_copy_regions (op, rs);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-08-10 15:29:29 -04:00
|
|
|
if (op == Cut) {
|
|
|
|
selection->clear_regions ();
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2009-08-10 15:29:29 -04:00
|
|
|
if (!selection->points.empty()) {
|
|
|
|
cut_copy_points (op);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-08-10 15:29:29 -04:00
|
|
|
if (op == Cut) {
|
|
|
|
selection->clear_points ();
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
commit_reversible_command ();
|
2009-08-10 15:29:29 -04:00
|
|
|
break; // terminate case statement here
|
2009-10-14 12:10:01 -04:00
|
|
|
}
|
2009-08-10 15:29:29 -04:00
|
|
|
if (!selection->time.empty()) {
|
|
|
|
/* don't cause suprises */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// fall thru if there was nothing selected
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-08-10 15:29:29 -04:00
|
|
|
case MouseRange:
|
|
|
|
if (selection->time.empty()) {
|
|
|
|
nframes64_t start, end;
|
|
|
|
if (!get_edit_op_range (start, end)) {
|
|
|
|
return;
|
|
|
|
}
|
2009-12-13 16:27:19 -05:00
|
|
|
selection->set (start, end);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-08-10 15:29:29 -04:00
|
|
|
begin_reversible_command (opname + _(" range"));
|
|
|
|
cut_copy_ranges (op);
|
|
|
|
commit_reversible_command ();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-08-10 15:29:29 -04:00
|
|
|
if (op == Cut) {
|
|
|
|
selection->clear_time ();
|
|
|
|
}
|
2007-11-12 17:23:01 -05:00
|
|
|
|
2009-08-10 15:29:29 -04:00
|
|
|
break;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-08-10 15:29:29 -04:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
if (op == Cut || op == Clear) {
|
2010-05-05 18:09:07 -04:00
|
|
|
_drags->abort ();
|
2008-09-10 11:03:30 -04:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2007-05-10 07:53:35 -04:00
|
|
|
/** Cut, copy or clear selected automation points.
|
|
|
|
* @param op Operation (Cut, Copy or Clear)
|
|
|
|
*/
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
|
|
|
Editor::cut_copy_points (CutCopyOp op)
|
|
|
|
{
|
|
|
|
for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>((*i).track);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (atv) {
|
|
|
|
atv->cut_copy_clear_objects (selection->points, op);
|
2009-10-14 12:10:01 -04:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-10 15:29:29 -04:00
|
|
|
/** Cut, copy or clear selected automation points.
|
|
|
|
* @param op Operation (Cut, Copy or Clear)
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
Editor::cut_copy_midi (CutCopyOp op)
|
|
|
|
{
|
2009-08-12 21:57:03 -04:00
|
|
|
for (MidiRegionSelection::iterator i = selection->midi_regions.begin(); i != selection->midi_regions.end(); ++i) {
|
2009-08-10 15:29:29 -04:00
|
|
|
MidiRegionView* mrv = *i;
|
|
|
|
mrv->cut_copy_clear (op);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-06 07:33:27 -04:00
|
|
|
|
|
|
|
|
|
|
|
struct lt_playlist {
|
|
|
|
bool operator () (const PlaylistState& a, const PlaylistState& b) {
|
|
|
|
return a.playlist < b.playlist;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
struct PlaylistMapping {
|
2009-07-09 13:58:13 -04:00
|
|
|
TimeAxisView* tv;
|
2007-01-28 12:44:13 -05:00
|
|
|
boost::shared_ptr<Playlist> pl;
|
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
PlaylistMapping (TimeAxisView* tvp) : tv (tvp) {}
|
2007-01-28 12:44:13 -05:00
|
|
|
};
|
|
|
|
|
2009-05-13 17:34:09 -04:00
|
|
|
/** Remove `clicked_regionview' */
|
|
|
|
void
|
|
|
|
Editor::remove_clicked_region ()
|
|
|
|
{
|
|
|
|
if (clicked_routeview == 0 || clicked_regionview == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
boost::shared_ptr<Playlist> playlist = clicked_routeview->playlist();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-05-13 17:34:09 -04:00
|
|
|
begin_reversible_command (_("remove region"));
|
2010-03-02 13:05:26 -05:00
|
|
|
playlist->clear_history ();
|
2009-05-13 17:34:09 -04:00
|
|
|
playlist->remove_region (clicked_regionview->region());
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command(new StatefulDiffCommand (playlist));
|
2009-05-13 17:34:09 -04:00
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Remove the selected regions */
|
|
|
|
void
|
|
|
|
Editor::remove_selected_regions ()
|
|
|
|
{
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2009-05-13 17:34:09 -04:00
|
|
|
get_regions_for_action (rs);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) {
|
2009-05-13 17:34:09 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rs.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
begin_reversible_command (_("remove region"));
|
|
|
|
|
|
|
|
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.
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-05-13 17:34:09 -04:00
|
|
|
regions_to_remove.push_back ((*i)->region());
|
|
|
|
}
|
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
vector<boost::shared_ptr<Playlist> > playlists;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-05-13 17:34:09 -04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
vector<boost::shared_ptr<Playlist> >::iterator i;
|
2009-05-13 17:34:09 -04:00
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
//only prep history if this is a new playlist.
|
2009-05-13 17:34:09 -04:00
|
|
|
for (i = playlists.begin(); i != playlists.end(); ++i) {
|
2010-03-02 13:05:26 -05:00
|
|
|
if ((*i) == playlist) {
|
2009-05-13 17:34:09 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i == playlists.end()) {
|
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
playlist->clear_history ();
|
2009-05-13 17:34:09 -04:00
|
|
|
playlist->freeze ();
|
2010-03-02 13:05:26 -05:00
|
|
|
|
|
|
|
playlists.push_back (playlist);
|
2009-05-13 17:34:09 -04:00
|
|
|
}
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
playlist->remove_region (*rl);
|
2009-05-13 17:34:09 -04:00
|
|
|
}
|
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
vector<boost::shared_ptr<Playlist> >::iterator pl;
|
2009-05-13 17:34:09 -04:00
|
|
|
|
|
|
|
for (pl = playlists.begin(); pl != playlists.end(); ++pl) {
|
2010-03-02 13:05:26 -05:00
|
|
|
(*pl)->thaw ();
|
|
|
|
_session->add_command(new StatefulDiffCommand (*pl));
|
2009-05-13 17:34:09 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
2007-05-10 07:53:35 -04:00
|
|
|
|
|
|
|
/** Cut, copy or clear selected regions.
|
|
|
|
* @param op Operation (Cut, Copy or Clear)
|
|
|
|
*/
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
2008-03-17 16:54:03 -04:00
|
|
|
Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs)
|
2009-05-13 17:34:09 -04:00
|
|
|
{
|
2007-01-28 12:44:13 -05:00
|
|
|
/* we can't use a std::map here because the ordering is important, and we can't trivially sort
|
|
|
|
a map when we want ordered access to both elements. i think.
|
|
|
|
*/
|
|
|
|
|
|
|
|
vector<PlaylistMapping> pmap;
|
2006-10-21 18:59:29 -04:00
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t first_position = max_frames;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2010-03-04 08:15:04 -05:00
|
|
|
typedef set<boost::shared_ptr<Playlist> > FreezeList;
|
|
|
|
FreezeList freezelist;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
/* get ordering correct before we cut/copy */
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
rs.sort_by_position_and_track ();
|
|
|
|
|
|
|
|
for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ++x) {
|
2007-01-28 12:44:13 -05:00
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
first_position = min ((nframes64_t) (*x)->region()->position(), first_position);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (op == Cut || op == Clear) {
|
2007-01-28 12:44:13 -05:00
|
|
|
boost::shared_ptr<Playlist> pl = (*x)->region()->playlist();
|
2007-01-09 18:24:54 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (pl) {
|
2010-03-04 08:15:04 -05:00
|
|
|
FreezeList::iterator fl;
|
2006-10-21 18:59:29 -04:00
|
|
|
|
2009-05-13 17:34:09 -04:00
|
|
|
//only take state if this is a new playlist.
|
|
|
|
for (fl = freezelist.begin(); fl != freezelist.end(); ++fl) {
|
2010-03-04 08:15:04 -05:00
|
|
|
if ((*fl) == pl) {
|
2009-05-13 17:34:09 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-05-13 17:34:09 -04:00
|
|
|
if (fl == freezelist.end()) {
|
2010-03-04 08:15:04 -05:00
|
|
|
pl->clear_history();
|
2005-09-25 14:42:24 -04:00
|
|
|
pl->freeze ();
|
2010-03-04 08:15:04 -05:00
|
|
|
freezelist.insert (pl);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-01-28 12:44:13 -05:00
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
TimeAxisView* tv = &(*x)->get_trackview();
|
2007-01-28 12:44:13 -05:00
|
|
|
vector<PlaylistMapping>::iterator z;
|
|
|
|
|
|
|
|
for (z = pmap.begin(); z != pmap.end(); ++z) {
|
|
|
|
if ((*z).tv == tv) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
if (z == pmap.end()) {
|
|
|
|
pmap.push_back (PlaylistMapping (tv));
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
boost::shared_ptr<Playlist> pl = (*x)->region()->playlist();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
if (!pl) {
|
|
|
|
/* impossible, but this handles it for the future */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
TimeAxisView& tv = (*x)->get_trackview();
|
2007-01-28 12:44:13 -05:00
|
|
|
boost::shared_ptr<Playlist> npl;
|
2006-07-23 08:03:19 -04:00
|
|
|
RegionSelection::iterator tmp;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
tmp = x;
|
|
|
|
++tmp;
|
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
vector<PlaylistMapping>::iterator z;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
for (z = pmap.begin(); z != pmap.end(); ++z) {
|
2009-07-09 13:58:13 -04:00
|
|
|
if ((*z).tv == &tv) {
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
assert (z != pmap.end());
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
if (!(*z).pl) {
|
2009-12-17 13:24:23 -05:00
|
|
|
npl = PlaylistFactory::create (pl->data_type(), *_session, "cutlist", true);
|
2007-01-28 12:44:13 -05:00
|
|
|
npl->freeze();
|
|
|
|
(*z).pl = npl;
|
|
|
|
} else {
|
|
|
|
npl = (*z).pl;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
boost::shared_ptr<Region> r = (*x)->region();
|
2007-04-12 19:20:37 -04:00
|
|
|
boost::shared_ptr<Region> _xx;
|
2007-05-02 09:09:03 -04:00
|
|
|
|
|
|
|
assert (r != 0);
|
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
switch (op) {
|
|
|
|
case Cut:
|
2007-05-02 09:09:03 -04:00
|
|
|
_xx = RegionFactory::create (r);
|
|
|
|
npl->add_region (_xx, r->position() - first_position);
|
|
|
|
pl->remove_region (r);
|
2007-01-28 12:44:13 -05:00
|
|
|
break;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
case Copy:
|
2007-04-12 19:20:37 -04:00
|
|
|
/* copy region before adding, so we're not putting same object into two different playlists */
|
2007-05-02 11:21:51 -04:00
|
|
|
npl->add_region (RegionFactory::create (r), r->position() - first_position);
|
2007-01-28 12:44:13 -05:00
|
|
|
break;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
case Clear:
|
|
|
|
pl->remove_region (r);
|
|
|
|
break;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
x = tmp;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-01-09 18:24:54 -05:00
|
|
|
list<boost::shared_ptr<Playlist> > foo;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
/* the pmap is in the same order as the tracks in which selected regions occured */
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
for (vector<PlaylistMapping>::iterator i = pmap.begin(); i != pmap.end(); ++i) {
|
|
|
|
(*i).pl->thaw();
|
|
|
|
foo.push_back ((*i).pl);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (!foo.empty()) {
|
|
|
|
cut_buffer->set (foo);
|
|
|
|
}
|
2010-03-04 08:15:04 -05:00
|
|
|
|
|
|
|
for (FreezeList::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
|
|
|
|
(*pl)->thaw ();
|
|
|
|
_session->add_command (new StatefulDiffCommand (*pl));
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::cut_copy_ranges (CutCopyOp op)
|
|
|
|
{
|
2009-12-13 14:09:52 -05:00
|
|
|
TrackViewList* ts;
|
|
|
|
TrackViewList entered;
|
2007-11-12 17:23:01 -05:00
|
|
|
|
|
|
|
if (selection->tracks.empty()) {
|
2008-03-17 16:54:03 -04:00
|
|
|
if (!entered_track) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
entered.push_back (entered_track);
|
|
|
|
ts = &entered;
|
2007-11-12 17:23:01 -05:00
|
|
|
} else {
|
|
|
|
ts = &selection->tracks;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (TrackSelection::iterator i = ts->begin(); i != ts->end(); ++i) {
|
2005-09-25 14:42:24 -04:00
|
|
|
(*i)->cut_copy_clear (*selection, op);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::paste (float times)
|
|
|
|
{
|
2007-11-07 20:40:25 -05:00
|
|
|
paste_internal (get_preferred_edit_position(), times);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::mouse_paste ()
|
|
|
|
{
|
2007-11-07 20:40:25 -05:00
|
|
|
nframes64_t where;
|
|
|
|
bool ignored;
|
2006-01-02 15:27:51 -05:00
|
|
|
|
2007-11-07 20:40:25 -05:00
|
|
|
if (!mouse_frame (where, ignored)) {
|
|
|
|
return;
|
|
|
|
}
|
2006-01-02 15:27:51 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
snap_to (where);
|
|
|
|
paste_internal (where, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-09-10 11:03:30 -04:00
|
|
|
Editor::paste_internal (nframes64_t position, float times)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
bool commit = false;
|
|
|
|
|
2009-08-12 21:57:03 -04:00
|
|
|
if (internal_editing()) {
|
|
|
|
if (cut_buffer->midi_notes.empty()) {
|
|
|
|
return;
|
2009-10-14 12:10:01 -04:00
|
|
|
}
|
2009-08-12 21:57:03 -04:00
|
|
|
} else {
|
|
|
|
if (cut_buffer->empty()) {
|
|
|
|
return;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (position == max_frames) {
|
2007-11-07 20:40:25 -05:00
|
|
|
position = get_preferred_edit_position();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
begin_reversible_command (_("paste"));
|
|
|
|
|
2009-12-13 14:09:52 -05:00
|
|
|
TrackViewList ts;
|
|
|
|
TrackViewList::iterator i;
|
2005-09-25 14:42:24 -04:00
|
|
|
size_t nth;
|
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
/* get everything in the correct order */
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (!selection->tracks.empty()) {
|
|
|
|
sort_track_selection ();
|
|
|
|
ts = selection->tracks;
|
|
|
|
} else if (entered_track) {
|
|
|
|
ts.push_back (entered_track);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (nth = 0, i = ts.begin(); i != ts.end(); ++i, ++nth) {
|
2007-01-28 12:44:13 -05:00
|
|
|
|
2009-08-12 21:57:03 -04:00
|
|
|
/* undo/redo is handled by individual tracks/regions */
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-08-12 21:57:03 -04:00
|
|
|
if (internal_editing()) {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-08-12 21:57:03 -04:00
|
|
|
RegionSelection rs;
|
|
|
|
RegionSelection::iterator r;
|
|
|
|
MidiNoteSelection::iterator cb;
|
|
|
|
|
|
|
|
get_regions_at (rs, position, ts);
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
for (cb = cut_buffer->midi_notes.begin(), r = rs.begin();
|
2009-08-13 15:48:10 -04:00
|
|
|
cb != cut_buffer->midi_notes.end() && r != rs.end(); ++r) {
|
2009-08-12 21:57:03 -04:00
|
|
|
MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (*r);
|
|
|
|
if (mrv) {
|
2009-08-13 15:48:10 -04:00
|
|
|
mrv->paste (position, times, **cb);
|
2009-08-12 21:57:03 -04:00
|
|
|
++cb;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if ((*i)->paste (position, times, *cut_buffer, nth)) {
|
|
|
|
commit = true;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (commit) {
|
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2006-07-23 08:03:19 -04:00
|
|
|
Editor::duplicate_some_regions (RegionSelection& regions, float times)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2009-10-14 12:10:01 -04:00
|
|
|
boost::shared_ptr<Playlist> playlist;
|
2008-01-10 16:20:59 -05:00
|
|
|
RegionSelection sel = regions; // clear (below) may clear the argument list if its the current region selection
|
|
|
|
RegionSelection foo;
|
|
|
|
|
2009-12-01 18:56:29 -05:00
|
|
|
nframes_t const start_frame = regions.start ();
|
|
|
|
nframes_t const end_frame = regions.end_frame ();
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
begin_reversible_command (_("duplicate region"));
|
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
selection->clear_regions ();
|
2006-01-08 09:50:41 -05:00
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
for (RegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
boost::shared_ptr<Region> r ((*i)->region());
|
2006-01-08 01:08:15 -05:00
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
TimeAxisView& tv = (*i)->get_time_axis_view();
|
|
|
|
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (&tv);
|
2008-01-10 16:20:59 -05:00
|
|
|
latest_regionviews.clear ();
|
2009-12-11 18:29:48 -05:00
|
|
|
sigc::connection c = rtv->view()->RegionViewAdded.connect (sigc::mem_fun(*this, &Editor::collect_new_region_view));
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
playlist = (*i)->region()->playlist();
|
2010-03-02 13:05:26 -05:00
|
|
|
playlist->clear_history ();
|
2010-07-06 07:33:27 -04:00
|
|
|
playlist->duplicate (r, end_frame + (r->first_frame() - start_frame), times);
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command(new StatefulDiffCommand (playlist));
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-01-08 01:08:15 -05:00
|
|
|
c.disconnect ();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
foo.insert (foo.end(), latest_regionviews.begin(), latest_regionviews.end());
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
commit_reversible_command ();
|
2008-01-10 16:20:59 -05:00
|
|
|
|
|
|
|
if (!foo.empty()) {
|
|
|
|
selection->set (foo);
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::duplicate_selection (float times)
|
|
|
|
{
|
|
|
|
if (selection->time.empty() || selection->tracks.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
boost::shared_ptr<Playlist> playlist;
|
2008-02-16 17:43:18 -05:00
|
|
|
vector<boost::shared_ptr<Region> > new_regions;
|
|
|
|
vector<boost::shared_ptr<Region> >::iterator ri;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
create_region_from_selection (new_regions);
|
|
|
|
|
|
|
|
if (new_regions.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
begin_reversible_command (_("duplicate selection"));
|
|
|
|
|
|
|
|
ri = new_regions.begin();
|
|
|
|
|
|
|
|
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
|
|
|
|
if ((playlist = (*i)->playlist()) == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
2010-03-02 13:05:26 -05:00
|
|
|
playlist->clear_history ();
|
2006-08-29 17:21:48 -04:00
|
|
|
playlist->duplicate (*ri, selection->time[clicked_selection].end, times);
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command (new StatefulDiffCommand (playlist));
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
++ri;
|
|
|
|
if (ri == new_regions.end()) {
|
|
|
|
--ri;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
|
2006-05-19 16:10:35 -04:00
|
|
|
void
|
|
|
|
Editor::reset_point_selection ()
|
|
|
|
{
|
|
|
|
/* reset all selected points to the relevant default value */
|
|
|
|
|
|
|
|
for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>((*i).track);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2006-05-19 16:10:35 -04:00
|
|
|
if (atv) {
|
|
|
|
atv->reset_objects (selection->points);
|
2009-10-14 12:10:01 -04:00
|
|
|
}
|
2006-05-19 16:10:35 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
|
|
|
Editor::center_playhead ()
|
|
|
|
{
|
2009-06-13 13:52:51 -04:00
|
|
|
float page = _canvas_width * frames_per_unit;
|
2005-09-25 14:42:24 -04:00
|
|
|
center_screen_internal (playhead_cursor->current_frame, page);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-11-12 17:23:01 -05:00
|
|
|
Editor::center_edit_point ()
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2009-06-13 13:52:51 -04:00
|
|
|
float page = _canvas_width * frames_per_unit;
|
2007-11-07 20:40:25 -05:00
|
|
|
center_screen_internal (get_preferred_edit_position(), page);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-01-09 18:24:54 -05:00
|
|
|
Editor::clear_playlist (boost::shared_ptr<Playlist> playlist)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
begin_reversible_command (_("clear playlist"));
|
2010-03-02 13:05:26 -05:00
|
|
|
playlist->clear_history ();
|
2007-01-09 18:24:54 -05:00
|
|
|
playlist->clear ();
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command (new StatefulDiffCommand (playlist));
|
2005-09-25 14:42:24 -04:00
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-01-12 18:45:50 -05:00
|
|
|
Editor::nudge_track (bool use_edit, bool forwards)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2009-10-14 12:10:01 -04:00
|
|
|
boost::shared_ptr<Playlist> playlist;
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t distance;
|
|
|
|
nframes64_t next_distance;
|
|
|
|
nframes64_t start;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
if (use_edit) {
|
2007-11-07 20:40:25 -05:00
|
|
|
start = get_preferred_edit_position();
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
|
|
|
start = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((distance = get_nudge_distance (start, next_distance)) == 0) {
|
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (selection->tracks.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
begin_reversible_command (_("nudge track"));
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
|
|
|
|
|
|
|
|
if ((playlist = (*i)->playlist()) == 0) {
|
|
|
|
continue;
|
2009-10-14 12:10:01 -04:00
|
|
|
}
|
|
|
|
|
2010-03-04 08:15:04 -05:00
|
|
|
playlist->clear_history ();
|
|
|
|
playlist->clear_owned_history ();
|
2010-03-02 13:05:26 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
playlist->nudge_after (start, distance, forwards);
|
2010-03-04 08:15:04 -05:00
|
|
|
|
|
|
|
vector<StatefulDiffCommand*> cmds;
|
|
|
|
|
|
|
|
playlist->rdiff (cmds);
|
|
|
|
|
|
|
|
for (vector<StatefulDiffCommand*>::iterator c = cmds.begin(); c != cmds.end(); ++c) {
|
|
|
|
_session->add_command (*c);
|
|
|
|
}
|
|
|
|
|
|
|
|
_session->add_command (new StatefulDiffCommand (playlist));
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
|
|
|
commit_reversible_command ();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::remove_last_capture ()
|
|
|
|
{
|
|
|
|
vector<string> choices;
|
|
|
|
string prompt;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
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)");
|
|
|
|
|
|
|
|
choices.push_back (_("No, do nothing."));
|
2006-04-20 07:41:45 -04:00
|
|
|
choices.push_back (_("Yes, destroy it."));
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-12-22 20:26:33 -05:00
|
|
|
Gtkmm2ext::Choice prompter (_("Destroy last capture"), prompt, choices);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2006-04-20 07:41:45 -04:00
|
|
|
if (prompter.run () == 1) {
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->remove_last_capture ();
|
2010-06-23 16:14:07 -04:00
|
|
|
_regions->redisplay ();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2005-11-24 09:59:36 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->remove_last_capture();
|
2010-06-23 16:14:07 -04:00
|
|
|
_regions->redisplay ();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-01-12 18:45:50 -05:00
|
|
|
Editor::normalize_region ()
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2009-06-20 10:02:27 -04:00
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
if (rs.empty()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-06-20 10:02:27 -04:00
|
|
|
Dialog dialog (rs.size() > 1 ? _("Normalize regions") : _("Normalize region"));
|
|
|
|
HBox hbox;
|
2010-04-30 11:00:00 -04:00
|
|
|
hbox.set_spacing (6);
|
|
|
|
hbox.set_border_width (6);
|
2009-06-20 10:02:27 -04:00
|
|
|
hbox.pack_start (*manage (new Label (_("Normalize to:"))));
|
|
|
|
SpinButton spin (0.2, 2);
|
|
|
|
spin.set_range (-112, 0);
|
|
|
|
spin.set_increments (0.1, 1);
|
|
|
|
spin.set_value (0);
|
|
|
|
hbox.pack_start (spin);
|
2009-06-20 11:46:43 -04:00
|
|
|
spin.set_value (_last_normalization_value);
|
2009-06-20 10:02:27 -04:00
|
|
|
hbox.pack_start (*manage (new Label (_("dbFS"))));
|
|
|
|
hbox.show_all ();
|
2010-04-30 11:00:00 -04:00
|
|
|
dialog.get_vbox()->set_spacing (12);
|
2009-06-20 10:02:27 -04:00
|
|
|
dialog.get_vbox()->pack_start (hbox);
|
|
|
|
dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
|
|
|
|
dialog.add_button (_("Normalize"), RESPONSE_ACCEPT);
|
|
|
|
|
|
|
|
if (dialog.run () == RESPONSE_CANCEL) {
|
|
|
|
return;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
begin_reversible_command (_("normalize"));
|
|
|
|
|
2008-03-17 16:54:03 -04:00
|
|
|
track_canvas->get_window()->set_cursor (*wait_cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
gdk_flush ();
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) {
|
2006-07-23 08:03:19 -04:00
|
|
|
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
|
|
|
|
if (!arv)
|
|
|
|
continue;
|
2010-03-02 13:05:26 -05:00
|
|
|
arv->region()->clear_history ();
|
2009-06-20 10:02:27 -04:00
|
|
|
arv->audio_region()->normalize_to (spin.get_value());
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command (new StatefulDiffCommand (arv->region()));
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
commit_reversible_command ();
|
2008-03-17 16:54:03 -04:00
|
|
|
track_canvas->get_window()->set_cursor (*current_canvas_cursor);
|
2009-06-20 11:46:43 -04:00
|
|
|
|
|
|
|
_last_normalization_value = spin.get_value ();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2009-09-09 12:39:33 -04:00
|
|
|
Editor::reset_region_scale_amplitude ()
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-01-19 00:06:33 -05:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
|
|
|
if (rs.empty()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-09-09 12:39:33 -04:00
|
|
|
begin_reversible_command ("reset gain");
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) {
|
2006-07-23 08:03:19 -04:00
|
|
|
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
|
|
|
|
if (!arv)
|
|
|
|
continue;
|
2010-03-02 13:05:26 -05:00
|
|
|
arv->region()->clear_history ();
|
2006-08-29 17:21:48 -04:00
|
|
|
arv->audio_region()->set_scale_amplitude (1.0f);
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command (new StatefulDiffCommand (arv->region()));
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
|
2008-01-19 00:06:33 -05:00
|
|
|
void
|
|
|
|
Editor::adjust_region_scale_amplitude (bool up)
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) {
|
2008-01-19 00:06:33 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-01-19 00:06:33 -05:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
|
|
|
if (rs.empty()) {
|
2008-01-19 00:06:33 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
begin_reversible_command ("denormalize");
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) {
|
2008-01-19 00:06:33 -05:00
|
|
|
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
|
2010-03-02 13:05:26 -05:00
|
|
|
if (!arv) {
|
2008-01-19 00:06:33 -05:00
|
|
|
continue;
|
2010-03-02 13:05:26 -05:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
arv->region()->clear_history ();
|
|
|
|
|
2008-01-19 00:06:33 -05:00
|
|
|
double fraction = gain_to_slider_position (arv->audio_region()->scale_amplitude ());
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-01-19 00:06:33 -05:00
|
|
|
if (up) {
|
|
|
|
fraction += 0.05;
|
|
|
|
fraction = min (fraction, 1.0);
|
|
|
|
} else {
|
|
|
|
fraction -= 0.05;
|
|
|
|
fraction = max (fraction, 0.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!up && fraction <= 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
fraction = slider_position_to_gain (fraction);
|
|
|
|
|
2008-02-01 22:57:35 -05:00
|
|
|
if (up && fraction >= 2.0) {
|
|
|
|
continue;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-01-19 00:06:33 -05:00
|
|
|
arv->audio_region()->set_scale_amplitude (fraction);
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command (new StatefulDiffCommand (arv->region()));
|
2008-01-19 00:06:33 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
void
|
2008-01-12 18:45:50 -05:00
|
|
|
Editor::reverse_region ()
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
Reverse rev (*_session);
|
2005-09-25 14:42:24 -04:00
|
|
|
apply_filter (rev, _("reverse regions"));
|
|
|
|
}
|
|
|
|
|
2009-04-29 13:01:14 -04:00
|
|
|
void
|
|
|
|
Editor::strip_region_silence ()
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) {
|
2009-04-29 13:01:14 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-04-30 13:07:57 -04:00
|
|
|
RegionSelection rs;
|
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
|
|
|
if (rs.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::list<boost::shared_ptr<AudioRegion> > ar;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-04-30 13:07:57 -04:00
|
|
|
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
|
|
|
|
AudioRegionView* const arv = dynamic_cast<AudioRegionView*> (*i);
|
|
|
|
if (arv) {
|
|
|
|
ar.push_back (arv->audio_region ());
|
|
|
|
}
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2010-03-04 21:09:37 -05:00
|
|
|
StripSilenceDialog d (_session, ar);
|
2009-04-29 13:01:14 -04:00
|
|
|
int const r = d.run ();
|
|
|
|
|
|
|
|
if (r == Gtk::RESPONSE_OK) {
|
2009-12-17 13:24:23 -05:00
|
|
|
StripSilence s (*_session, d.threshold (), d.minimum_length (), d.fade_length ());
|
2009-04-29 13:01:14 -04:00
|
|
|
apply_filter (s, _("strip silence"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-07 12:53:53 -04:00
|
|
|
Command*
|
2009-08-26 23:09:30 -04:00
|
|
|
Editor::apply_midi_note_edit_op_to_region (MidiOperator& op, MidiRegionView& mrv)
|
|
|
|
{
|
|
|
|
Evoral::Sequence<Evoral::MusicalTime>::Notes selected;
|
2010-05-20 11:06:30 -04:00
|
|
|
mrv.selection_as_notelist (selected, true);
|
2009-09-07 12:53:53 -04:00
|
|
|
|
|
|
|
vector<Evoral::Sequence<Evoral::MusicalTime>::Notes> v;
|
2009-08-26 23:09:30 -04:00
|
|
|
v.push_back (selected);
|
|
|
|
|
2009-09-07 12:53:53 -04:00
|
|
|
return op (mrv.midi_region()->model(), v);
|
2009-08-26 23:09:30 -04:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-08-26 23:09:30 -04:00
|
|
|
void
|
|
|
|
Editor::apply_midi_note_edit_op (MidiOperator& op)
|
|
|
|
{
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2009-09-07 12:53:53 -04:00
|
|
|
Command* cmd;
|
2009-08-26 23:09:30 -04:00
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
|
|
|
if (rs.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
begin_reversible_command (op.name ());
|
|
|
|
|
|
|
|
for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ) {
|
|
|
|
RegionSelection::iterator tmp = r;
|
|
|
|
++tmp;
|
|
|
|
|
|
|
|
MidiRegionView* const mrv = dynamic_cast<MidiRegionView*> (*r);
|
|
|
|
|
|
|
|
if (mrv) {
|
2009-09-07 12:53:53 -04:00
|
|
|
cmd = apply_midi_note_edit_op_to_region (op, *mrv);
|
|
|
|
if (cmd) {
|
|
|
|
(*cmd)();
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->add_command (cmd);
|
2009-09-07 12:53:53 -04:00
|
|
|
}
|
2009-08-26 23:09:30 -04:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-08-26 23:09:30 -04:00
|
|
|
r = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
commit_reversible_command ();
|
|
|
|
rs.clear ();
|
|
|
|
}
|
2007-08-06 01:30:18 -04:00
|
|
|
|
2010-05-18 23:03:28 -04:00
|
|
|
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_history ();
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
2008-01-12 18:45:50 -05:00
|
|
|
Editor::quantize_region ()
|
2007-08-06 01:30:18 -04:00
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) {
|
2007-08-06 01:30:18 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-08-26 23:09:30 -04:00
|
|
|
QuantizeDialog* qd = new QuantizeDialog (*this);
|
|
|
|
|
|
|
|
qd->present ();
|
2009-10-26 22:36:42 -04:00
|
|
|
const int r = qd->run ();
|
2009-08-26 23:09:30 -04:00
|
|
|
qd->hide ();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-10-26 22:36:42 -04:00
|
|
|
if (r == Gtk::RESPONSE_OK) {
|
2009-12-17 13:24:23 -05:00
|
|
|
Quantize quant (*_session, Plain,
|
2009-10-26 22:36:42 -04:00
|
|
|
qd->snap_start(), qd->snap_end(),
|
|
|
|
qd->start_grid_size(), qd->end_grid_size(),
|
|
|
|
qd->strength(), qd->swing(), qd->threshold());
|
2009-08-26 23:09:30 -04:00
|
|
|
|
2009-10-26 22:36:42 -04:00
|
|
|
apply_midi_note_edit_op (quant);
|
|
|
|
}
|
2007-08-06 01:30:18 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::apply_filter (Filter& filter, string command)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
|
|
|
if (rs.empty()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
begin_reversible_command (command);
|
|
|
|
|
2008-03-17 16:54:03 -04:00
|
|
|
track_canvas->get_window()->set_cursor (*wait_cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
gdk_flush ();
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ) {
|
2007-08-06 01:30:18 -04:00
|
|
|
RegionSelection::iterator tmp = r;
|
|
|
|
++tmp;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-08-06 01:30:18 -04:00
|
|
|
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
|
|
|
|
if (arv) {
|
|
|
|
boost::shared_ptr<Playlist> playlist = arv->region()->playlist();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-08-06 01:30:18 -04:00
|
|
|
if (arv->audio_region()->apply (filter) == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
playlist->clear_history ();
|
|
|
|
|
2009-04-29 13:01:14 -04:00
|
|
|
if (filter.results.empty ()) {
|
|
|
|
|
|
|
|
/* no regions returned; remove the old one */
|
|
|
|
playlist->remove_region (arv->region ());
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-04-29 13:01:14 -04:00
|
|
|
} else {
|
|
|
|
|
|
|
|
std::vector<boost::shared_ptr<Region> >::iterator res = filter.results.begin ();
|
|
|
|
|
|
|
|
/* first region replaces the old one */
|
|
|
|
playlist->replace_region (arv->region(), *res, (*res)->position());
|
|
|
|
++res;
|
|
|
|
|
|
|
|
/* add the rest */
|
|
|
|
while (res != filter.results.end()) {
|
|
|
|
playlist->add_region (*res, (*res)->position());
|
|
|
|
++res;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-04-29 13:01:14 -04:00
|
|
|
}
|
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command(new StatefulDiffCommand (playlist));
|
2007-08-06 01:30:18 -04:00
|
|
|
} else {
|
|
|
|
goto out;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
r = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
commit_reversible_command ();
|
2008-02-16 17:43:18 -05:00
|
|
|
rs.clear ();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
out:
|
2008-03-17 16:54:03 -04:00
|
|
|
track_canvas->get_window()->set_cursor (*current_canvas_cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::region_selection_op (void (Region::*pmf)(void))
|
|
|
|
{
|
2006-07-23 08:03:19 -04:00
|
|
|
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
|
2006-08-29 17:21:48 -04:00
|
|
|
Region* region = (*i)->region().get();
|
|
|
|
(region->*pmf)();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::region_selection_op (void (Region::*pmf)(void*), void *arg)
|
|
|
|
{
|
2006-07-23 08:03:19 -04:00
|
|
|
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
|
2006-08-29 17:21:48 -04:00
|
|
|
Region* region = (*i)->region().get();
|
|
|
|
(region->*pmf)(arg);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::region_selection_op (void (Region::*pmf)(bool), bool yn)
|
|
|
|
{
|
2006-07-23 08:03:19 -04:00
|
|
|
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
|
2006-08-29 17:21:48 -04:00
|
|
|
Region* region = (*i)->region().get();
|
|
|
|
(region->*pmf)(yn);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::external_edit_region ()
|
|
|
|
{
|
|
|
|
/* more to come */
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-09-10 11:03:30 -04:00
|
|
|
Editor::brush (nframes64_t pos)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2006-07-23 08:03:19 -04:00
|
|
|
RegionSelection sel;
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
|
|
|
snap_to (pos);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
if (rs.empty()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
|
2005-09-25 14:42:24 -04:00
|
|
|
mouse_brush_insert_region ((*i), pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-11-19 11:45:16 -05:00
|
|
|
void
|
|
|
|
Editor::reset_region_gain_envelopes ()
|
|
|
|
{
|
2010-03-01 19:00:00 -05:00
|
|
|
RegionSelection rs = get_equivalent_regions (selection->regions, ARDOUR::Properties::edit.property_id);
|
2008-02-16 17:43:18 -05:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session || rs.empty()) {
|
2006-11-19 11:45:16 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->begin_reversible_command (_("reset region gain"));
|
2006-11-19 11:45:16 -05:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
|
2006-11-19 11:45:16 -05:00
|
|
|
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
|
|
|
|
if (arv) {
|
2007-06-29 00:02:58 -04:00
|
|
|
boost::shared_ptr<AutomationList> alist (arv->audio_region()->envelope());
|
|
|
|
XMLNode& before (alist->get_state());
|
2006-11-19 11:45:16 -05:00
|
|
|
|
|
|
|
arv->audio_region()->set_default_envelope ();
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->add_command (new MementoCommand<AutomationList>(*arv->audio_region()->envelope().get(), &before, &alist->get_state()));
|
2006-11-19 11:45:16 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->commit_reversible_command ();
|
2006-11-19 11:45:16 -05:00
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
2007-10-11 18:07:47 -04:00
|
|
|
Editor::toggle_gain_envelope_visibility ()
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2010-03-01 19:00:00 -05:00
|
|
|
RegionSelection rs = get_equivalent_regions (selection->regions, ARDOUR::Properties::edit.property_id);
|
2008-02-16 17:43:18 -05:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session || rs.empty()) {
|
2009-06-26 07:22:16 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->begin_reversible_command (_("region gain envelope visible"));
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
|
2006-07-23 08:03:19 -04:00
|
|
|
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
|
2006-11-19 11:45:16 -05:00
|
|
|
if (arv) {
|
2010-03-02 13:05:26 -05:00
|
|
|
arv->region()->clear_history ();
|
2008-01-12 18:45:50 -05:00
|
|
|
arv->set_envelope_visible (!arv->envelope_visible());
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command (new StatefulDiffCommand (arv->region()));
|
2006-11-19 11:45:16 -05:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2009-06-26 07:22:16 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->commit_reversible_command ();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-10-11 18:07:47 -04:00
|
|
|
Editor::toggle_gain_envelope_active ()
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2010-03-01 19:00:00 -05:00
|
|
|
RegionSelection rs = get_equivalent_regions (selection->regions, ARDOUR::Properties::edit.property_id);
|
2008-02-16 17:43:18 -05:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session || rs.empty()) {
|
2009-06-26 07:22:16 -04:00
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->begin_reversible_command (_("region gain envelope active"));
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
|
2006-07-23 08:03:19 -04:00
|
|
|
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
|
2006-11-19 11:45:16 -05:00
|
|
|
if (arv) {
|
2010-02-11 12:08:34 -05:00
|
|
|
arv->region()->clear_history ();
|
2008-01-12 18:45:50 -05:00
|
|
|
arv->audio_region()->set_envelope_active (!arv->audio_region()->envelope_active());
|
2010-02-11 18:10:29 -05:00
|
|
|
_session->add_command (new StatefulDiffCommand (arv->region()));
|
2007-10-11 18:07:47 -04:00
|
|
|
}
|
2007-05-14 12:16:54 -04:00
|
|
|
}
|
2009-06-26 07:22:16 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->commit_reversible_command ();
|
2007-05-14 12:16:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-10-11 18:07:47 -04:00
|
|
|
Editor::toggle_region_lock ()
|
2007-05-14 12:16:54 -04:00
|
|
|
{
|
2010-03-01 19:00:00 -05:00
|
|
|
RegionSelection rs = get_equivalent_regions (selection->regions, ARDOUR::Properties::edit.property_id);
|
2008-02-16 17:43:18 -05:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session || rs.empty()) {
|
2009-06-26 07:22:16 -04:00
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->begin_reversible_command (_("region lock"));
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
|
2010-02-11 12:08:34 -05:00
|
|
|
(*i)->region()->clear_history ();
|
2008-01-12 18:45:50 -05:00
|
|
|
(*i)->region()->set_locked (!(*i)->region()->locked());
|
2010-02-11 18:10:29 -05:00
|
|
|
_session->add_command (new StatefulDiffCommand ((*i)->region()));
|
2006-11-19 11:45:16 -05:00
|
|
|
}
|
2009-06-26 07:22:16 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->commit_reversible_command ();
|
2006-11-19 11:45:16 -05:00
|
|
|
}
|
|
|
|
|
2008-02-02 12:22:04 -05:00
|
|
|
void
|
2010-05-02 10:08:37 -04:00
|
|
|
Editor::toggle_region_lock_style ()
|
2008-02-02 12:22:04 -05:00
|
|
|
{
|
2010-03-01 19:00:00 -05:00
|
|
|
RegionSelection rs = get_equivalent_regions (selection->regions, ARDOUR::Properties::edit.property_id);
|
2008-02-16 17:43:18 -05:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session || rs.empty()) {
|
2009-06-26 07:22:16 -04:00
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->begin_reversible_command (_("region lock style"));
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
|
2010-03-02 13:05:26 -05:00
|
|
|
(*i)->region()->clear_history ();
|
2010-06-27 20:34:09 -04:00
|
|
|
PositionLockStyle const ns = (*i)->region()->position_lock_style() == AudioTime ? MusicTime : AudioTime;
|
2010-05-02 10:08:37 -04:00
|
|
|
(*i)->region()->set_position_lock_style (ns);
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command (new StatefulDiffCommand ((*i)->region()));
|
2008-02-02 12:22:04 -05:00
|
|
|
}
|
2009-06-26 07:22:16 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->commit_reversible_command ();
|
2008-02-02 12:22:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-11-19 11:45:16 -05:00
|
|
|
void
|
2007-10-11 18:07:47 -04:00
|
|
|
Editor::toggle_region_mute ()
|
2006-11-19 11:45:16 -05:00
|
|
|
{
|
2010-03-01 19:00:00 -05:00
|
|
|
RegionSelection rs = get_equivalent_regions (selection->regions, ARDOUR::Properties::edit.property_id);
|
2008-02-16 17:43:18 -05:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session || rs.empty()) {
|
2009-06-26 07:22:16 -04:00
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->begin_reversible_command (_("region mute"));
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
|
2010-02-11 12:08:34 -05:00
|
|
|
(*i)->region()->clear_history ();
|
2008-01-12 18:45:50 -05:00
|
|
|
(*i)->region()->set_muted (!(*i)->region()->muted());
|
2010-02-11 18:10:29 -05:00
|
|
|
_session->add_command (new StatefulDiffCommand ((*i)->region()));
|
2006-11-19 11:45:16 -05:00
|
|
|
}
|
2009-06-26 07:22:16 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->commit_reversible_command ();
|
2006-11-19 11:45:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-10-11 18:07:47 -04:00
|
|
|
Editor::toggle_region_opaque ()
|
2006-11-19 11:45:16 -05:00
|
|
|
{
|
2010-03-01 19:00:00 -05:00
|
|
|
RegionSelection rs = get_equivalent_regions (selection->regions, ARDOUR::Properties::edit.property_id);
|
2008-02-16 17:43:18 -05:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session || rs.empty()) {
|
2009-06-26 07:22:16 -04:00
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->begin_reversible_command (_("region opacity"));
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
|
2010-02-11 12:08:34 -05:00
|
|
|
(*i)->region()->clear_history ();
|
2008-01-12 18:45:50 -05:00
|
|
|
(*i)->region()->set_opaque (!(*i)->region()->opaque());
|
2010-02-11 18:10:29 -05:00
|
|
|
_session->add_command (new StatefulDiffCommand ((*i)->region()));
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2009-06-26 07:22:16 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->commit_reversible_command ();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2007-01-28 12:44:13 -05:00
|
|
|
|
2008-12-12 09:43:24 -05:00
|
|
|
void
|
|
|
|
Editor::toggle_record_enable ()
|
|
|
|
{
|
|
|
|
bool new_state = false;
|
|
|
|
bool first = true;
|
|
|
|
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
|
2009-07-09 13:58:13 -04:00
|
|
|
RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView *>(*i);
|
2008-12-12 09:43:24 -05:00
|
|
|
if (!rtav)
|
|
|
|
continue;
|
|
|
|
if (!rtav->is_track())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (first) {
|
|
|
|
new_state = !rtav->track()->record_enabled();
|
|
|
|
first = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
rtav->track()->set_record_enable(new_state, this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
void
|
|
|
|
Editor::set_fade_length (bool in)
|
|
|
|
{
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
2009-06-26 07:22:39 -04:00
|
|
|
get_regions_for_action (rs, true);
|
2007-11-12 17:23:01 -05:00
|
|
|
|
2009-06-26 07:22:39 -04:00
|
|
|
if (rs.empty()) {
|
2007-11-12 17:23:01 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-06-26 07:22:39 -04:00
|
|
|
/* we need a region to measure the offset from the start */
|
|
|
|
|
|
|
|
RegionView* rv = rs.front ();
|
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
nframes64_t pos = get_preferred_edit_position();
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t len;
|
2010-05-07 21:20:33 -04:00
|
|
|
char const * cmd;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-01-10 17:22:29 -05:00
|
|
|
if (pos > rv->region()->last_frame() || pos < rv->region()->first_frame()) {
|
|
|
|
/* edit point is outside the relevant region */
|
|
|
|
return;
|
|
|
|
}
|
2007-11-12 17:23:01 -05:00
|
|
|
|
|
|
|
if (in) {
|
|
|
|
if (pos <= rv->region()->position()) {
|
|
|
|
/* can't do it */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
len = pos - rv->region()->position();
|
|
|
|
cmd = _("set fade in length");
|
|
|
|
} else {
|
|
|
|
if (pos >= rv->region()->last_frame()) {
|
|
|
|
/* can't do it */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
len = rv->region()->last_frame() - pos;
|
|
|
|
cmd = _("set fade out length");
|
|
|
|
}
|
|
|
|
|
|
|
|
begin_reversible_command (cmd);
|
|
|
|
|
|
|
|
for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ++x) {
|
|
|
|
AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
|
|
|
|
|
|
|
|
if (!tmp) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-01-10 17:22:29 -05:00
|
|
|
boost::shared_ptr<AutomationList> alist;
|
|
|
|
if (in) {
|
|
|
|
alist = tmp->audio_region()->fade_in();
|
|
|
|
} else {
|
|
|
|
alist = tmp->audio_region()->fade_out();
|
|
|
|
}
|
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
XMLNode &before = alist->get_state();
|
|
|
|
|
|
|
|
if (in) {
|
|
|
|
tmp->audio_region()->set_fade_in_length (len);
|
2008-02-16 17:43:18 -05:00
|
|
|
tmp->audio_region()->set_fade_in_active (true);
|
2007-11-12 17:23:01 -05:00
|
|
|
} else {
|
|
|
|
tmp->audio_region()->set_fade_out_length (len);
|
2008-02-16 17:43:18 -05:00
|
|
|
tmp->audio_region()->set_fade_out_active (true);
|
2007-11-12 17:23:01 -05:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
XMLNode &after = alist->get_state();
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->add_command(new MementoCommand<AutomationList>(*alist, &before, &after));
|
2007-11-12 17:23:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
void
|
|
|
|
Editor::toggle_fade_active (bool in)
|
|
|
|
{
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-01-10 16:20:59 -05:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
|
|
|
if (rs.empty()) {
|
2008-01-10 16:20:59 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* cmd = (in ? _("toggle fade in active") : _("toggle fade out active"));
|
|
|
|
bool have_switch = false;
|
2008-02-01 22:57:35 -05:00
|
|
|
bool yn = false;
|
2008-01-10 16:20:59 -05:00
|
|
|
|
|
|
|
begin_reversible_command (cmd);
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ++x) {
|
2008-01-10 16:20:59 -05:00
|
|
|
AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (!tmp) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
boost::shared_ptr<AudioRegion> region (tmp->audio_region());
|
|
|
|
|
|
|
|
/* make the behaviour consistent across all regions */
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (!have_switch) {
|
2008-01-10 17:22:29 -05:00
|
|
|
if (in) {
|
|
|
|
yn = region->fade_in_active();
|
|
|
|
} else {
|
|
|
|
yn = region->fade_out_active();
|
|
|
|
}
|
2008-01-10 16:20:59 -05:00
|
|
|
have_switch = true;
|
|
|
|
}
|
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
region->clear_history ();
|
|
|
|
|
2008-01-10 17:22:29 -05:00
|
|
|
if (in) {
|
|
|
|
region->set_fade_in_active (!yn);
|
|
|
|
} else {
|
|
|
|
region->set_fade_out_active (!yn);
|
|
|
|
}
|
2010-03-02 13:05:26 -05:00
|
|
|
|
|
|
|
_session->add_command(new StatefulDiffCommand (region));
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
|
2008-01-10 17:22:29 -05:00
|
|
|
commit_reversible_command ();
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
void
|
|
|
|
Editor::set_fade_in_shape (AudioRegion::FadeShape shape)
|
|
|
|
{
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
|
|
|
if (rs.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
2008-01-10 17:22:29 -05:00
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
begin_reversible_command (_("set fade in shape"));
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ++x) {
|
2007-01-28 12:44:13 -05:00
|
|
|
AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
|
|
|
|
|
|
|
|
if (!tmp) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-06-29 00:02:58 -04:00
|
|
|
boost::shared_ptr<AutomationList> alist = tmp->audio_region()->fade_in();
|
|
|
|
XMLNode &before = alist->get_state();
|
2007-01-28 12:44:13 -05:00
|
|
|
|
|
|
|
tmp->audio_region()->set_fade_in_shape (shape);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-06-29 00:02:58 -04:00
|
|
|
XMLNode &after = alist->get_state();
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &after));
|
2007-01-28 12:44:13 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
commit_reversible_command ();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::set_fade_out_shape (AudioRegion::FadeShape shape)
|
|
|
|
{
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
|
|
|
if (rs.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
begin_reversible_command (_("set fade out shape"));
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ++x) {
|
2007-01-28 12:44:13 -05:00
|
|
|
AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
|
|
|
|
|
|
|
|
if (!tmp) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-06-29 00:02:58 -04:00
|
|
|
boost::shared_ptr<AutomationList> alist = tmp->audio_region()->fade_out();
|
|
|
|
XMLNode &before = alist->get_state();
|
2007-01-28 12:44:13 -05:00
|
|
|
|
|
|
|
tmp->audio_region()->set_fade_out_shape (shape);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-06-29 00:02:58 -04:00
|
|
|
XMLNode &after = alist->get_state();
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &after));
|
2007-01-28 12:44:13 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::set_fade_in_active (bool yn)
|
|
|
|
{
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
|
|
|
if (rs.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
begin_reversible_command (_("set fade in active"));
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ++x) {
|
2007-01-28 12:44:13 -05:00
|
|
|
AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
|
|
|
|
|
|
|
|
if (!tmp) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
boost::shared_ptr<AudioRegion> ar (tmp->audio_region());
|
2010-03-02 13:05:26 -05:00
|
|
|
|
|
|
|
ar->clear_history ();
|
2007-01-28 12:44:13 -05:00
|
|
|
ar->set_fade_in_active (yn);
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command (new StatefulDiffCommand (ar));
|
2007-01-28 12:44:13 -05:00
|
|
|
}
|
2008-01-10 17:22:29 -05:00
|
|
|
|
|
|
|
commit_reversible_command ();
|
2007-01-28 12:44:13 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::set_fade_out_active (bool yn)
|
|
|
|
{
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
|
|
|
if (rs.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
begin_reversible_command (_("set fade out active"));
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ++x) {
|
2007-01-28 12:44:13 -05:00
|
|
|
AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
|
|
|
|
|
|
|
|
if (!tmp) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
boost::shared_ptr<AudioRegion> ar (tmp->audio_region());
|
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
ar->clear_history ();
|
2007-01-28 12:44:13 -05:00
|
|
|
ar->set_fade_out_active (yn);
|
2010-03-02 13:05:26 -05:00
|
|
|
_session->add_command(new StatefulDiffCommand (ar));
|
2007-01-28 12:44:13 -05:00
|
|
|
}
|
2008-01-10 17:22:29 -05:00
|
|
|
|
|
|
|
commit_reversible_command ();
|
2007-01-28 12:44:13 -05:00
|
|
|
}
|
|
|
|
|
2008-10-09 17:55:05 -04:00
|
|
|
void
|
|
|
|
Editor::toggle_selected_region_fades (int dir)
|
|
|
|
{
|
|
|
|
RegionSelection rs;
|
|
|
|
RegionSelection::iterator i;
|
|
|
|
boost::shared_ptr<AudioRegion> ar;
|
|
|
|
bool yn;
|
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-10-09 17:55:05 -04:00
|
|
|
if (rs.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = rs.begin(); i != rs.end(); ++i) {
|
|
|
|
if ((ar = boost::dynamic_pointer_cast<AudioRegion>((*i)->region())) != 0) {
|
|
|
|
if (dir == -1) {
|
|
|
|
yn = ar->fade_out_active ();
|
|
|
|
} else {
|
|
|
|
yn = ar->fade_in_active ();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i == rs.end()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX should this undo-able? */
|
|
|
|
|
|
|
|
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
|
|
|
|
if ((ar = boost::dynamic_pointer_cast<AudioRegion>((*i)->region())) == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (dir == 1 || dir == 0) {
|
|
|
|
ar->set_fade_in_active (!yn);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dir == -1 || dir == 0) {
|
|
|
|
ar->set_fade_out_active (!yn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Update region fade visibility after its configuration has been changed */
|
|
|
|
void
|
|
|
|
Editor::update_region_fade_visibility ()
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
bool _fade_visibility = _session->config.get_show_region_fades ();
|
2008-10-09 17:55:05 -04:00
|
|
|
|
|
|
|
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
2009-07-09 13:58:13 -04:00
|
|
|
AudioTimeAxisView* v = dynamic_cast<AudioTimeAxisView*>(*i);
|
2008-10-09 17:55:05 -04:00
|
|
|
if (v) {
|
|
|
|
if (_fade_visibility) {
|
|
|
|
v->audio_view()->show_all_fades ();
|
|
|
|
} else {
|
|
|
|
v->audio_view()->hide_all_fades ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-04-22 14:01:10 -04:00
|
|
|
|
|
|
|
/** Update crossfade visibility after its configuration has been changed */
|
|
|
|
void
|
|
|
|
Editor::update_xfade_visibility ()
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
_xfade_visibility = _session->config.get_xfades_visible ();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-04-22 14:01:10 -04:00
|
|
|
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
2009-07-09 13:58:13 -04:00
|
|
|
AudioTimeAxisView* v = dynamic_cast<AudioTimeAxisView*>(*i);
|
2007-04-22 14:01:10 -04:00
|
|
|
if (v) {
|
|
|
|
if (_xfade_visibility) {
|
|
|
|
v->show_all_xfades ();
|
|
|
|
} else {
|
|
|
|
v->hide_all_xfades ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-11-12 17:23:01 -05:00
|
|
|
|
|
|
|
void
|
|
|
|
Editor::set_edit_point ()
|
|
|
|
{
|
|
|
|
nframes64_t where;
|
|
|
|
bool ignored;
|
|
|
|
|
|
|
|
if (!mouse_frame (where, ignored)) {
|
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
snap_to (where);
|
|
|
|
|
|
|
|
if (selection->markers.empty()) {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
mouse_add_new_marker (where);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
bool ignored;
|
|
|
|
|
|
|
|
Location* loc = find_location_from_marker (selection->markers.front(), ignored);
|
|
|
|
|
|
|
|
if (loc) {
|
|
|
|
loc->move_to (where);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::set_playhead_cursor ()
|
|
|
|
{
|
|
|
|
if (entered_marker) {
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_locate (entered_marker->position(), _session->transport_rolling());
|
2007-11-12 17:23:01 -05:00
|
|
|
} else {
|
|
|
|
nframes64_t where;
|
|
|
|
bool ignored;
|
|
|
|
|
|
|
|
if (!mouse_frame (where, ignored)) {
|
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
snap_to (where);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (_session) {
|
|
|
|
_session->request_locate (where, _session->transport_rolling());
|
2007-11-12 17:23:01 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::split ()
|
|
|
|
{
|
2010-06-28 11:01:14 -04:00
|
|
|
if (((mouse_mode == MouseRange) ||
|
|
|
|
(mouse_mode != MouseObject && _join_object_range_state == JOIN_OBJECT_RANGE_RANGE)) &&
|
|
|
|
!selection->time.empty()) {
|
|
|
|
separate_regions_between (selection->time);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
|
|
|
|
2009-06-25 16:58:32 -04:00
|
|
|
get_regions_for_action (rs, true);
|
2007-11-12 17:23:01 -05:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
nframes64_t where = get_preferred_edit_position();
|
2007-11-12 17:23:01 -05:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
if (rs.empty()) {
|
|
|
|
return;
|
2007-11-12 17:23:01 -05:00
|
|
|
}
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
split_regions_at (where, rs);
|
2007-11-12 17:23:01 -05:00
|
|
|
}
|
2008-01-07 16:12:29 -05:00
|
|
|
|
|
|
|
void
|
2008-01-10 16:20:59 -05:00
|
|
|
Editor::ensure_entered_track_selected (bool op_really_wants_one_track_if_none_are_selected)
|
2008-01-07 16:12:29 -05:00
|
|
|
{
|
2008-01-10 16:20:59 -05:00
|
|
|
if (entered_track && mouse_mode == MouseObject) {
|
|
|
|
if (!selection->tracks.empty()) {
|
|
|
|
if (!selection->selected (entered_track)) {
|
|
|
|
selection->add (entered_track);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* there is no selection, but this operation requires/prefers selected objects */
|
|
|
|
|
|
|
|
if (op_really_wants_one_track_if_none_are_selected) {
|
|
|
|
selection->set (entered_track);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct EditorOrderRouteSorter {
|
|
|
|
bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
|
|
|
|
/* use of ">" forces the correct sort order */
|
|
|
|
return a->order_key ("editor") < b->order_key ("editor");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::select_next_route()
|
|
|
|
{
|
|
|
|
if (selection->tracks.empty()) {
|
|
|
|
selection->set (track_views.front());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
TimeAxisView* current = selection->tracks.front();
|
2008-01-10 16:20:59 -05:00
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
RouteUI *rui;
|
2008-12-12 09:43:24 -05:00
|
|
|
do {
|
|
|
|
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
|
|
|
if (*i == current) {
|
|
|
|
++i;
|
|
|
|
if (i != track_views.end()) {
|
|
|
|
current = (*i);
|
|
|
|
} else {
|
|
|
|
current = (*(track_views.begin()));
|
|
|
|
//selection->set (*(track_views.begin()));
|
|
|
|
}
|
|
|
|
break;
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
}
|
2009-07-09 13:58:13 -04:00
|
|
|
rui = dynamic_cast<RouteUI *>(current);
|
|
|
|
} while ( current->hidden() || (rui != NULL && !rui->route()->active()));
|
2008-12-12 09:43:24 -05:00
|
|
|
|
|
|
|
selection->set(current);
|
|
|
|
|
|
|
|
ensure_track_visible(current);
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::select_prev_route()
|
|
|
|
{
|
|
|
|
if (selection->tracks.empty()) {
|
|
|
|
selection->set (track_views.front());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
TimeAxisView* current = selection->tracks.front();
|
2008-01-10 16:20:59 -05:00
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
RouteUI *rui;
|
2008-12-12 09:43:24 -05:00
|
|
|
do {
|
|
|
|
for (TrackViewList::reverse_iterator i = track_views.rbegin(); i != track_views.rend(); ++i) {
|
|
|
|
if (*i == current) {
|
|
|
|
++i;
|
|
|
|
if (i != track_views.rend()) {
|
|
|
|
current = (*i);
|
|
|
|
} else {
|
|
|
|
current = *(track_views.rbegin());
|
|
|
|
}
|
|
|
|
break;
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
}
|
2009-07-09 13:58:13 -04:00
|
|
|
rui = dynamic_cast<RouteUI *>(current);
|
|
|
|
} while ( current->hidden() || (rui != NULL && !rui->route()->active()));
|
2008-12-12 09:43:24 -05:00
|
|
|
|
|
|
|
selection->set (current);
|
|
|
|
|
|
|
|
ensure_track_visible(current);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-07-09 13:58:13 -04:00
|
|
|
Editor::ensure_track_visible(TimeAxisView *track)
|
2008-12-12 09:43:24 -05:00
|
|
|
{
|
|
|
|
if (track->hidden())
|
|
|
|
return;
|
|
|
|
|
2009-01-01 19:17:55 -05:00
|
|
|
double const current_view_min_y = vertical_adjustment.get_value();
|
|
|
|
double const current_view_max_y = vertical_adjustment.get_value() + vertical_adjustment.get_page_size() - canvas_timebars_vsize;
|
2008-12-12 09:43:24 -05:00
|
|
|
|
2009-01-01 19:17:55 -05:00
|
|
|
double const track_min_y = track->y_position ();
|
|
|
|
double const track_max_y = track->y_position () + track->effective_height ();
|
2008-12-12 09:43:24 -05:00
|
|
|
|
|
|
|
if (track_min_y >= current_view_min_y &&
|
|
|
|
track_max_y <= current_view_max_y) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
double new_value;
|
|
|
|
|
|
|
|
if (track_min_y < current_view_min_y) {
|
|
|
|
// Track is above the current view
|
|
|
|
new_value = track_min_y;
|
|
|
|
} else {
|
|
|
|
// Track is below the current view
|
2009-01-01 19:17:55 -05:00
|
|
|
new_value = track->y_position () + track->effective_height() + canvas_timebars_vsize - vertical_adjustment.get_page_size();
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
2008-12-12 09:43:24 -05:00
|
|
|
|
|
|
|
vertical_adjustment.set_value(new_value);
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::set_loop_from_selection (bool play)
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (_session == 0 || selection->time.empty()) {
|
2008-01-10 16:20:59 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t start = selection->time[clicked_selection].start;
|
|
|
|
nframes64_t end = selection->time[clicked_selection].end;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
set_loop_range (start, end, _("set loop range from selection"));
|
|
|
|
|
|
|
|
if (play) {
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_play_loop (true);
|
|
|
|
_session->request_locate (start, true);
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::set_loop_from_edit_range (bool play)
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (_session == 0) {
|
2008-01-10 16:20:59 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nframes64_t start;
|
|
|
|
nframes64_t end;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (!get_edit_op_range (start, end)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
set_loop_range (start, end, _("set loop range from edit range"));
|
|
|
|
|
|
|
|
if (play) {
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_play_loop (true);
|
|
|
|
_session->request_locate (start, true);
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::set_loop_from_region (bool play)
|
|
|
|
{
|
|
|
|
nframes64_t start = max_frames;
|
|
|
|
nframes64_t end = 0;
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-01-10 16:20:59 -05:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
|
|
|
if (rs.empty()) {
|
2008-01-10 16:20:59 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
|
2008-01-10 16:20:59 -05:00
|
|
|
if ((*i)->region()->position() < start) {
|
|
|
|
start = (*i)->region()->position();
|
|
|
|
}
|
|
|
|
if ((*i)->region()->last_frame() + 1 > end) {
|
|
|
|
end = (*i)->region()->last_frame() + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
set_loop_range (start, end, _("set loop range from region"));
|
|
|
|
|
|
|
|
if (play) {
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_play_loop (true);
|
|
|
|
_session->request_locate (start, true);
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::set_punch_from_selection ()
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (_session == 0 || selection->time.empty()) {
|
2008-01-10 16:20:59 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t start = selection->time[clicked_selection].start;
|
|
|
|
nframes64_t end = selection->time[clicked_selection].end;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
set_punch_range (start, end, _("set punch range from selection"));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::set_punch_from_edit_range ()
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (_session == 0) {
|
2008-01-10 16:20:59 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nframes64_t start;
|
|
|
|
nframes64_t end;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (!get_edit_op_range (start, end)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
set_punch_range (start, end, _("set punch range from edit range"));
|
|
|
|
}
|
|
|
|
|
2008-01-10 17:22:29 -05:00
|
|
|
void
|
|
|
|
Editor::set_punch_from_region ()
|
|
|
|
{
|
|
|
|
nframes64_t start = max_frames;
|
|
|
|
nframes64_t end = 0;
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-01-10 17:22:29 -05:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
|
|
|
if (rs.empty()) {
|
2008-01-10 17:22:29 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
|
2008-01-10 17:22:29 -05:00
|
|
|
if ((*i)->region()->position() < start) {
|
|
|
|
start = (*i)->region()->position();
|
|
|
|
}
|
|
|
|
if ((*i)->region()->last_frame() + 1 > end) {
|
|
|
|
end = (*i)->region()->last_frame() + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
set_punch_range (start, end, _("set punch range from region"));
|
|
|
|
}
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
void
|
|
|
|
Editor::pitch_shift_regions ()
|
|
|
|
{
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
if (rs.empty()) {
|
2008-01-10 16:20:59 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
pitch_shift (rs, 1.2);
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-01 22:57:35 -05:00
|
|
|
void
|
|
|
|
Editor::use_region_as_bar ()
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) {
|
2008-02-01 22:57:35 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-02-01 22:57:35 -05:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
|
|
|
if (rs.empty()) {
|
2008-02-01 22:57:35 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
RegionView* rv = rs.front();
|
2008-02-01 22:57:35 -05:00
|
|
|
|
|
|
|
define_one_bar (rv->region()->position(), rv->region()->last_frame() + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::use_range_as_bar ()
|
|
|
|
{
|
|
|
|
nframes64_t start, end;
|
|
|
|
if (get_edit_op_range (start, end)) {
|
|
|
|
define_one_bar (start, end);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::define_one_bar (nframes64_t start, nframes64_t end)
|
|
|
|
{
|
|
|
|
nframes64_t length = end - start;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
const Meter& m (_session->tempo_map().meter_at (start));
|
2008-02-01 22:57:35 -05:00
|
|
|
|
2008-02-02 12:22:04 -05:00
|
|
|
/* length = 1 bar */
|
2008-02-01 22:57:35 -05:00
|
|
|
|
|
|
|
/* now we want frames per beat.
|
|
|
|
we have frames per bar, and beats per bar, so ...
|
|
|
|
*/
|
|
|
|
|
2008-02-02 12:22:04 -05:00
|
|
|
double frames_per_beat = length / m.beats_per_bar();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-01 22:57:35 -05:00
|
|
|
/* beats per minute = */
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
double beats_per_minute = (_session->frame_rate() * 60.0) / frames_per_beat;
|
2008-02-01 22:57:35 -05:00
|
|
|
|
2008-02-02 12:22:04 -05:00
|
|
|
/* now decide whether to:
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
(a) set global tempo
|
2008-02-02 12:22:04 -05:00
|
|
|
(b) add a new tempo marker
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
const TempoSection& t (_session->tempo_map().tempo_section_at (start));
|
2008-02-01 22:57:35 -05:00
|
|
|
|
2008-02-02 12:22:04 -05:00
|
|
|
bool do_global = false;
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if ((_session->tempo_map().n_tempos() == 1) && (_session->tempo_map().n_meters() == 1)) {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-02 12:22:04 -05:00
|
|
|
/* only 1 tempo & 1 meter: ask if the user wants to set the tempo
|
|
|
|
at the start, or create a new marker
|
|
|
|
*/
|
|
|
|
|
|
|
|
vector<string> options;
|
|
|
|
options.push_back (_("Cancel"));
|
2008-02-16 17:43:18 -05:00
|
|
|
options.push_back (_("Add new marker"));
|
|
|
|
options.push_back (_("Set global tempo"));
|
2009-12-22 20:26:33 -05:00
|
|
|
|
|
|
|
Choice c (
|
|
|
|
_("Define one bar"),
|
|
|
|
_("Do you want to set the global tempo or add a new tempo marker?"),
|
|
|
|
options
|
|
|
|
);
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
c.set_default_response (2);
|
2008-02-02 12:22:04 -05:00
|
|
|
|
|
|
|
switch (c.run()) {
|
|
|
|
case 0:
|
2008-02-16 17:43:18 -05:00
|
|
|
return;
|
|
|
|
|
|
|
|
case 2:
|
2008-02-02 12:22:04 -05:00
|
|
|
do_global = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
do_global = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
/* more than 1 tempo and/or meter section already, go ahead do the "usual":
|
|
|
|
if the marker is at the region starter, change it, otherwise add
|
2009-10-14 12:10:01 -04:00
|
|
|
a new tempo marker
|
2008-02-02 12:22:04 -05:00
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
2008-02-01 22:57:35 -05:00
|
|
|
begin_reversible_command (_("set tempo from region"));
|
2009-12-17 13:24:23 -05:00
|
|
|
XMLNode& before (_session->tempo_map().get_state());
|
2008-02-01 22:57:35 -05:00
|
|
|
|
2008-02-02 12:22:04 -05:00
|
|
|
if (do_global) {
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->tempo_map().change_initial_tempo (beats_per_minute, t.note_type());
|
2008-02-02 12:22:04 -05:00
|
|
|
} else if (t.frame() == start) {
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->tempo_map().change_existing_tempo_at (start, beats_per_minute, t.note_type());
|
2008-02-01 22:57:35 -05:00
|
|
|
} else {
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->tempo_map().add_tempo (Tempo (beats_per_minute, t.note_type()), start);
|
2008-02-01 22:57:35 -05:00
|
|
|
}
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
XMLNode& after (_session->tempo_map().get_state());
|
2008-02-01 22:57:35 -05:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->add_command (new MementoCommand<TempoMap>(_session->tempo_map(), &before, &after));
|
2008-02-01 22:57:35 -05:00
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::split_region_at_transients ()
|
|
|
|
{
|
2008-02-02 12:22:04 -05:00
|
|
|
AnalysisFeatureList positions;
|
2008-02-01 22:57:35 -05:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) {
|
2008-02-01 22:57:35 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
RegionSelection rs;
|
2008-02-01 22:57:35 -05:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
get_regions_for_action (rs);
|
|
|
|
|
|
|
|
if (rs.empty()) {
|
2008-02-01 22:57:35 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->begin_reversible_command (_("split regions"));
|
2008-02-01 22:57:35 -05:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ) {
|
2008-02-01 22:57:35 -05:00
|
|
|
|
|
|
|
RegionSelection::iterator tmp;
|
|
|
|
|
|
|
|
tmp = i;
|
|
|
|
++tmp;
|
|
|
|
|
|
|
|
boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> ((*i)->region());
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-01 22:57:35 -05:00
|
|
|
if (ar && (ar->get_transients (positions) == 0)) {
|
2008-02-16 17:43:18 -05:00
|
|
|
split_region_at_points ((*i)->region(), positions, true);
|
2008-02-01 22:57:35 -05:00
|
|
|
positions.clear ();
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-01 22:57:35 -05:00
|
|
|
i = tmp;
|
|
|
|
}
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->commit_reversible_command ();
|
2008-02-01 22:57:35 -05:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-02-16 17:43:18 -05:00
|
|
|
Editor::split_region_at_points (boost::shared_ptr<Region> r, AnalysisFeatureList& positions, bool can_ferret)
|
2008-02-01 22:57:35 -05:00
|
|
|
{
|
2008-02-16 17:43:18 -05:00
|
|
|
bool use_rhythmic_rodent = false;
|
|
|
|
|
|
|
|
boost::shared_ptr<Playlist> pl = r->playlist();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-01 22:57:35 -05:00
|
|
|
if (!pl) {
|
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-01 22:57:35 -05:00
|
|
|
if (positions.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
|
|
|
|
if (positions.size() > 20) {
|
|
|
|
Glib::ustring msgstr = string_compose (_("You are about to split\n%1\ninto %2 pieces.\nThis could take a long time."), r->name(), positions.size() + 1);
|
|
|
|
MessageDialog msg (msgstr,
|
|
|
|
false,
|
|
|
|
Gtk::MESSAGE_INFO,
|
|
|
|
Gtk::BUTTONS_OK_CANCEL);
|
|
|
|
|
|
|
|
if (can_ferret) {
|
|
|
|
msg.add_button (_("Call for the Ferret!"), RESPONSE_APPLY);
|
|
|
|
msg.set_secondary_text (_("Press OK to continue with this split operation\nor ask the Ferret dialog to tune the analysis"));
|
|
|
|
} else {
|
|
|
|
msg.set_secondary_text (_("Press OK to continue with this split operation"));
|
|
|
|
}
|
|
|
|
|
|
|
|
msg.set_title (_("Excessive split?"));
|
|
|
|
msg.present ();
|
|
|
|
|
|
|
|
int response = msg.run();
|
|
|
|
msg.hide ();
|
2010-07-06 07:33:27 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
switch (response) {
|
|
|
|
case RESPONSE_OK:
|
|
|
|
break;
|
|
|
|
case RESPONSE_APPLY:
|
|
|
|
use_rhythmic_rodent = true;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
if (use_rhythmic_rodent) {
|
|
|
|
show_rhythm_ferret ();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
AnalysisFeatureList::const_iterator x;
|
|
|
|
|
2010-03-02 13:05:26 -05:00
|
|
|
pl->clear_history ();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-01 22:57:35 -05:00
|
|
|
x = positions.begin();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-01 22:57:35 -05:00
|
|
|
if (x == positions.end()) {
|
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-01 22:57:35 -05:00
|
|
|
pl->freeze ();
|
2008-02-16 17:43:18 -05:00
|
|
|
pl->remove_region (r);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2010-07-06 07:33:27 -04:00
|
|
|
nframes64_t pos = 0;
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
while (x != positions.end()) {
|
2010-07-06 07:33:27 -04:00
|
|
|
|
|
|
|
/* deal with positons that are out of scope of present region bounds */
|
|
|
|
if (*x <= 0 || *x > r->length()){
|
|
|
|
++x;
|
|
|
|
continue;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
|
|
|
/* file start = original start + how far we from the initial position ?
|
2008-02-01 22:57:35 -05:00
|
|
|
*/
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2010-07-06 07:33:27 -04:00
|
|
|
nframes64_t file_start = r->start() + pos;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
2008-02-01 22:57:35 -05:00
|
|
|
/* length = next position - current position
|
|
|
|
*/
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-01 22:57:35 -05:00
|
|
|
nframes64_t len = (*x) - pos;
|
2010-07-06 07:33:27 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
/* XXX we do we really want to allow even single-sample regions?
|
|
|
|
shouldn't we have some kind of lower limit on region size?
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (len <= 0) {
|
|
|
|
break;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-01 22:57:35 -05:00
|
|
|
string new_name;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2010-03-30 19:40:28 -04:00
|
|
|
if (RegionFactory::region_name (new_name, r->name())) {
|
2008-02-16 17:43:18 -05:00
|
|
|
break;
|
2008-02-01 22:57:35 -05:00
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
/* do NOT announce new regions 1 by one, just wait till they are all done */
|
|
|
|
|
2010-02-18 08:59:49 -05:00
|
|
|
PropertyList plist;
|
|
|
|
|
|
|
|
plist.add (ARDOUR::Properties::start, file_start);
|
|
|
|
plist.add (ARDOUR::Properties::length, len);
|
|
|
|
plist.add (ARDOUR::Properties::name, new_name);
|
|
|
|
plist.add (ARDOUR::Properties::layer, 0);
|
|
|
|
|
|
|
|
boost::shared_ptr<Region> nr = RegionFactory::create (r->sources(), plist, false);
|
2010-07-06 07:33:27 -04:00
|
|
|
pl->add_region (nr, r->position() + pos);
|
2008-02-16 17:43:18 -05:00
|
|
|
|
2008-02-01 22:57:35 -05:00
|
|
|
pos += len;
|
|
|
|
++x;
|
2010-07-06 07:33:27 -04:00
|
|
|
}
|
2008-02-16 17:43:18 -05:00
|
|
|
|
2010-07-06 07:33:27 -04:00
|
|
|
string new_name;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
2010-07-06 07:33:27 -04:00
|
|
|
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);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2010-07-06 07:33:27 -04:00
|
|
|
boost::shared_ptr<Region> nr = RegionFactory::create (r->sources(), plist, false);
|
|
|
|
pl->add_region (nr, r->position() + pos);
|
2008-02-16 17:43:18 -05:00
|
|
|
|
2010-07-06 07:33:27 -04:00
|
|
|
|
|
|
|
pl->thaw ();
|
2010-02-18 08:59:49 -05:00
|
|
|
|
2010-07-06 07:33:27 -04:00
|
|
|
_session->add_command (new StatefulDiffCommand (pl));
|
|
|
|
}
|
2008-02-16 17:43:18 -05:00
|
|
|
|
2010-07-06 07:33:27 -04:00
|
|
|
void
|
|
|
|
Editor::place_transient()
|
|
|
|
{
|
|
|
|
if (!_session) {
|
|
|
|
return;
|
2009-10-14 12:10:01 -04:00
|
|
|
}
|
2008-02-16 17:43:18 -05:00
|
|
|
|
2010-07-06 07:33:27 -04:00
|
|
|
RegionSelection rs;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
2010-07-06 07:33:27 -04:00
|
|
|
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 ();
|
2008-02-01 22:57:35 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::tab_to_transient (bool forward)
|
|
|
|
{
|
2008-02-02 12:22:04 -05:00
|
|
|
AnalysisFeatureList positions;
|
2008-02-01 22:57:35 -05:00
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) {
|
2008-02-01 22:57:35 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
nframes64_t pos = _session->audible_frame ();
|
2008-02-01 22:57:35 -05:00
|
|
|
|
2008-02-02 12:22:04 -05:00
|
|
|
if (!selection->tracks.empty()) {
|
2008-02-01 22:57:35 -05:00
|
|
|
|
2008-02-02 12:22:04 -05:00
|
|
|
for (TrackSelection::iterator t = selection->tracks.begin(); t != selection->tracks.end(); ++t) {
|
|
|
|
|
2009-07-09 13:58:13 -04:00
|
|
|
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*t);
|
2008-02-02 12:22:04 -05:00
|
|
|
|
|
|
|
if (rtv) {
|
2010-04-21 16:42:22 -04:00
|
|
|
boost::shared_ptr<Track> tr = rtv->track();
|
|
|
|
if (tr) {
|
|
|
|
boost::shared_ptr<Playlist> pl = tr->playlist ();
|
2008-02-02 12:22:04 -05:00
|
|
|
if (pl) {
|
|
|
|
nframes64_t result = pl->find_next_transient (pos, forward ? 1 : -1);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-02 12:22:04 -05:00
|
|
|
if (result >= 0) {
|
|
|
|
positions.push_back (result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
|
|
|
RegionSelection rs;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
get_regions_for_action (rs);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
if (rs.empty()) {
|
2008-02-02 12:22:04 -05:00
|
|
|
return;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) {
|
2008-02-02 12:22:04 -05:00
|
|
|
(*r)->region()->get_transients (positions);
|
|
|
|
}
|
2008-02-01 22:57:35 -05:00
|
|
|
}
|
|
|
|
|
2009-12-17 13:24:23 -05:00
|
|
|
TransientDetector::cleanup_transients (positions, _session->frame_rate(), 3.0);
|
2008-02-01 22:57:35 -05:00
|
|
|
|
|
|
|
if (forward) {
|
2008-02-02 12:22:04 -05:00
|
|
|
AnalysisFeatureList::iterator x;
|
2008-02-01 22:57:35 -05:00
|
|
|
|
|
|
|
for (x = positions.begin(); x != positions.end(); ++x) {
|
|
|
|
if ((*x) > pos) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (x != positions.end ()) {
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_locate (*x);
|
2008-02-01 22:57:35 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
2008-02-02 12:22:04 -05:00
|
|
|
AnalysisFeatureList::reverse_iterator x;
|
2008-02-01 22:57:35 -05:00
|
|
|
|
|
|
|
for (x = positions.rbegin(); x != positions.rend(); ++x) {
|
|
|
|
if ((*x) < pos) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (x != positions.rend ()) {
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_locate (*x);
|
2008-02-01 22:57:35 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-07-06 07:33:27 -04:00
|
|
|
|
2008-02-19 17:10:27 -05:00
|
|
|
void
|
|
|
|
Editor::playhead_forward_to_grid ()
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) return;
|
2008-02-19 17:10:27 -05:00
|
|
|
nframes64_t pos = playhead_cursor->current_frame;
|
2008-09-10 11:03:30 -04:00
|
|
|
if (pos < max_frames - 1) {
|
|
|
|
pos += 2;
|
2008-02-19 17:10:27 -05:00
|
|
|
snap_to_internal (pos, 1, false);
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_locate (pos);
|
2008-02-19 17:10:27 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::playhead_backward_to_grid ()
|
|
|
|
{
|
2009-12-17 13:24:23 -05:00
|
|
|
if (!_session) return;
|
2008-02-19 17:10:27 -05:00
|
|
|
nframes64_t pos = playhead_cursor->current_frame;
|
2008-09-10 11:03:30 -04:00
|
|
|
if (pos > 2) {
|
|
|
|
pos -= 2;
|
2008-02-19 17:10:27 -05:00
|
|
|
snap_to_internal (pos, -1, false);
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->request_locate (pos);
|
2008-02-19 17:10:27 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-17 16:54:03 -04:00
|
|
|
void
|
2010-05-10 20:09:41 -04:00
|
|
|
Editor::set_track_height (Height h)
|
2008-03-17 16:54:03 -04:00
|
|
|
{
|
|
|
|
TrackSelection& ts (selection->tracks);
|
|
|
|
|
|
|
|
for (TrackSelection::iterator x = ts.begin(); x != ts.end(); ++x) {
|
|
|
|
(*x)->set_height (h);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::toggle_tracks_active ()
|
|
|
|
{
|
|
|
|
TrackSelection& ts (selection->tracks);
|
|
|
|
bool first = true;
|
|
|
|
bool target = false;
|
|
|
|
|
|
|
|
if (ts.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (TrackSelection::iterator x = ts.begin(); x != ts.end(); ++x) {
|
2009-07-09 13:58:13 -04:00
|
|
|
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*x);
|
2008-03-17 16:54:03 -04:00
|
|
|
|
|
|
|
if (rtv) {
|
|
|
|
if (first) {
|
|
|
|
target = !rtv->_route->active();
|
|
|
|
first = false;
|
|
|
|
}
|
|
|
|
rtv->_route->set_active (target);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::remove_tracks ()
|
|
|
|
{
|
|
|
|
TrackSelection& ts (selection->tracks);
|
|
|
|
|
|
|
|
if (ts.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
vector<string> choices;
|
|
|
|
string prompt;
|
|
|
|
int ntracks = 0;
|
|
|
|
int nbusses = 0;
|
|
|
|
const char* trackstr;
|
|
|
|
const char* busstr;
|
|
|
|
vector<boost::shared_ptr<Route> > routes;
|
2010-06-16 12:59:20 -04:00
|
|
|
bool special_bus = false;
|
2008-03-17 16:54:03 -04:00
|
|
|
|
|
|
|
for (TrackSelection::iterator x = ts.begin(); x != ts.end(); ++x) {
|
2009-07-09 13:58:13 -04:00
|
|
|
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*x);
|
2008-03-17 16:54:03 -04:00
|
|
|
if (rtv) {
|
|
|
|
if (rtv->is_track()) {
|
|
|
|
ntracks++;
|
|
|
|
} else {
|
|
|
|
nbusses++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
routes.push_back (rtv->_route);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2010-06-16 12:59:20 -04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2008-03-17 16:54:03 -04:00
|
|
|
if (ntracks + nbusses == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ntracks > 1) {
|
|
|
|
trackstr = _("tracks");
|
|
|
|
} else {
|
|
|
|
trackstr = _("track");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nbusses > 1) {
|
|
|
|
busstr = _("busses");
|
|
|
|
} else {
|
|
|
|
busstr = _("bus");
|
|
|
|
}
|
|
|
|
|
|
|
|
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!"),
|
|
|
|
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!"),
|
|
|
|
ntracks, trackstr);
|
|
|
|
}
|
|
|
|
} else if (nbusses) {
|
|
|
|
prompt = string_compose (_("Do you really want to remove %1 %2?"),
|
|
|
|
nbusses, busstr);
|
|
|
|
}
|
|
|
|
|
|
|
|
choices.push_back (_("No, do nothing."));
|
|
|
|
if (ntracks + nbusses > 1) {
|
|
|
|
choices.push_back (_("Yes, remove them."));
|
|
|
|
} else {
|
|
|
|
choices.push_back (_("Yes, remove it."));
|
|
|
|
}
|
|
|
|
|
2009-12-22 20:26:33 -05:00
|
|
|
string title;
|
|
|
|
if (ntracks) {
|
|
|
|
title = string_compose (_("Remove %1"), trackstr);
|
|
|
|
} else {
|
|
|
|
title = string_compose (_("Remove %1"), busstr);
|
|
|
|
}
|
|
|
|
|
|
|
|
Choice prompter (title, prompt, choices);
|
2008-03-17 16:54:03 -04:00
|
|
|
|
|
|
|
if (prompter.run () != 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (vector<boost::shared_ptr<Route> >::iterator x = routes.begin(); x != routes.end(); ++x) {
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->remove_route (*x);
|
2008-03-17 16:54:03 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-11 10:06:50 -04:00
|
|
|
void
|
|
|
|
Editor::do_insert_time ()
|
|
|
|
{
|
|
|
|
if (selection->tracks.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ArdourDialog d (*this, _("Insert Time"));
|
|
|
|
|
2009-06-08 18:59:27 -04:00
|
|
|
nframes64_t const pos = get_preferred_edit_position ();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2009-06-08 18:59:27 -04:00
|
|
|
d.get_vbox()->set_border_width (12);
|
|
|
|
d.get_vbox()->set_spacing (4);
|
2008-04-11 10:06:50 -04:00
|
|
|
|
2009-06-08 18:59:27 -04:00
|
|
|
Table table (2, 2);
|
|
|
|
table.set_spacings (4);
|
2008-04-11 10:06:50 -04:00
|
|
|
|
2009-06-08 18:59:27 -04:00
|
|
|
Label time_label (_("Time to insert:"));
|
|
|
|
time_label.set_alignment (1, 0.5);
|
|
|
|
table.attach (time_label, 0, 1, 0, 1, FILL | EXPAND);
|
2009-11-25 21:15:44 -05:00
|
|
|
AudioClock clock ("insertTimeClock", true, X_("InsertTimeClock"), true, false, true, true);
|
2009-06-08 18:59:27 -04:00
|
|
|
clock.set (0);
|
2009-12-17 13:24:23 -05:00
|
|
|
clock.set_session (_session);
|
2009-10-14 12:10:01 -04:00
|
|
|
clock.set_bbt_reference (pos);
|
2009-06-08 18:59:27 -04:00
|
|
|
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);
|
2009-06-08 19:24:14 -04:00
|
|
|
CheckButton move_tempos (_("Move tempo and meter changes"));
|
|
|
|
d.get_vbox()->pack_start (move_tempos);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-04-11 10:06:50 -04:00
|
|
|
d.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
|
2009-06-08 18:59:27 -04:00
|
|
|
d.add_button (_("Insert time"), Gtk::RESPONSE_OK);
|
|
|
|
d.show_all ();
|
2008-04-11 10:06:50 -04:00
|
|
|
|
|
|
|
int response = d.run ();
|
|
|
|
|
|
|
|
if (response != RESPONSE_OK) {
|
|
|
|
return;
|
|
|
|
}
|
2009-06-08 18:59:27 -04:00
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t distance = clock.current_duration (pos);
|
2008-04-11 10:06:50 -04:00
|
|
|
|
|
|
|
if (distance == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-05-07 21:20:33 -04:00
|
|
|
/* only setting this to keep GCC quiet */
|
|
|
|
InsertTimeOption opt = LeaveIntersected;
|
2008-04-11 10:06:50 -04:00
|
|
|
|
2009-06-08 18:59:27 -04:00
|
|
|
switch (intersected_combo.get_active_row_number ()) {
|
|
|
|
case 0:
|
2008-04-11 10:06:50 -04:00
|
|
|
opt = LeaveIntersected;
|
2009-06-08 18:59:27 -04:00
|
|
|
break;
|
|
|
|
case 1:
|
2008-04-11 10:06:50 -04:00
|
|
|
opt = MoveIntersected;
|
2009-06-08 18:59:27 -04:00
|
|
|
break;
|
|
|
|
case 2:
|
2008-04-11 10:06:50 -04:00
|
|
|
opt = SplitIntersected;
|
2009-06-08 18:59:27 -04:00
|
|
|
break;
|
2008-04-11 10:06:50 -04:00
|
|
|
}
|
|
|
|
|
2009-06-08 19:24:14 -04:00
|
|
|
insert_time (pos, distance, opt, move_glued.get_active(), move_markers.get_active(), move_tempos.get_active());
|
2008-04-11 10:06:50 -04:00
|
|
|
}
|
2008-09-10 11:03:30 -04:00
|
|
|
|
2008-04-11 10:06:50 -04:00
|
|
|
void
|
2009-10-14 12:10:01 -04:00
|
|
|
Editor::insert_time (nframes64_t pos, nframes64_t frames, InsertTimeOption opt,
|
2009-06-08 19:24:14 -04:00
|
|
|
bool ignore_music_glue, bool markers_too, bool tempo_too)
|
2008-04-11 10:06:50 -04:00
|
|
|
{
|
|
|
|
bool commit = false;
|
|
|
|
|
|
|
|
if (Config->get_edit_mode() == Lock) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
begin_reversible_command (_("insert time"));
|
|
|
|
|
|
|
|
for (TrackSelection::iterator x = selection->tracks.begin(); x != selection->tracks.end(); ++x) {
|
2008-12-12 09:43:24 -05:00
|
|
|
/* regions */
|
2008-04-11 10:06:50 -04:00
|
|
|
boost::shared_ptr<Playlist> pl = (*x)->playlist();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-12-12 09:43:24 -05:00
|
|
|
if (pl) {
|
2008-04-11 10:06:50 -04:00
|
|
|
|
2010-03-04 08:15:04 -05:00
|
|
|
pl->clear_history ();
|
|
|
|
pl->clear_owned_history ();
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-12-12 09:43:24 -05:00
|
|
|
if (opt == SplitIntersected) {
|
|
|
|
pl->split (pos);
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-12-12 09:43:24 -05:00
|
|
|
pl->shift (pos, frames, (opt == MoveIntersected), ignore_music_glue);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2010-03-04 08:15:04 -05:00
|
|
|
vector<StatefulDiffCommand*> cmds;
|
|
|
|
|
|
|
|
pl->rdiff (cmds);
|
|
|
|
|
|
|
|
for (vector<StatefulDiffCommand*>::iterator c = cmds.begin(); c != cmds.end(); ++c) {
|
|
|
|
_session->add_command (*c);
|
|
|
|
}
|
|
|
|
|
|
|
|
_session->add_command (new StatefulDiffCommand (pl));
|
2008-12-12 09:43:24 -05:00
|
|
|
commit = true;
|
|
|
|
}
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-12-12 09:43:24 -05:00
|
|
|
/* automation */
|
2009-07-09 13:58:13 -04:00
|
|
|
RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (*x);
|
2008-12-12 09:43:24 -05:00
|
|
|
if (rtav) {
|
|
|
|
rtav->route ()->shift (pos, frames);
|
|
|
|
commit = true;
|
2008-04-11 10:06:50 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-12 09:43:24 -05:00
|
|
|
/* markers */
|
2008-09-10 11:03:30 -04:00
|
|
|
if (markers_too) {
|
|
|
|
bool moved = false;
|
2009-12-17 13:24:23 -05:00
|
|
|
XMLNode& before (_session->locations()->get_state());
|
|
|
|
Locations::LocationList copy (_session->locations()->list());
|
2008-09-10 11:03:30 -04:00
|
|
|
|
|
|
|
for (Locations::LocationList::iterator i = copy.begin(); i != copy.end(); ++i) {
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
moved = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (moved) {
|
2009-12-17 13:24:23 -05:00
|
|
|
XMLNode& after (_session->locations()->get_state());
|
|
|
|
_session->add_command (new MementoCommand<Locations>(*_session->locations(), &before, &after));
|
2008-09-10 11:03:30 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-08 19:24:14 -04:00
|
|
|
if (tempo_too) {
|
2009-12-17 13:24:23 -05:00
|
|
|
_session->tempo_map().insert_time (pos, frames);
|
2009-06-08 19:24:14 -04:00
|
|
|
}
|
|
|
|
|
2008-04-11 10:06:50 -04:00
|
|
|
if (commit) {
|
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
}
|
2008-09-10 11:03:30 -04:00
|
|
|
|
|
|
|
void
|
2009-06-21 21:01:43 -04:00
|
|
|
Editor::fit_selected_tracks ()
|
2008-09-10 11:03:30 -04:00
|
|
|
{
|
2009-06-21 21:01:43 -04:00
|
|
|
fit_tracks (selection->tracks);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-12-13 14:09:52 -05:00
|
|
|
Editor::fit_tracks (TrackViewList & tracks)
|
2009-06-21 21:01:43 -04:00
|
|
|
{
|
|
|
|
if (tracks.empty()) {
|
2008-09-10 11:03:30 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t child_heights = 0;
|
|
|
|
|
2009-06-21 21:01:43 -04:00
|
|
|
for (TrackSelection::iterator t = tracks.begin(); t != tracks.end(); ++t) {
|
2008-09-10 11:03:30 -04:00
|
|
|
|
|
|
|
if (!(*t)->marked_for_display()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2009-01-01 19:17:55 -05:00
|
|
|
child_heights += (*t)->effective_height() - (*t)->current_height();
|
2008-09-10 11:03:30 -04:00
|
|
|
}
|
|
|
|
|
2009-06-21 21:01:43 -04:00
|
|
|
uint32_t h = (uint32_t) floor ((_canvas_height - child_heights - canvas_timebars_vsize) / tracks.size());
|
2008-09-10 11:03:30 -04:00
|
|
|
double first_y_pos = DBL_MAX;
|
|
|
|
|
2010-05-10 20:09:41 -04:00
|
|
|
if (h < TimeAxisView::preset_height (HeightSmall)) {
|
2009-06-21 21:01:43 -04:00
|
|
|
MessageDialog msg (*this, _("There are too many tracks to fit in the current window"));
|
2008-10-14 10:20:29 -04:00
|
|
|
/* too small to be displayed */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
undo_visual_stack.push_back (current_visual_state());
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-10-14 10:20:29 -04:00
|
|
|
/* operate on all tracks, hide unselected ones that are in the middle of selected ones */
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-10-14 10:20:29 -04:00
|
|
|
bool prev_was_selected = false;
|
2009-06-21 21:01:43 -04:00
|
|
|
bool is_selected = tracks.contains (track_views.front());
|
2008-10-14 10:20:29 -04:00
|
|
|
bool next_is_selected;
|
|
|
|
|
|
|
|
for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
|
|
|
|
|
|
|
|
TrackViewList::iterator next;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-10-14 10:20:29 -04:00
|
|
|
next = t;
|
|
|
|
++next;
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-10-14 10:20:29 -04:00
|
|
|
if (next != track_views.end()) {
|
2009-06-21 21:01:43 -04:00
|
|
|
next_is_selected = tracks.contains (*next);
|
2008-10-14 10:20:29 -04:00
|
|
|
} else {
|
|
|
|
next_is_selected = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_selected) {
|
|
|
|
(*t)->set_height (h);
|
2009-01-01 19:17:55 -05:00
|
|
|
first_y_pos = std::min ((*t)->y_position (), first_y_pos);
|
2008-10-14 10:20:29 -04:00
|
|
|
} else {
|
|
|
|
if (prev_was_selected && next_is_selected) {
|
2010-05-09 21:37:35 -04:00
|
|
|
hide_track_in_display (*t);
|
2008-10-14 10:20:29 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
prev_was_selected = is_selected;
|
|
|
|
is_selected = next_is_selected;
|
2008-09-10 11:03:30 -04:00
|
|
|
}
|
2008-10-14 10:20:29 -04:00
|
|
|
|
2009-10-14 12:10:01 -04:00
|
|
|
/*
|
|
|
|
set the controls_layout height now, because waiting for its size
|
|
|
|
request signal handler will cause the vertical adjustment setting to fail
|
|
|
|
*/
|
2008-10-14 10:20:29 -04:00
|
|
|
|
2008-10-12 21:56:42 -04:00
|
|
|
controls_layout.property_height () = full_canvas_height - canvas_timebars_vsize;
|
2008-09-10 11:03:30 -04:00
|
|
|
vertical_adjustment.set_value (first_y_pos);
|
|
|
|
|
|
|
|
redo_visual_stack.push_back (current_visual_state());
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::save_visual_state (uint32_t n)
|
|
|
|
{
|
|
|
|
while (visual_states.size() <= n) {
|
|
|
|
visual_states.push_back (0);
|
|
|
|
}
|
|
|
|
|
2008-12-18 14:31:00 -05:00
|
|
|
delete visual_states[n];
|
2008-09-10 11:03:30 -04:00
|
|
|
|
|
|
|
visual_states[n] = current_visual_state (true);
|
|
|
|
gdk_beep ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::goto_visual_state (uint32_t n)
|
|
|
|
{
|
|
|
|
if (visual_states.size() <= n) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (visual_states[n] == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
use_visual_state (*visual_states[n]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::start_visual_state_op (uint32_t n)
|
|
|
|
{
|
|
|
|
if (visual_state_op_connection.empty()) {
|
2009-12-11 18:29:48 -05:00
|
|
|
visual_state_op_connection = Glib::signal_timeout().connect (sigc::bind (sigc::mem_fun (*this, &Editor::end_visual_state_op), n), 1000);
|
2008-09-10 11:03:30 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::cancel_visual_state_op (uint32_t n)
|
|
|
|
{
|
|
|
|
if (!visual_state_op_connection.empty()) {
|
|
|
|
visual_state_op_connection.disconnect();
|
|
|
|
goto_visual_state (n);
|
2009-10-01 16:52:07 -04:00
|
|
|
} else {
|
|
|
|
//we land here if called from the menu OR if end_visual_state_op has been called
|
|
|
|
//so check if we are already in visual state n
|
|
|
|
// XXX not yet checking it at all, but redoing does not hurt
|
|
|
|
goto_visual_state (n);
|
|
|
|
}
|
2008-09-10 11:03:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Editor::end_visual_state_op (uint32_t n)
|
|
|
|
{
|
|
|
|
visual_state_op_connection.disconnect();
|
|
|
|
save_visual_state (n);
|
2009-10-14 12:10:01 -04:00
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
PopUp* pup = new PopUp (WIN_POS_MOUSE, 1000, true);
|
|
|
|
char buf[32];
|
|
|
|
snprintf (buf, sizeof (buf), _("Saved view %u"), n+1);
|
|
|
|
pup->set_text (buf);
|
|
|
|
pup->touch();
|
|
|
|
|
|
|
|
return false; // do not call again
|
|
|
|
}
|
2008-10-09 17:55:05 -04:00
|
|
|
|