2005-09-25 14:42:24 -04:00
|
|
|
/*
|
|
|
|
Copyright (C) 2000-2001 Paul Davis
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
#include <cassert>
|
2005-09-25 14:42:24 -04:00
|
|
|
#include <cstdlib>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <cmath>
|
|
|
|
#include <set>
|
|
|
|
#include <string>
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
#include <pbd/error.h>
|
2005-09-25 16:33:00 -04:00
|
|
|
#include <gtkmm2ext/utils.h>
|
2006-08-09 21:22:45 -04:00
|
|
|
#include <pbd/memento_command.h>
|
2007-10-14 01:45:31 -04:00
|
|
|
#include <pbd/basename.h>
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
#include "ardour_ui.h"
|
|
|
|
#include "editor.h"
|
|
|
|
#include "time_axis_view.h"
|
|
|
|
#include "audio_time_axis.h"
|
2006-08-01 13:19:38 -04:00
|
|
|
#include "audio_region_view.h"
|
2007-03-18 02:07:08 -04:00
|
|
|
#include "midi_region_view.h"
|
2005-09-25 14:42:24 -04:00
|
|
|
#include "marker.h"
|
|
|
|
#include "streamview.h"
|
|
|
|
#include "region_gain_line.h"
|
|
|
|
#include "automation_time_axis.h"
|
2007-07-06 23:19:04 -04:00
|
|
|
#include "control_point.h"
|
2005-09-25 14:42:24 -04:00
|
|
|
#include "prompter.h"
|
|
|
|
#include "utils.h"
|
|
|
|
#include "selection.h"
|
|
|
|
#include "keyboard.h"
|
|
|
|
#include "editing.h"
|
|
|
|
#include "rgb_macros.h"
|
|
|
|
|
|
|
|
#include <ardour/types.h>
|
2007-04-12 19:20:37 -04:00
|
|
|
#include <ardour/profile.h>
|
2005-09-25 14:42:24 -04:00
|
|
|
#include <ardour/route.h>
|
|
|
|
#include <ardour/audio_track.h>
|
2006-06-14 21:34:54 -04:00
|
|
|
#include <ardour/audio_diskstream.h>
|
2007-10-14 01:45:31 -04:00
|
|
|
#include <ardour/midi_diskstream.h>
|
2005-09-25 14:42:24 -04:00
|
|
|
#include <ardour/playlist.h>
|
|
|
|
#include <ardour/audioplaylist.h>
|
|
|
|
#include <ardour/audioregion.h>
|
2006-07-23 08:03:19 -04:00
|
|
|
#include <ardour/midi_region.h>
|
2005-09-25 14:42:24 -04:00
|
|
|
#include <ardour/dB.h>
|
|
|
|
#include <ardour/utils.h>
|
|
|
|
#include <ardour/region_factory.h>
|
2007-10-14 01:45:31 -04:00
|
|
|
#include <ardour/source_factory.h>
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
#include <bitset>
|
|
|
|
|
|
|
|
#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 16:33:00 -04:00
|
|
|
using namespace sigc;
|
2005-09-25 14:42:24 -04:00
|
|
|
using namespace Gtk;
|
|
|
|
using namespace Editing;
|
|
|
|
|
2007-11-06 08:33:39 -05:00
|
|
|
const static double ZERO_GAIN_FRACTION = gain_to_slider_position(dB_to_coefficient(0.0));
|
|
|
|
|
2007-11-07 20:40:25 -05:00
|
|
|
bool
|
|
|
|
Editor::mouse_frame (nframes64_t& where, bool& in_track_canvas) const
|
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
double wx, wy;
|
|
|
|
Gdk::ModifierType mask;
|
|
|
|
Glib::RefPtr<Gdk::Window> canvas_window = const_cast<Editor*>(this)->track_canvas.get_window();
|
|
|
|
Glib::RefPtr<const Gdk::Window> pointer_window;
|
|
|
|
|
|
|
|
pointer_window = canvas_window->get_pointer (x, y, mask);
|
|
|
|
|
|
|
|
if (pointer_window == track_canvas.get_bin_window()) {
|
|
|
|
|
|
|
|
track_canvas.window_to_world (x, y, wx, wy);
|
|
|
|
in_track_canvas = true;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
in_track_canvas = false;
|
|
|
|
|
|
|
|
if (pointer_window == time_canvas.get_bin_window()) {
|
|
|
|
time_canvas.window_to_world (x, y, wx, wy);
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
wx += horizontal_adjustment.get_value();
|
|
|
|
wy += vertical_adjustment.get_value();
|
|
|
|
|
|
|
|
GdkEvent event;
|
|
|
|
event.type = GDK_BUTTON_RELEASE;
|
|
|
|
event.button.x = wx;
|
|
|
|
event.button.y = wy;
|
|
|
|
|
|
|
|
where = event_frame (&event, 0, 0);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
nframes64_t
|
|
|
|
Editor::event_frame (GdkEvent* event, double* pcx, double* pcy) const
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
double cx, cy;
|
|
|
|
|
|
|
|
if (pcx == 0) {
|
|
|
|
pcx = &cx;
|
|
|
|
}
|
|
|
|
if (pcy == 0) {
|
|
|
|
pcy = &cy;
|
|
|
|
}
|
|
|
|
|
|
|
|
*pcx = 0;
|
|
|
|
*pcy = 0;
|
|
|
|
|
|
|
|
switch (event->type) {
|
|
|
|
case GDK_BUTTON_RELEASE:
|
|
|
|
case GDK_BUTTON_PRESS:
|
|
|
|
case GDK_2BUTTON_PRESS:
|
|
|
|
case GDK_3BUTTON_PRESS:
|
2005-11-22 00:10:12 -05:00
|
|
|
track_canvas.w2c(event->button.x, event->button.y, *pcx, *pcy);
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
case GDK_MOTION_NOTIFY:
|
2005-11-22 00:10:12 -05:00
|
|
|
track_canvas.w2c(event->motion.x, event->motion.y, *pcx, *pcy);
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
case GDK_ENTER_NOTIFY:
|
|
|
|
case GDK_LEAVE_NOTIFY:
|
2005-11-22 00:10:12 -05:00
|
|
|
track_canvas.w2c(event->crossing.x, event->crossing.y, *pcx, *pcy);
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
2006-01-28 08:33:54 -05:00
|
|
|
case GDK_KEY_PRESS:
|
|
|
|
case GDK_KEY_RELEASE:
|
|
|
|
// track_canvas.w2c(event->key.x, event->key.y, *pcx, *pcy);
|
|
|
|
break;
|
2005-09-25 14:42:24 -04:00
|
|
|
default:
|
2005-10-06 15:10:57 -04:00
|
|
|
warning << string_compose (_("Editor::event_frame() used on unhandled event type %1"), event->type) << endmsg;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* note that pixel_to_frame() never returns less than zero, so even if the pixel
|
|
|
|
position is negative (as can be the case with motion events in particular),
|
|
|
|
the frame location is always positive.
|
|
|
|
*/
|
2006-01-02 15:27:51 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
return pixel_to_frame (*pcx);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::mouse_mode_toggled (MouseMode m)
|
|
|
|
{
|
|
|
|
if (ignore_mouse_mode_toggle) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (m) {
|
|
|
|
case MouseRange:
|
|
|
|
if (mouse_select_button.get_active()) {
|
|
|
|
set_mouse_mode (m);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseObject:
|
|
|
|
if (mouse_move_button.get_active()) {
|
|
|
|
set_mouse_mode (m);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseGain:
|
|
|
|
if (mouse_gain_button.get_active()) {
|
|
|
|
set_mouse_mode (m);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseZoom:
|
|
|
|
if (mouse_zoom_button.get_active()) {
|
|
|
|
set_mouse_mode (m);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseTimeFX:
|
|
|
|
if (mouse_timefx_button.get_active()) {
|
|
|
|
set_mouse_mode (m);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseAudition:
|
|
|
|
if (mouse_audition_button.get_active()) {
|
|
|
|
set_mouse_mode (m);
|
|
|
|
}
|
|
|
|
break;
|
2007-07-14 21:56:11 -04:00
|
|
|
|
|
|
|
case MouseNote:
|
|
|
|
if (mouse_note_button.get_active()) {
|
|
|
|
set_mouse_mode (m);
|
|
|
|
}
|
|
|
|
break;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
Gdk::Cursor*
|
|
|
|
Editor::which_grabber_cursor ()
|
|
|
|
{
|
|
|
|
switch (_edit_point) {
|
|
|
|
case EditAtMouse:
|
|
|
|
return grabber_edit_point_cursor;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return grabber_cursor;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::set_canvas_cursor ()
|
|
|
|
{
|
|
|
|
switch (mouse_mode) {
|
|
|
|
case MouseRange:
|
|
|
|
current_canvas_cursor = selector_cursor;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseObject:
|
|
|
|
current_canvas_cursor = which_grabber_cursor();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseGain:
|
|
|
|
current_canvas_cursor = cross_hair_cursor;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseZoom:
|
|
|
|
current_canvas_cursor = zoom_cursor;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseTimeFX:
|
|
|
|
current_canvas_cursor = time_fx_cursor; // just use playhead
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseAudition:
|
|
|
|
current_canvas_cursor = speaker_cursor;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseNote:
|
|
|
|
set_midi_edit_cursor (current_midi_edit_mode());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_drawable()) {
|
|
|
|
track_canvas.get_window()->set_cursor(*current_canvas_cursor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
|
|
|
Editor::set_mouse_mode (MouseMode m, bool force)
|
|
|
|
{
|
|
|
|
if (drag_info.item) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-05-24 18:43:15 -04:00
|
|
|
if (!force && m == mouse_mode) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mouse_mode = m;
|
|
|
|
|
|
|
|
instant_save ();
|
|
|
|
|
|
|
|
if (mouse_mode != MouseRange) {
|
|
|
|
|
|
|
|
/* in all modes except range, hide the range selection,
|
|
|
|
show the object (region) selection.
|
|
|
|
*/
|
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
|
2005-09-25 14:42:24 -04:00
|
|
|
(*i)->set_should_show_selection (true);
|
|
|
|
}
|
|
|
|
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
|
|
|
(*i)->hide_selection ();
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
2006-02-15 07:15:29 -05:00
|
|
|
/*
|
|
|
|
in range mode,show the range selection.
|
2005-09-25 14:42:24 -04:00
|
|
|
*/
|
|
|
|
|
|
|
|
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
|
2006-06-21 14:14:45 -04:00
|
|
|
if ((*i)->get_selected()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
(*i)->show_selection (selection->time);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-08-08 15:13:36 -04:00
|
|
|
/* XXX the hack of unsetting all other buttons should go
|
2005-09-25 14:42:24 -04:00
|
|
|
away once GTK2 allows us to use regular radio buttons drawn like
|
|
|
|
normal buttons, rather than my silly GroupedButton hack.
|
|
|
|
*/
|
|
|
|
|
|
|
|
ignore_mouse_mode_toggle = true;
|
|
|
|
|
|
|
|
switch (mouse_mode) {
|
|
|
|
case MouseRange:
|
|
|
|
mouse_select_button.set_active (true);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseObject:
|
|
|
|
mouse_move_button.set_active (true);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseGain:
|
|
|
|
mouse_gain_button.set_active (true);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseZoom:
|
|
|
|
mouse_zoom_button.set_active (true);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseTimeFX:
|
|
|
|
mouse_timefx_button.set_active (true);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseAudition:
|
|
|
|
mouse_audition_button.set_active (true);
|
|
|
|
break;
|
2007-07-14 21:56:11 -04:00
|
|
|
|
|
|
|
case MouseNote:
|
|
|
|
mouse_note_button.set_active (true);
|
2007-08-10 16:55:27 -04:00
|
|
|
set_midi_edit_cursor (current_midi_edit_mode());
|
2007-07-14 21:56:11 -04:00
|
|
|
break;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2007-08-08 15:13:36 -04:00
|
|
|
if (mouse_mode == MouseNote)
|
|
|
|
midi_toolbar_frame.show();
|
|
|
|
else
|
|
|
|
midi_toolbar_frame.hide();
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
ignore_mouse_mode_toggle = false;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
set_canvas_cursor ();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::step_mouse_mode (bool next)
|
|
|
|
{
|
|
|
|
switch (current_mouse_mode()) {
|
|
|
|
case MouseObject:
|
|
|
|
if (next) set_mouse_mode (MouseRange);
|
|
|
|
else set_mouse_mode (MouseTimeFX);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseRange:
|
|
|
|
if (next) set_mouse_mode (MouseZoom);
|
|
|
|
else set_mouse_mode (MouseObject);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseZoom:
|
|
|
|
if (next) set_mouse_mode (MouseGain);
|
|
|
|
else set_mouse_mode (MouseRange);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseGain:
|
|
|
|
if (next) set_mouse_mode (MouseTimeFX);
|
|
|
|
else set_mouse_mode (MouseZoom);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseTimeFX:
|
|
|
|
if (next) set_mouse_mode (MouseAudition);
|
|
|
|
else set_mouse_mode (MouseGain);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseAudition:
|
|
|
|
if (next) set_mouse_mode (MouseObject);
|
|
|
|
else set_mouse_mode (MouseTimeFX);
|
|
|
|
break;
|
2007-07-14 21:56:11 -04:00
|
|
|
|
|
|
|
case MouseNote:
|
|
|
|
if (next) set_mouse_mode (MouseObject);
|
|
|
|
else set_mouse_mode (MouseAudition);
|
|
|
|
break;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-08-09 16:50:56 -04:00
|
|
|
void
|
|
|
|
Editor::midi_edit_mode_toggled (MidiEditMode m)
|
|
|
|
{
|
|
|
|
if (ignore_midi_edit_mode_toggle) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (m) {
|
2007-10-14 01:45:31 -04:00
|
|
|
case MidiEditPencil:
|
|
|
|
if (midi_tool_pencil_button.get_active())
|
2007-08-09 16:50:56 -04:00
|
|
|
set_midi_edit_mode (m);
|
|
|
|
break;
|
2007-10-14 01:45:31 -04:00
|
|
|
|
|
|
|
case MidiEditSelect:
|
|
|
|
if (midi_tool_select_button.get_active())
|
2007-08-09 16:50:56 -04:00
|
|
|
set_midi_edit_mode (m);
|
|
|
|
break;
|
2007-10-14 01:45:31 -04:00
|
|
|
|
2007-08-09 16:50:56 -04:00
|
|
|
case MidiEditErase:
|
2007-10-14 01:45:31 -04:00
|
|
|
if (midi_tool_erase_button.get_active())
|
2007-08-09 16:50:56 -04:00
|
|
|
set_midi_edit_mode (m);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2007-08-10 16:55:27 -04:00
|
|
|
|
|
|
|
set_midi_edit_cursor(m);
|
2007-08-09 16:50:56 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-08-08 15:13:36 -04:00
|
|
|
void
|
|
|
|
Editor::set_midi_edit_mode (MidiEditMode m, bool force)
|
|
|
|
{
|
|
|
|
if (drag_info.item) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!force && m == midi_edit_mode) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
midi_edit_mode = m;
|
|
|
|
|
|
|
|
instant_save ();
|
|
|
|
|
2007-08-09 16:50:56 -04:00
|
|
|
ignore_midi_edit_mode_toggle = true;
|
2007-08-08 15:13:36 -04:00
|
|
|
|
|
|
|
switch (midi_edit_mode) {
|
|
|
|
case MidiEditPencil:
|
|
|
|
midi_tool_pencil_button.set_active (true);
|
|
|
|
break;
|
2007-10-14 01:45:31 -04:00
|
|
|
|
|
|
|
case MidiEditSelect:
|
|
|
|
midi_tool_select_button.set_active (true);
|
|
|
|
break;
|
|
|
|
|
2007-08-08 15:13:36 -04:00
|
|
|
case MidiEditErase:
|
|
|
|
midi_tool_erase_button.set_active (true);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2007-08-09 16:50:56 -04:00
|
|
|
ignore_midi_edit_mode_toggle = false;
|
2007-08-08 15:13:36 -04:00
|
|
|
|
2007-08-10 16:55:27 -04:00
|
|
|
set_midi_edit_cursor (current_midi_edit_mode());
|
|
|
|
|
|
|
|
if (is_drawable()) {
|
2007-08-08 15:13:36 -04:00
|
|
|
track_canvas.get_window()->set_cursor(*current_canvas_cursor);
|
2007-08-10 16:55:27 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::set_midi_edit_cursor (MidiEditMode m)
|
|
|
|
{
|
|
|
|
switch (midi_edit_mode) {
|
|
|
|
case MidiEditPencil:
|
|
|
|
current_canvas_cursor = midi_pencil_cursor;
|
|
|
|
break;
|
2007-10-14 01:45:31 -04:00
|
|
|
|
|
|
|
case MidiEditSelect:
|
|
|
|
current_canvas_cursor = midi_select_cursor;
|
|
|
|
break;
|
|
|
|
|
2007-08-10 16:55:27 -04:00
|
|
|
case MidiEditErase:
|
|
|
|
current_canvas_cursor = midi_erase_cursor;
|
|
|
|
break;
|
|
|
|
}
|
2007-08-08 15:13:36 -04:00
|
|
|
}
|
|
|
|
|
2006-06-13 03:27:52 -04:00
|
|
|
void
|
|
|
|
Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
/* in object/audition/timefx mode, any button press sets
|
|
|
|
the selection if the object can be selected. this is a
|
|
|
|
bit of hack, because we want to avoid this if the
|
|
|
|
mouse operation is a region alignment.
|
|
|
|
|
2006-06-13 03:27:52 -04:00
|
|
|
note: not dbl-click or triple-click
|
|
|
|
*/
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-06-13 03:27:52 -04:00
|
|
|
if (((mouse_mode != MouseObject) &&
|
|
|
|
(mouse_mode != MouseAudition || item_type != RegionItem) &&
|
2007-03-18 02:07:08 -04:00
|
|
|
(mouse_mode != MouseTimeFX || item_type != RegionItem) &&
|
|
|
|
(mouse_mode != MouseRange)) ||
|
|
|
|
|
2006-06-13 03:27:52 -04:00
|
|
|
(event->type != GDK_BUTTON_PRESS && event->type != GDK_BUTTON_RELEASE || event->button.button > 3)) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2007-01-28 12:44:13 -05:00
|
|
|
|
|
|
|
if (event->type == GDK_BUTTON_PRESS || event->type == GDK_BUTTON_RELEASE) {
|
|
|
|
|
|
|
|
if ((event->button.state & Keyboard::RelevantModifierKeyMask) && event->button.button != 1) {
|
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
/* almost no selection action on modified button-2 or button-3 events */
|
|
|
|
|
|
|
|
if (item_type != RegionItem && event->button.button != 2) {
|
|
|
|
return;
|
|
|
|
}
|
2007-01-28 12:44:13 -05:00
|
|
|
}
|
|
|
|
}
|
2006-06-13 03:27:52 -04:00
|
|
|
|
|
|
|
Selection::Operation op = Keyboard::selection_type (event->button.state);
|
|
|
|
bool press = (event->type == GDK_BUTTON_PRESS);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
// begin_reversible_command (_("select on click"));
|
|
|
|
|
2006-06-13 03:27:52 -04:00
|
|
|
switch (item_type) {
|
|
|
|
case RegionItem:
|
2007-10-11 18:07:47 -04:00
|
|
|
if (mouse_mode != MouseRange) {
|
2008-01-10 16:20:59 -05:00
|
|
|
set_selected_regionview_from_click (press, op, true);
|
2007-10-11 18:07:47 -04:00
|
|
|
} else if (event->type == GDK_BUTTON_PRESS) {
|
2008-01-10 16:20:59 -05:00
|
|
|
set_selected_track_as_side_effect ();
|
2007-10-11 18:07:47 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RegionViewNameHighlight:
|
|
|
|
case RegionViewName:
|
|
|
|
if (mouse_mode != MouseRange) {
|
2008-01-10 16:20:59 -05:00
|
|
|
set_selected_regionview_from_click (press, op, true);
|
2007-10-11 18:07:47 -04:00
|
|
|
} else if (event->type == GDK_BUTTON_PRESS) {
|
2008-01-10 16:20:59 -05:00
|
|
|
set_selected_track_as_side_effect ();
|
2007-10-11 18:07:47 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
case FadeInHandleItem:
|
|
|
|
case FadeInItem:
|
|
|
|
case FadeOutHandleItem:
|
|
|
|
case FadeOutItem:
|
2007-03-18 02:07:08 -04:00
|
|
|
if (mouse_mode != MouseRange) {
|
2008-01-10 16:20:59 -05:00
|
|
|
set_selected_regionview_from_click (press, op, true);
|
2007-03-18 02:07:08 -04:00
|
|
|
} else if (event->type == GDK_BUTTON_PRESS) {
|
2008-01-10 16:20:59 -05:00
|
|
|
set_selected_track_as_side_effect ();
|
2007-03-18 02:07:08 -04:00
|
|
|
}
|
2006-06-13 03:27:52 -04:00
|
|
|
break;
|
2007-05-10 07:53:35 -04:00
|
|
|
|
2007-06-30 14:41:50 -04:00
|
|
|
case ControlPointItem:
|
2008-01-10 16:20:59 -05:00
|
|
|
set_selected_track_as_side_effect ();
|
2007-03-18 02:07:08 -04:00
|
|
|
if (mouse_mode != MouseRange) {
|
2008-01-10 16:20:59 -05:00
|
|
|
set_selected_control_point_from_click (op, false);
|
2007-03-18 02:07:08 -04:00
|
|
|
}
|
2006-06-13 03:27:52 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case StreamItem:
|
2007-03-18 02:07:08 -04:00
|
|
|
/* for context click or range selection, select track */
|
|
|
|
if (event->button.button == 3) {
|
2008-01-10 16:20:59 -05:00
|
|
|
set_selected_track_as_side_effect ();
|
2007-03-18 02:07:08 -04:00
|
|
|
} else if (event->type == GDK_BUTTON_PRESS && mouse_mode == MouseRange) {
|
2008-01-10 16:20:59 -05:00
|
|
|
set_selected_track_as_side_effect ();
|
2007-03-18 02:07:08 -04:00
|
|
|
}
|
2006-06-13 03:27:52 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case AutomationTrackItem:
|
2008-01-10 16:20:59 -05:00
|
|
|
set_selected_track_as_side_effect (true);
|
2006-06-13 03:27:52 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2006-06-13 03:27:52 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
|
|
|
|
{
|
|
|
|
track_canvas.grab_focus();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-06-13 03:27:52 -04:00
|
|
|
if (session && session->actively_recording()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
button_selection (item, event, item_type);
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (drag_info.item == 0 &&
|
|
|
|
(Keyboard::is_delete_event (&event->button) ||
|
|
|
|
Keyboard::is_context_menu_event (&event->button) ||
|
|
|
|
Keyboard::is_edit_event (&event->button))) {
|
|
|
|
|
|
|
|
/* handled by button release */
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (event->button.button) {
|
|
|
|
case 1:
|
|
|
|
|
|
|
|
if (event->type == GDK_BUTTON_PRESS) {
|
|
|
|
|
|
|
|
if (drag_info.item) {
|
2005-11-12 22:53:51 -05:00
|
|
|
drag_info.item->ungrab (event->button.time);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* single mouse clicks on any of these item types operate
|
|
|
|
independent of mouse mode, mostly because they are
|
|
|
|
not on the main track canvas or because we want
|
|
|
|
them to be modeless.
|
|
|
|
*/
|
|
|
|
|
|
|
|
switch (item_type) {
|
|
|
|
case PlayheadCursorItem:
|
|
|
|
start_cursor_grab (item, event);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
case MarkerItem:
|
2008-01-10 16:20:59 -05:00
|
|
|
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::ModifierMask(Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
|
2005-09-25 14:42:24 -04:00
|
|
|
hide_marker (item, event);
|
|
|
|
} else {
|
|
|
|
start_marker_grab (item, event);
|
|
|
|
}
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
case TempoMarkerItem:
|
2008-01-10 16:20:59 -05:00
|
|
|
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)) {
|
2006-03-05 14:39:16 -05:00
|
|
|
start_tempo_marker_copy_grab (item, event);
|
|
|
|
} else {
|
|
|
|
start_tempo_marker_grab (item, event);
|
|
|
|
}
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
case MeterMarkerItem:
|
2008-01-10 16:20:59 -05:00
|
|
|
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)) {
|
2006-03-05 14:39:16 -05:00
|
|
|
start_meter_marker_copy_grab (item, event);
|
|
|
|
} else {
|
|
|
|
start_meter_marker_grab (item, event);
|
|
|
|
}
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
case TempoBarItem:
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
case MeterBarItem:
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
case RangeMarkerBarItem:
|
|
|
|
start_range_markerbar_op (item, event, CreateRangeMarker);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
2006-06-13 03:27:52 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
case CdMarkerBarItem:
|
|
|
|
start_range_markerbar_op (item, event, CreateCDMarker);
|
|
|
|
return true;
|
|
|
|
break;
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
case TransportMarkerBarItem:
|
|
|
|
start_range_markerbar_op (item, event, CreateTransportMarker);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (mouse_mode) {
|
|
|
|
case MouseRange:
|
|
|
|
switch (item_type) {
|
|
|
|
case StartSelectionTrimItem:
|
|
|
|
start_selection_op (item, event, SelectionStartTrim);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EndSelectionTrimItem:
|
|
|
|
start_selection_op (item, event, SelectionEndTrim);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SelectionItem:
|
|
|
|
if (Keyboard::modifier_state_contains
|
2008-01-10 16:20:59 -05:00
|
|
|
(event->button.state, Keyboard::ModifierMask(Keyboard::SecondaryModifier))) {
|
2005-09-25 14:42:24 -04:00
|
|
|
// contains and not equals because I can't use alt as a modifier alone.
|
|
|
|
start_selection_grab (item, event);
|
2008-01-10 16:20:59 -05:00
|
|
|
} else if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
|
2005-09-25 14:42:24 -04:00
|
|
|
/* grab selection for moving */
|
|
|
|
start_selection_op (item, event, SelectionMove);
|
2008-01-07 16:12:29 -05:00
|
|
|
} else {
|
2005-09-25 14:42:24 -04:00
|
|
|
/* this was debated, but decided the more common action was to
|
|
|
|
make a new selection */
|
|
|
|
start_selection_op (item, event, CreateSelection);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
start_selection_op (item, event, CreateSelection);
|
|
|
|
}
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseObject:
|
2008-01-10 16:20:59 -05:00
|
|
|
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::ModifierMask(Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) &&
|
2007-01-28 12:44:13 -05:00
|
|
|
event->type == GDK_BUTTON_PRESS) {
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
start_rubberband_select (item, event);
|
|
|
|
|
|
|
|
} else if (event->type == GDK_BUTTON_PRESS) {
|
|
|
|
|
|
|
|
switch (item_type) {
|
|
|
|
case FadeInHandleItem:
|
|
|
|
start_fade_in_grab (item, event);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
case FadeOutHandleItem:
|
|
|
|
start_fade_out_grab (item, event);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
case RegionItem:
|
2008-01-10 16:20:59 -05:00
|
|
|
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)) {
|
2005-09-25 14:42:24 -04:00
|
|
|
start_region_copy_grab (item, event);
|
|
|
|
} else if (Keyboard::the_keyboard().key_is_down (GDK_b)) {
|
|
|
|
start_region_brush_grab (item, event);
|
|
|
|
} else {
|
|
|
|
start_region_grab (item, event);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
case RegionViewNameHighlight:
|
2005-09-25 14:42:24 -04:00
|
|
|
start_trim (item, event);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
case RegionViewName:
|
2005-09-25 14:42:24 -04:00
|
|
|
/* rename happens on edit clicks */
|
|
|
|
start_trim (clicked_regionview->get_name_highlight(), event);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
2007-06-30 14:41:50 -04:00
|
|
|
case ControlPointItem:
|
2005-09-25 14:42:24 -04:00
|
|
|
start_control_point_grab (item, event);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
2007-06-30 14:41:50 -04:00
|
|
|
case AutomationLineItem:
|
2005-09-25 14:42:24 -04:00
|
|
|
start_line_grab_from_line (item, event);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case StreamItem:
|
|
|
|
case AutomationTrackItem:
|
|
|
|
start_rubberband_select (item, event);
|
|
|
|
break;
|
|
|
|
|
2007-05-10 22:54:43 -04:00
|
|
|
#ifdef WITH_CMT
|
2005-09-25 14:42:24 -04:00
|
|
|
case ImageFrameHandleStartItem:
|
|
|
|
imageframe_start_handle_op(item, event) ;
|
2006-03-07 21:50:53 -05:00
|
|
|
return(true) ;
|
2005-09-25 14:42:24 -04:00
|
|
|
break ;
|
|
|
|
case ImageFrameHandleEndItem:
|
|
|
|
imageframe_end_handle_op(item, event) ;
|
2006-03-07 21:50:53 -05:00
|
|
|
return(true) ;
|
2005-09-25 14:42:24 -04:00
|
|
|
break ;
|
|
|
|
case MarkerViewHandleStartItem:
|
|
|
|
markerview_item_start_handle_op(item, event) ;
|
2006-03-07 21:50:53 -05:00
|
|
|
return(true) ;
|
2005-09-25 14:42:24 -04:00
|
|
|
break ;
|
|
|
|
case MarkerViewHandleEndItem:
|
|
|
|
markerview_item_end_handle_op(item, event) ;
|
2006-03-07 21:50:53 -05:00
|
|
|
return(true) ;
|
2005-09-25 14:42:24 -04:00
|
|
|
break ;
|
|
|
|
case MarkerViewItem:
|
|
|
|
start_markerview_grab(item, event) ;
|
|
|
|
break ;
|
|
|
|
case ImageFrameItem:
|
|
|
|
start_imageframe_grab(item, event) ;
|
|
|
|
break ;
|
2007-05-10 22:54:43 -04:00
|
|
|
#endif
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-06-13 03:27:52 -04:00
|
|
|
case MarkerBarItem:
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseGain:
|
|
|
|
switch (item_type) {
|
|
|
|
case RegionItem:
|
|
|
|
// start_line_grab_from_regionview (item, event);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GainLineItem:
|
|
|
|
start_line_grab_from_line (item, event);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-06-30 14:41:50 -04:00
|
|
|
case ControlPointItem:
|
2005-09-25 14:42:24 -04:00
|
|
|
start_control_point_grab (item, event);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
switch (item_type) {
|
2007-06-30 14:41:50 -04:00
|
|
|
case ControlPointItem:
|
2005-09-25 14:42:24 -04:00
|
|
|
start_control_point_grab (item, event);
|
|
|
|
break;
|
|
|
|
|
2007-06-30 14:41:50 -04:00
|
|
|
case AutomationLineItem:
|
2005-09-25 14:42:24 -04:00
|
|
|
start_line_grab_from_line (item, event);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RegionItem:
|
|
|
|
// XXX need automation mode to identify which
|
|
|
|
// line to use
|
|
|
|
// start_line_grab_from_regionview (item, event);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseZoom:
|
|
|
|
if (event->type == GDK_BUTTON_PRESS) {
|
|
|
|
start_mouse_zoom (item, event);
|
|
|
|
}
|
|
|
|
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseTimeFX:
|
|
|
|
if (item_type == RegionItem) {
|
|
|
|
start_time_fx (item, event);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseAudition:
|
2007-10-11 18:07:47 -04:00
|
|
|
_scrubbing = true;
|
2008-01-07 16:12:29 -05:00
|
|
|
scrub_reversals = 0;
|
|
|
|
scrub_reverse_distance = 0;
|
2007-11-07 20:40:25 -05:00
|
|
|
last_scrub_x = event->button.x;
|
|
|
|
scrubbing_direction = 0;
|
2008-01-07 16:12:29 -05:00
|
|
|
track_canvas.get_window()->set_cursor (*transparent_cursor);
|
2007-10-11 18:07:47 -04:00
|
|
|
/* rest handled in motion & release */
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
2007-10-14 01:45:31 -04:00
|
|
|
case MouseNote:
|
|
|
|
start_create_region_grab (item, event);
|
|
|
|
break;
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
switch (mouse_mode) {
|
|
|
|
case MouseObject:
|
|
|
|
if (event->type == GDK_BUTTON_PRESS) {
|
|
|
|
switch (item_type) {
|
|
|
|
case RegionItem:
|
2008-01-10 16:20:59 -05:00
|
|
|
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)) {
|
2005-09-25 14:42:24 -04:00
|
|
|
start_region_copy_grab (item, event);
|
|
|
|
} else {
|
|
|
|
start_region_grab (item, event);
|
|
|
|
}
|
2008-01-10 16:20:59 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
2007-06-30 14:41:50 -04:00
|
|
|
case ControlPointItem:
|
2005-09-25 14:42:24 -04:00
|
|
|
start_control_point_grab (item, event);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch (item_type) {
|
2006-07-23 08:03:19 -04:00
|
|
|
case RegionViewNameHighlight:
|
2005-09-25 14:42:24 -04:00
|
|
|
start_trim (item, event);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
case RegionViewName:
|
2005-09-25 14:42:24 -04:00
|
|
|
start_trim (clicked_regionview->get_name_highlight(), event);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseRange:
|
|
|
|
if (event->type == GDK_BUTTON_PRESS) {
|
|
|
|
/* relax till release */
|
|
|
|
}
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case MouseZoom:
|
2008-01-10 16:20:59 -05:00
|
|
|
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
|
2005-09-25 14:42:24 -04:00
|
|
|
temporal_zoom_session();
|
|
|
|
} else {
|
|
|
|
temporal_zoom_to_frame (true, event_frame(event));
|
|
|
|
}
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
2006-03-07 21:50:53 -05:00
|
|
|
|
|
|
|
return false;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2005-11-22 00:10:12 -05:00
|
|
|
bool
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t where = event_frame (event, 0, 0);
|
2008-02-16 17:43:18 -05:00
|
|
|
AutomationTimeAxisView* atv = 0;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
/* no action if we're recording */
|
|
|
|
|
|
|
|
if (session && session->actively_recording()) {
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* first, see if we're finishing a drag ... */
|
|
|
|
|
|
|
|
if (drag_info.item) {
|
|
|
|
if (end_grab (item, event)) {
|
|
|
|
/* grab dragged, so do nothing else */
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-06-13 03:27:52 -04:00
|
|
|
button_selection (item, event, item_type);
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
/* edit events get handled here */
|
|
|
|
|
|
|
|
if (drag_info.item == 0 && Keyboard::is_edit_event (&event->button)) {
|
|
|
|
switch (item_type) {
|
|
|
|
case RegionItem:
|
|
|
|
edit_region ();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TempoMarkerItem:
|
|
|
|
edit_tempo_marker (item);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MeterMarkerItem:
|
|
|
|
edit_meter_marker (item);
|
|
|
|
break;
|
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
case RegionViewName:
|
2005-09-25 14:42:24 -04:00
|
|
|
if (clicked_regionview->name_active()) {
|
|
|
|
return mouse_rename_region (item, event);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* context menu events get handled here */
|
|
|
|
|
|
|
|
if (Keyboard::is_context_menu_event (&event->button)) {
|
|
|
|
|
|
|
|
if (drag_info.item == 0) {
|
|
|
|
|
|
|
|
/* no matter which button pops up the context menu, tell the menu
|
|
|
|
widget to use button 1 to drive menu selection.
|
|
|
|
*/
|
|
|
|
|
|
|
|
switch (item_type) {
|
|
|
|
case FadeInItem:
|
|
|
|
case FadeInHandleItem:
|
|
|
|
case FadeOutItem:
|
|
|
|
case FadeOutHandleItem:
|
|
|
|
popup_fade_context_menu (1, event->button.time, item, item_type);
|
|
|
|
break;
|
2008-01-12 18:45:50 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
case StreamItem:
|
2008-01-12 18:45:50 -05:00
|
|
|
popup_track_context_menu (1, event->button.time, item_type, false, where);
|
2007-10-11 18:07:47 -04:00
|
|
|
break;
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
case RegionItem:
|
2006-07-23 08:03:19 -04:00
|
|
|
case RegionViewNameHighlight:
|
|
|
|
case RegionViewName:
|
2008-01-12 18:45:50 -05:00
|
|
|
popup_track_context_menu (1, event->button.time, item_type, false, where);
|
2007-10-11 18:07:47 -04:00
|
|
|
break;
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
case SelectionItem:
|
2008-01-12 18:45:50 -05:00
|
|
|
popup_track_context_menu (1, event->button.time, item_type, true, where);
|
2007-10-11 18:07:47 -04:00
|
|
|
break;
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
case AutomationTrackItem:
|
2008-01-12 18:45:50 -05:00
|
|
|
popup_track_context_menu (1, event->button.time, item_type, false, where);
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case MarkerBarItem:
|
|
|
|
case RangeMarkerBarItem:
|
2008-01-10 16:20:59 -05:00
|
|
|
case TransportMarkerBarItem:
|
|
|
|
case CdMarkerBarItem:
|
2005-09-25 14:42:24 -04:00
|
|
|
case TempoBarItem:
|
|
|
|
case MeterBarItem:
|
|
|
|
popup_ruler_menu (pixel_to_frame(event->button.x), item_type);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MarkerItem:
|
|
|
|
marker_context_menu (&event->button, item);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TempoMarkerItem:
|
|
|
|
tm_marker_context_menu (&event->button, item);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MeterMarkerItem:
|
|
|
|
tm_marker_context_menu (&event->button, item);
|
|
|
|
break;
|
2008-01-12 18:45:50 -05:00
|
|
|
|
|
|
|
case CrossfadeViewItem:
|
|
|
|
popup_track_context_menu (1, event->button.time, item_type, false, where);
|
|
|
|
break;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-05-10 22:54:43 -04:00
|
|
|
#ifdef WITH_CMT
|
2005-09-25 14:42:24 -04:00
|
|
|
case ImageFrameItem:
|
|
|
|
popup_imageframe_edit_menu(1, event->button.time, item, true) ;
|
|
|
|
break ;
|
|
|
|
case ImageFrameTimeAxisItem:
|
|
|
|
popup_imageframe_edit_menu(1, event->button.time, item, false) ;
|
|
|
|
break ;
|
|
|
|
case MarkerViewItem:
|
|
|
|
popup_marker_time_axis_edit_menu(1, event->button.time, item, true) ;
|
|
|
|
break ;
|
|
|
|
case MarkerTimeAxisItem:
|
|
|
|
popup_marker_time_axis_edit_menu(1, event->button.time, item, false) ;
|
|
|
|
break ;
|
2007-05-10 22:54:43 -04:00
|
|
|
#endif
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* delete events get handled here */
|
|
|
|
|
|
|
|
if (drag_info.item == 0 && Keyboard::is_delete_event (&event->button)) {
|
|
|
|
|
|
|
|
switch (item_type) {
|
|
|
|
case TempoMarkerItem:
|
|
|
|
remove_tempo_marker (item);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MeterMarkerItem:
|
|
|
|
remove_meter_marker (item);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MarkerItem:
|
2005-11-12 22:53:51 -05:00
|
|
|
remove_marker (*item, event);
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case RegionItem:
|
|
|
|
if (mouse_mode == MouseObject) {
|
|
|
|
remove_clicked_region ();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2007-06-30 14:41:50 -04:00
|
|
|
case ControlPointItem:
|
2005-09-25 14:42:24 -04:00
|
|
|
if (mouse_mode == MouseGain) {
|
|
|
|
remove_gain_control_point (item, event);
|
2007-06-30 14:41:50 -04:00
|
|
|
} else {
|
|
|
|
remove_control_point (item, event);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (event->button.button) {
|
|
|
|
case 1:
|
|
|
|
|
|
|
|
switch (item_type) {
|
|
|
|
/* see comments in button_press_handler */
|
|
|
|
case PlayheadCursorItem:
|
|
|
|
case MarkerItem:
|
|
|
|
case GainLineItem:
|
2007-06-30 14:41:50 -04:00
|
|
|
case AutomationLineItem:
|
2005-09-25 14:42:24 -04:00
|
|
|
case StartSelectionTrimItem:
|
|
|
|
case EndSelectionTrimItem:
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
case MarkerBarItem:
|
|
|
|
if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
|
|
|
|
snap_to (where, 0, true);
|
|
|
|
}
|
|
|
|
mouse_add_new_marker (where);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
case CdMarkerBarItem:
|
|
|
|
// if we get here then a dragged range wasn't done
|
|
|
|
if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
|
|
|
|
snap_to (where, 0, true);
|
|
|
|
}
|
|
|
|
mouse_add_new_marker (where, true);
|
|
|
|
return true;
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
case TempoBarItem:
|
|
|
|
if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
|
|
|
|
snap_to (where);
|
|
|
|
}
|
|
|
|
mouse_add_new_tempo_event (where);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
case MeterBarItem:
|
|
|
|
mouse_add_new_meter_event (pixel_to_frame (event->button.x));
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (mouse_mode) {
|
|
|
|
case MouseObject:
|
|
|
|
switch (item_type) {
|
|
|
|
case AutomationTrackItem:
|
2008-02-16 17:43:18 -05:00
|
|
|
atv = dynamic_cast<AutomationTimeAxisView*>(clicked_routeview);
|
|
|
|
if (atv) {
|
|
|
|
atv->add_automation_event (item, event, where, event->button.y);
|
|
|
|
}
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseGain:
|
2006-08-01 13:19:38 -04:00
|
|
|
// Gain only makes sense for audio regions
|
2007-04-12 19:20:37 -04:00
|
|
|
|
|
|
|
if (!dynamic_cast<AudioRegionView*>(clicked_regionview)) {
|
2006-08-01 13:19:38 -04:00
|
|
|
break;
|
2007-04-12 19:20:37 -04:00
|
|
|
}
|
2006-08-01 13:19:38 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
switch (item_type) {
|
|
|
|
case RegionItem:
|
2006-07-23 08:03:19 -04:00
|
|
|
dynamic_cast<AudioRegionView*>(clicked_regionview)->add_gain_point_event (item, event);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case AutomationTrackItem:
|
2006-08-16 16:36:14 -04:00
|
|
|
dynamic_cast<AutomationTimeAxisView*>(clicked_axisview)->
|
2005-09-25 14:42:24 -04:00
|
|
|
add_automation_event (item, event, where, event->button.y);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseAudition:
|
2007-10-11 18:07:47 -04:00
|
|
|
_scrubbing = false;
|
2008-01-07 16:12:29 -05:00
|
|
|
track_canvas.get_window()->set_cursor (*current_canvas_cursor);
|
2007-11-07 20:40:25 -05:00
|
|
|
if (scrubbing_direction == 0) {
|
2007-10-11 18:07:47 -04:00
|
|
|
/* no drag, just a click */
|
|
|
|
switch (item_type) {
|
|
|
|
case RegionItem:
|
2008-01-10 16:20:59 -05:00
|
|
|
play_selected_region ();
|
2007-10-11 18:07:47 -04:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* make sure we stop */
|
|
|
|
session->request_transport_speed (0.0);
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
2007-10-14 01:45:31 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
switch (mouse_mode) {
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
case MouseObject:
|
|
|
|
switch (item_type) {
|
|
|
|
case RegionItem:
|
|
|
|
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
|
|
|
|
raise_region ();
|
|
|
|
} else if (Keyboard::modifier_state_equals (event->button.state, Keyboard::ModifierMask (Keyboard::TertiaryModifier|Keyboard::SecondaryModifier))) {
|
|
|
|
lower_region ();
|
|
|
|
} else {
|
|
|
|
// Button2 click is unused
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
case MouseRange:
|
|
|
|
|
|
|
|
// x_style_paste (where, 1.0);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2006-03-07 21:50:53 -05:00
|
|
|
return false;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2005-11-22 00:10:12 -05:00
|
|
|
bool
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
ControlPoint* cp;
|
|
|
|
Marker * marker;
|
|
|
|
double fraction;
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
if (last_item_entered != item) {
|
|
|
|
last_item_entered = item;
|
|
|
|
last_item_entered_n = 0;
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
switch (item_type) {
|
2007-06-30 14:41:50 -04:00
|
|
|
case ControlPointItem:
|
2007-03-18 02:07:08 -04:00
|
|
|
if (mouse_mode == MouseGain || mouse_mode == MouseObject) {
|
|
|
|
cp = static_cast<ControlPoint*>(item->get_data ("control_point"));
|
|
|
|
cp->set_visible (true);
|
|
|
|
|
|
|
|
double at_x, at_y;
|
|
|
|
at_x = cp->get_x();
|
|
|
|
at_y = cp->get_y ();
|
2007-07-06 23:19:04 -04:00
|
|
|
cp->item()->i2w (at_x, at_y);
|
2007-03-18 02:07:08 -04:00
|
|
|
at_x += 20.0;
|
|
|
|
at_y += 20.0;
|
|
|
|
|
2007-07-06 23:19:04 -04:00
|
|
|
fraction = 1.0 - (cp->get_y() / cp->line().height());
|
2007-03-18 02:07:08 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (is_drawable() && !_scrubbing) {
|
|
|
|
track_canvas.get_window()->set_cursor (*fader_cursor);
|
2007-03-18 02:07:08 -04:00
|
|
|
}
|
2008-02-16 17:43:18 -05:00
|
|
|
|
|
|
|
last_item_entered_n++;
|
|
|
|
set_verbose_canvas_cursor (cp->line().get_verbose_cursor_string (fraction), at_x, at_y);
|
|
|
|
if (last_item_entered_n < 10) {
|
|
|
|
show_verbose_canvas_cursor ();
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
break;
|
2008-01-10 16:20:59 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
case GainLineItem:
|
|
|
|
if (mouse_mode == MouseGain) {
|
2005-11-27 17:35:04 -05:00
|
|
|
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
|
|
|
|
if (line)
|
2007-06-29 13:13:09 -04:00
|
|
|
line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_EnteredGainLine.get();
|
2005-09-25 14:42:24 -04:00
|
|
|
if (is_drawable()) {
|
2005-12-12 15:54:55 -05:00
|
|
|
track_canvas.get_window()->set_cursor (*fader_cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2007-06-30 14:41:50 -04:00
|
|
|
case AutomationLineItem:
|
2007-03-18 02:07:08 -04:00
|
|
|
if (mouse_mode == MouseGain || mouse_mode == MouseObject) {
|
|
|
|
{
|
|
|
|
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
|
|
|
|
if (line)
|
2007-06-29 13:13:09 -04:00
|
|
|
line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_EnteredAutomationLine.get();
|
2007-03-18 02:07:08 -04:00
|
|
|
}
|
|
|
|
if (is_drawable()) {
|
|
|
|
track_canvas.get_window()->set_cursor (*fader_cursor);
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
case RegionViewNameHighlight:
|
2005-09-25 14:42:24 -04:00
|
|
|
if (is_drawable() && mouse_mode == MouseObject) {
|
2005-12-12 15:54:55 -05:00
|
|
|
track_canvas.get_window()->set_cursor (*trimmer_cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case StartSelectionTrimItem:
|
|
|
|
case EndSelectionTrimItem:
|
2007-05-10 22:54:43 -04:00
|
|
|
|
|
|
|
#ifdef WITH_CMT
|
2005-09-25 14:42:24 -04:00
|
|
|
case ImageFrameHandleStartItem:
|
|
|
|
case ImageFrameHandleEndItem:
|
|
|
|
case MarkerViewHandleStartItem:
|
|
|
|
case MarkerViewHandleEndItem:
|
2007-05-10 22:54:43 -04:00
|
|
|
#endif
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (is_drawable()) {
|
2005-12-12 15:54:55 -05:00
|
|
|
track_canvas.get_window()->set_cursor (*trimmer_cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PlayheadCursorItem:
|
|
|
|
if (is_drawable()) {
|
2008-02-16 17:43:18 -05:00
|
|
|
switch (_edit_point) {
|
|
|
|
case EditAtMouse:
|
|
|
|
track_canvas.get_window()->set_cursor (*grabber_edit_point_cursor);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
track_canvas.get_window()->set_cursor (*grabber_cursor);
|
|
|
|
break;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
case RegionViewName:
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
/* when the name is not an active item, the entire name highlight is for trimming */
|
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
if (!reinterpret_cast<RegionView *> (item->get_data ("regionview"))->name_active()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
if (mouse_mode == MouseObject && is_drawable()) {
|
2005-12-12 15:54:55 -05:00
|
|
|
track_canvas.get_window()->set_cursor (*trimmer_cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case AutomationTrackItem:
|
|
|
|
if (is_drawable()) {
|
2007-08-10 16:55:27 -04:00
|
|
|
Gdk::Cursor *cursor;
|
2005-09-25 14:42:24 -04:00
|
|
|
switch (mouse_mode) {
|
|
|
|
case MouseRange:
|
|
|
|
cursor = selector_cursor;
|
|
|
|
break;
|
|
|
|
case MouseZoom:
|
|
|
|
cursor = zoom_cursor;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
cursor = cross_hair_cursor;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-12-12 15:54:55 -05:00
|
|
|
track_canvas.get_window()->set_cursor (*cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
AutomationTimeAxisView* atv;
|
2005-11-28 17:36:26 -05:00
|
|
|
if ((atv = static_cast<AutomationTimeAxisView*>(item->get_data ("trackview"))) != 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
clear_entered_track = false;
|
|
|
|
set_entered_track (atv);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MarkerBarItem:
|
|
|
|
case RangeMarkerBarItem:
|
|
|
|
case TransportMarkerBarItem:
|
2008-01-10 16:20:59 -05:00
|
|
|
case CdMarkerBarItem:
|
2005-09-25 14:42:24 -04:00
|
|
|
case MeterBarItem:
|
|
|
|
case TempoBarItem:
|
|
|
|
if (is_drawable()) {
|
2005-12-12 15:54:55 -05:00
|
|
|
time_canvas.get_window()->set_cursor (*timebar_cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MarkerItem:
|
2005-11-28 17:36:26 -05:00
|
|
|
if ((marker = static_cast<Marker *> (item->get_data ("marker"))) == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
}
|
2007-11-12 17:23:01 -05:00
|
|
|
entered_marker = marker;
|
2007-06-29 13:13:09 -04:00
|
|
|
marker->set_color_rgba (ARDOUR_UI::config()->canvasvar_EnteredMarker.get());
|
2005-09-25 14:42:24 -04:00
|
|
|
// fall through
|
|
|
|
case MeterMarkerItem:
|
|
|
|
case TempoMarkerItem:
|
|
|
|
if (is_drawable()) {
|
2005-12-12 15:54:55 -05:00
|
|
|
time_canvas.get_window()->set_cursor (*timebar_cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FadeInHandleItem:
|
|
|
|
case FadeOutHandleItem:
|
|
|
|
if (mouse_mode == MouseObject) {
|
2005-11-27 17:35:04 -05:00
|
|
|
ArdourCanvas::SimpleRect *rect = dynamic_cast<ArdourCanvas::SimpleRect *> (item);
|
|
|
|
if (rect) {
|
|
|
|
rect->property_fill_color_rgba() = 0;
|
|
|
|
rect->property_outline_pixels() = 1;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* second pass to handle entered track status in a comprehensible way.
|
|
|
|
*/
|
|
|
|
|
|
|
|
switch (item_type) {
|
|
|
|
case GainLineItem:
|
2007-06-30 14:41:50 -04:00
|
|
|
case AutomationLineItem:
|
|
|
|
case ControlPointItem:
|
2005-09-25 14:42:24 -04:00
|
|
|
/* these do not affect the current entered track state */
|
|
|
|
clear_entered_track = false;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AutomationTrackItem:
|
|
|
|
/* handled above already */
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
set_entered_track (0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2006-03-07 21:50:53 -05:00
|
|
|
return false;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2005-11-22 00:10:12 -05:00
|
|
|
bool
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
AutomationLine* al;
|
|
|
|
ControlPoint* cp;
|
|
|
|
Marker *marker;
|
|
|
|
Location *loc;
|
2006-07-23 08:03:19 -04:00
|
|
|
RegionView* rv;
|
2005-09-25 14:42:24 -04:00
|
|
|
bool is_start;
|
|
|
|
|
|
|
|
switch (item_type) {
|
2007-06-30 14:41:50 -04:00
|
|
|
case ControlPointItem:
|
2005-11-28 17:36:26 -05:00
|
|
|
cp = reinterpret_cast<ControlPoint*>(item->get_data ("control_point"));
|
2007-07-06 23:19:04 -04:00
|
|
|
if (cp->line().the_list()->interpolation() != AutomationList::Discrete) {
|
|
|
|
if (cp->line().npoints() > 1 && !cp->selected()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
cp->set_visible (false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_drawable()) {
|
2005-12-12 15:54:55 -05:00
|
|
|
track_canvas.get_window()->set_cursor (*current_canvas_cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
hide_verbose_canvas_cursor ();
|
|
|
|
break;
|
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
case RegionViewNameHighlight:
|
2005-09-25 14:42:24 -04:00
|
|
|
case StartSelectionTrimItem:
|
|
|
|
case EndSelectionTrimItem:
|
|
|
|
case PlayheadCursorItem:
|
2007-05-10 22:54:43 -04:00
|
|
|
|
|
|
|
#ifdef WITH_CMT
|
2005-09-25 14:42:24 -04:00
|
|
|
case ImageFrameHandleStartItem:
|
|
|
|
case ImageFrameHandleEndItem:
|
|
|
|
case MarkerViewHandleStartItem:
|
|
|
|
case MarkerViewHandleEndItem:
|
2007-05-10 22:54:43 -04:00
|
|
|
#endif
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (is_drawable()) {
|
2005-12-12 15:54:55 -05:00
|
|
|
track_canvas.get_window()->set_cursor (*current_canvas_cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GainLineItem:
|
2007-06-30 14:41:50 -04:00
|
|
|
case AutomationLineItem:
|
2005-11-28 17:36:26 -05:00
|
|
|
al = reinterpret_cast<AutomationLine*> (item->get_data ("line"));
|
2005-11-27 17:35:04 -05:00
|
|
|
{
|
|
|
|
ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
|
|
|
|
if (line)
|
|
|
|
line->property_fill_color_rgba() = al->get_line_color();
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
if (is_drawable()) {
|
2005-12-12 15:54:55 -05:00
|
|
|
track_canvas.get_window()->set_cursor (*current_canvas_cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
case RegionViewName:
|
2005-09-25 14:42:24 -04:00
|
|
|
/* see enter_handler() for notes */
|
2006-07-23 08:03:19 -04:00
|
|
|
if (!reinterpret_cast<RegionView *> (item->get_data ("regionview"))->name_active()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
if (is_drawable() && mouse_mode == MouseObject) {
|
2005-12-12 15:54:55 -05:00
|
|
|
track_canvas.get_window()->set_cursor (*current_canvas_cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RangeMarkerBarItem:
|
|
|
|
case TransportMarkerBarItem:
|
2008-01-10 16:20:59 -05:00
|
|
|
case CdMarkerBarItem:
|
2005-09-25 14:42:24 -04:00
|
|
|
case MeterBarItem:
|
|
|
|
case TempoBarItem:
|
|
|
|
case MarkerBarItem:
|
|
|
|
if (is_drawable()) {
|
2005-12-12 15:54:55 -05:00
|
|
|
time_canvas.get_window()->set_cursor (*timebar_cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MarkerItem:
|
2005-11-28 17:36:26 -05:00
|
|
|
if ((marker = static_cast<Marker *> (item->get_data ("marker"))) == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
}
|
2007-11-12 17:23:01 -05:00
|
|
|
entered_marker = 0;
|
|
|
|
if ((loc = find_location_from_marker (marker, is_start)) != 0) {
|
|
|
|
location_flags_changed (loc, this);
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
// fall through
|
|
|
|
case MeterMarkerItem:
|
|
|
|
case TempoMarkerItem:
|
|
|
|
|
|
|
|
if (is_drawable()) {
|
2005-12-12 15:54:55 -05:00
|
|
|
time_canvas.get_window()->set_cursor (*timebar_cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FadeInHandleItem:
|
|
|
|
case FadeOutHandleItem:
|
2006-07-23 08:03:19 -04:00
|
|
|
rv = static_cast<RegionView*>(item->get_data ("regionview"));
|
2005-11-27 17:35:04 -05:00
|
|
|
{
|
|
|
|
ArdourCanvas::SimpleRect *rect = dynamic_cast<ArdourCanvas::SimpleRect *> (item);
|
|
|
|
if (rect) {
|
|
|
|
rect->property_fill_color_rgba() = rv->get_fill_color();
|
|
|
|
rect->property_outline_pixels() = 0;
|
|
|
|
}
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case AutomationTrackItem:
|
|
|
|
if (is_drawable()) {
|
2005-12-12 15:54:55 -05:00
|
|
|
track_canvas.get_window()->set_cursor (*current_canvas_cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
clear_entered_track = true;
|
2005-10-09 01:03:29 -04:00
|
|
|
Glib::signal_idle().connect (mem_fun(*this, &Editor::left_automation_track));
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2006-03-07 21:50:53 -05:00
|
|
|
return false;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
gint
|
|
|
|
Editor::left_automation_track ()
|
|
|
|
{
|
|
|
|
if (clear_entered_track) {
|
|
|
|
set_entered_track (0);
|
|
|
|
clear_entered_track = false;
|
|
|
|
}
|
2006-03-07 21:50:53 -05:00
|
|
|
return false;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2005-11-22 00:10:12 -05:00
|
|
|
bool
|
2006-05-17 22:19:27 -04:00
|
|
|
Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type, bool from_autoscroll)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2008-01-10 16:20:59 -05:00
|
|
|
if (event->motion.is_hint) {
|
|
|
|
gint x, y;
|
|
|
|
|
|
|
|
/* We call this so that MOTION_NOTIFY events continue to be
|
|
|
|
delivered to the canvas. We need to do this because we set
|
|
|
|
Gdk::POINTER_MOTION_HINT_MASK on the canvas. This reduces
|
|
|
|
the density of the events, at the expense of a round-trip
|
|
|
|
to the server. Given that this will mostly occur on cases
|
|
|
|
where DISPLAY = :0.0, and given the cost of what the motion
|
|
|
|
event might do, its a good tradeoff.
|
|
|
|
*/
|
|
|
|
|
|
|
|
track_canvas.get_pointer (x, y);
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (current_stepping_trackview) {
|
|
|
|
/* don't keep the persistent stepped trackview if the mouse moves */
|
|
|
|
current_stepping_trackview = 0;
|
|
|
|
step_timeout.disconnect ();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (session && session->actively_recording()) {
|
|
|
|
/* Sorry. no dragging stuff around while we record */
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2006-05-17 22:19:27 -04:00
|
|
|
drag_info.item_type = item_type;
|
2007-11-05 10:38:19 -05:00
|
|
|
drag_info.last_pointer_x = drag_info.current_pointer_x;
|
|
|
|
drag_info.last_pointer_y = drag_info.current_pointer_y;
|
2005-09-25 14:42:24 -04:00
|
|
|
drag_info.current_pointer_frame = event_frame (event, &drag_info.current_pointer_x,
|
|
|
|
&drag_info.current_pointer_y);
|
2006-01-02 15:27:51 -05:00
|
|
|
|
2007-10-11 18:07:47 -04:00
|
|
|
switch (mouse_mode) {
|
|
|
|
case MouseAudition:
|
|
|
|
if (_scrubbing) {
|
|
|
|
|
2007-11-07 20:40:25 -05:00
|
|
|
double delta;
|
2007-10-11 18:07:47 -04:00
|
|
|
|
2007-11-07 20:40:25 -05:00
|
|
|
if (scrubbing_direction == 0) {
|
|
|
|
/* first move */
|
|
|
|
session->request_locate (drag_info.current_pointer_frame, false);
|
|
|
|
session->request_transport_speed (0.1);
|
|
|
|
scrubbing_direction = 1;
|
2007-10-11 18:07:47 -04:00
|
|
|
|
|
|
|
} else {
|
2007-11-07 20:40:25 -05:00
|
|
|
|
|
|
|
if (last_scrub_x > drag_info.current_pointer_x) {
|
2008-01-07 16:12:29 -05:00
|
|
|
|
|
|
|
/* pointer moved to the left */
|
2007-11-07 20:40:25 -05:00
|
|
|
|
|
|
|
if (scrubbing_direction > 0) {
|
2008-01-07 16:12:29 -05:00
|
|
|
|
2007-11-07 20:40:25 -05:00
|
|
|
/* we reversed direction to go backwards */
|
2008-01-07 16:12:29 -05:00
|
|
|
|
|
|
|
scrub_reversals++;
|
|
|
|
scrub_reverse_distance += (int) (last_scrub_x - drag_info.current_pointer_x);
|
|
|
|
|
2007-11-07 20:40:25 -05:00
|
|
|
} else {
|
2008-01-07 16:12:29 -05:00
|
|
|
|
2007-11-07 20:40:25 -05:00
|
|
|
/* still moving to the left (backwards) */
|
|
|
|
|
2008-01-07 16:12:29 -05:00
|
|
|
scrub_reversals = 0;
|
|
|
|
scrub_reverse_distance = 0;
|
|
|
|
|
|
|
|
delta = 0.01 * (last_scrub_x - drag_info.current_pointer_x);
|
2007-11-07 20:40:25 -05:00
|
|
|
session->request_transport_speed (session->transport_speed() - delta);
|
|
|
|
}
|
|
|
|
|
2007-10-11 18:07:47 -04:00
|
|
|
} else {
|
2008-01-07 16:12:29 -05:00
|
|
|
/* pointer moved to the right */
|
|
|
|
|
2007-11-07 20:40:25 -05:00
|
|
|
if (scrubbing_direction < 0) {
|
|
|
|
/* we reversed direction to go forward */
|
2008-01-07 16:12:29 -05:00
|
|
|
|
|
|
|
scrub_reversals++;
|
|
|
|
scrub_reverse_distance += (int) (drag_info.current_pointer_x - last_scrub_x);
|
|
|
|
|
2007-11-07 20:40:25 -05:00
|
|
|
} else {
|
|
|
|
/* still moving to the right */
|
2008-01-07 16:12:29 -05:00
|
|
|
|
|
|
|
scrub_reversals = 0;
|
|
|
|
scrub_reverse_distance = 0;
|
2007-11-07 20:40:25 -05:00
|
|
|
|
2008-01-07 16:12:29 -05:00
|
|
|
delta = 0.01 * (drag_info.current_pointer_x - last_scrub_x);
|
2007-11-07 20:40:25 -05:00
|
|
|
session->request_transport_speed (session->transport_speed() + delta);
|
|
|
|
}
|
2008-01-07 16:12:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* if there have been more than 2 opposite motion moves detected, or one that moves
|
|
|
|
back more than 10 pixels, reverse direction
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (scrub_reversals >= 2 || scrub_reverse_distance > 10) {
|
|
|
|
|
|
|
|
if (scrubbing_direction > 0) {
|
|
|
|
/* was forwards, go backwards */
|
|
|
|
session->request_transport_speed (-0.1);
|
|
|
|
scrubbing_direction = -1;
|
|
|
|
} else {
|
|
|
|
/* was backwards, go forwards */
|
|
|
|
session->request_transport_speed (0.1);
|
|
|
|
scrubbing_direction = 1;
|
|
|
|
}
|
2007-11-07 20:40:25 -05:00
|
|
|
|
2008-01-07 16:12:29 -05:00
|
|
|
scrub_reverse_distance = 0;
|
|
|
|
scrub_reversals = 0;
|
2007-10-11 18:07:47 -04:00
|
|
|
}
|
|
|
|
}
|
2007-11-07 20:40:25 -05:00
|
|
|
|
|
|
|
last_scrub_x = drag_info.current_pointer_x;
|
2007-10-11 18:07:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-17 22:19:27 -04:00
|
|
|
if (!from_autoscroll && drag_info.item) {
|
2006-05-25 16:30:32 -04:00
|
|
|
/* item != 0 is the best test i can think of for dragging.
|
2005-09-25 14:42:24 -04:00
|
|
|
*/
|
2006-06-13 03:27:52 -04:00
|
|
|
if (!drag_info.move_threshold_passed) {
|
2006-05-25 16:30:32 -04:00
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
bool x_threshold_passed = (::llabs ((nframes64_t) (drag_info.current_pointer_x - drag_info.grab_x)) > 4LL);
|
|
|
|
bool y_threshold_passed = (::llabs ((nframes64_t) (drag_info.current_pointer_y - drag_info.grab_y)) > 4LL);
|
2007-05-31 17:15:28 -04:00
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
drag_info.move_threshold_passed = (x_threshold_passed || y_threshold_passed);
|
2006-03-07 21:50:53 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
// and change the initial grab loc/frame if this drag info wants us to
|
2006-05-25 16:30:32 -04:00
|
|
|
|
2006-06-13 03:27:52 -04:00
|
|
|
if (drag_info.want_move_threshold && drag_info.move_threshold_passed) {
|
2005-09-25 14:42:24 -04:00
|
|
|
drag_info.grab_frame = drag_info.current_pointer_frame;
|
|
|
|
drag_info.grab_x = drag_info.current_pointer_x;
|
|
|
|
drag_info.grab_y = drag_info.current_pointer_y;
|
|
|
|
drag_info.last_pointer_frame = drag_info.grab_frame;
|
|
|
|
drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (item_type) {
|
|
|
|
case PlayheadCursorItem:
|
|
|
|
case MarkerItem:
|
2007-06-30 14:41:50 -04:00
|
|
|
case ControlPointItem:
|
2005-09-25 14:42:24 -04:00
|
|
|
case TempoMarkerItem:
|
|
|
|
case MeterMarkerItem:
|
2006-07-23 08:03:19 -04:00
|
|
|
case RegionViewNameHighlight:
|
2005-09-25 14:42:24 -04:00
|
|
|
case StartSelectionTrimItem:
|
|
|
|
case EndSelectionTrimItem:
|
|
|
|
case SelectionItem:
|
|
|
|
case GainLineItem:
|
2007-06-30 14:41:50 -04:00
|
|
|
case AutomationLineItem:
|
2005-09-25 14:42:24 -04:00
|
|
|
case FadeInHandleItem:
|
|
|
|
case FadeOutHandleItem:
|
2007-05-10 22:54:43 -04:00
|
|
|
|
|
|
|
#ifdef WITH_CMT
|
2005-09-25 14:42:24 -04:00
|
|
|
case ImageFrameHandleStartItem:
|
|
|
|
case ImageFrameHandleEndItem:
|
|
|
|
case MarkerViewHandleStartItem:
|
|
|
|
case MarkerViewHandleEndItem:
|
2007-05-10 22:54:43 -04:00
|
|
|
#endif
|
|
|
|
|
2005-11-12 22:53:51 -05:00
|
|
|
if (drag_info.item && (event->motion.state & Gdk::BUTTON1_MASK ||
|
|
|
|
(event->motion.state & Gdk::BUTTON2_MASK))) {
|
2006-05-17 22:19:27 -04:00
|
|
|
if (!from_autoscroll) {
|
|
|
|
maybe_autoscroll (event);
|
|
|
|
}
|
|
|
|
(this->*(drag_info.motion_callback)) (item, event);
|
|
|
|
goto handled;
|
|
|
|
}
|
|
|
|
goto not_handled;
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (mouse_mode) {
|
|
|
|
case MouseObject:
|
|
|
|
case MouseRange:
|
|
|
|
case MouseZoom:
|
|
|
|
case MouseTimeFX:
|
2007-10-14 01:45:31 -04:00
|
|
|
case MouseNote:
|
2005-09-25 14:42:24 -04:00
|
|
|
if (drag_info.item && (event->motion.state & GDK_BUTTON1_MASK ||
|
|
|
|
(event->motion.state & GDK_BUTTON2_MASK))) {
|
2006-05-17 22:19:27 -04:00
|
|
|
if (!from_autoscroll) {
|
|
|
|
maybe_autoscroll (event);
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
(this->*(drag_info.motion_callback)) (item, event);
|
|
|
|
goto handled;
|
|
|
|
}
|
|
|
|
goto not_handled;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
handled:
|
2005-10-26 21:10:36 -04:00
|
|
|
track_canvas_motion (event);
|
2006-06-13 03:27:52 -04:00
|
|
|
// drag_info.last_pointer_frame = drag_info.current_pointer_frame;
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
not_handled:
|
2006-03-07 21:50:53 -05:00
|
|
|
return false;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-10-28 18:19:45 -04:00
|
|
|
Editor::start_grab (GdkEvent* event, Gdk::Cursor *cursor)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
if (drag_info.item == 0) {
|
|
|
|
fatal << _("programming error: start_grab called without drag item") << endmsg;
|
|
|
|
/*NOTREACHED*/
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cursor == 0) {
|
2008-02-16 17:43:18 -05:00
|
|
|
cursor = which_grabber_cursor ();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2007-08-10 16:55:27 -04:00
|
|
|
// if dragging with button2, the motion is x constrained, with Alt-button2 it is y constrained
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (event->button.button == 2) {
|
2008-01-10 16:20:59 -05:00
|
|
|
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::SecondaryModifier)) {
|
2006-04-27 05:04:24 -04:00
|
|
|
drag_info.y_constrained = true;
|
|
|
|
drag_info.x_constrained = false;
|
|
|
|
} else {
|
|
|
|
drag_info.y_constrained = false;
|
|
|
|
drag_info.x_constrained = true;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
|
|
|
drag_info.x_constrained = false;
|
2006-04-27 05:04:24 -04:00
|
|
|
drag_info.y_constrained = false;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2007-05-31 17:15:28 -04:00
|
|
|
drag_info.grab_frame = event_frame (event, &drag_info.grab_x, &drag_info.grab_y);
|
2005-09-25 14:42:24 -04:00
|
|
|
drag_info.last_pointer_frame = drag_info.grab_frame;
|
|
|
|
drag_info.current_pointer_frame = drag_info.grab_frame;
|
|
|
|
drag_info.current_pointer_x = drag_info.grab_x;
|
|
|
|
drag_info.current_pointer_y = drag_info.grab_y;
|
2007-11-05 10:38:19 -05:00
|
|
|
drag_info.last_pointer_x = drag_info.current_pointer_x;
|
|
|
|
drag_info.last_pointer_y = drag_info.current_pointer_y;
|
2005-09-25 14:42:24 -04:00
|
|
|
drag_info.cumulative_x_drag = 0;
|
|
|
|
drag_info.cumulative_y_drag = 0;
|
|
|
|
drag_info.first_move = true;
|
2006-06-13 03:27:52 -04:00
|
|
|
drag_info.move_threshold_passed = false;
|
2005-09-25 14:42:24 -04:00
|
|
|
drag_info.want_move_threshold = false;
|
|
|
|
drag_info.pointer_frame_offset = 0;
|
|
|
|
drag_info.brushing = false;
|
|
|
|
drag_info.copied_location = 0;
|
|
|
|
|
2005-11-12 22:53:51 -05:00
|
|
|
drag_info.item->grab (Gdk::POINTER_MOTION_MASK|Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK,
|
|
|
|
*cursor,
|
|
|
|
event->button.time);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (session && session->transport_rolling()) {
|
|
|
|
drag_info.was_rolling = true;
|
|
|
|
} else {
|
|
|
|
drag_info.was_rolling = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (snap_type) {
|
|
|
|
case SnapToRegionStart:
|
|
|
|
case SnapToRegionEnd:
|
|
|
|
case SnapToRegionSync:
|
|
|
|
case SnapToRegionBoundary:
|
|
|
|
build_region_boundary_cache ();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-06-13 03:27:52 -04:00
|
|
|
void
|
|
|
|
Editor::swap_grab (ArdourCanvas::Item* new_item, Gdk::Cursor* cursor, uint32_t time)
|
|
|
|
{
|
|
|
|
drag_info.item->ungrab (0);
|
|
|
|
drag_info.item = new_item;
|
|
|
|
|
|
|
|
if (cursor == 0) {
|
2008-02-16 17:43:18 -05:00
|
|
|
cursor = which_grabber_cursor ();
|
2006-06-13 03:27:52 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
drag_info.item->grab (Gdk::POINTER_MOTION_MASK|Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK, *cursor, time);
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
bool
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::end_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
bool did_drag = false;
|
|
|
|
|
|
|
|
stop_canvas_autoscroll ();
|
|
|
|
|
|
|
|
if (drag_info.item == 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2005-11-12 22:53:51 -05:00
|
|
|
drag_info.item->ungrab (event->button.time);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (drag_info.finished_callback) {
|
2007-11-05 10:38:19 -05:00
|
|
|
drag_info.last_pointer_x = drag_info.current_pointer_x;
|
|
|
|
drag_info.last_pointer_y = drag_info.current_pointer_y;
|
2005-09-25 14:42:24 -04:00
|
|
|
(this->*(drag_info.finished_callback)) (item, event);
|
|
|
|
}
|
|
|
|
|
|
|
|
did_drag = !drag_info.first_move;
|
|
|
|
|
|
|
|
hide_verbose_canvas_cursor();
|
|
|
|
|
|
|
|
drag_info.item = 0;
|
|
|
|
drag_info.copy = false;
|
|
|
|
drag_info.motion_callback = 0;
|
|
|
|
drag_info.finished_callback = 0;
|
|
|
|
drag_info.last_trackview = 0;
|
|
|
|
drag_info.last_frame_position = 0;
|
|
|
|
drag_info.grab_frame = 0;
|
|
|
|
drag_info.last_pointer_frame = 0;
|
|
|
|
drag_info.current_pointer_frame = 0;
|
|
|
|
drag_info.brushing = false;
|
|
|
|
|
|
|
|
if (drag_info.copied_location) {
|
|
|
|
delete drag_info.copied_location;
|
|
|
|
drag_info.copied_location = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return did_drag;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::start_fade_in_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
drag_info.item = item;
|
|
|
|
drag_info.motion_callback = &Editor::fade_in_drag_motion_callback;
|
|
|
|
drag_info.finished_callback = &Editor::fade_in_drag_finished_callback;
|
|
|
|
|
|
|
|
start_grab (event);
|
|
|
|
|
2005-11-28 17:36:26 -05:00
|
|
|
if ((drag_info.data = (item->get_data ("regionview"))) == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
fatal << _("programming error: fade in canvas item has no regionview data pointer!") << endmsg;
|
|
|
|
/*NOTREACHED*/
|
|
|
|
}
|
|
|
|
|
|
|
|
AudioRegionView* arv = static_cast<AudioRegionView*>(drag_info.data);
|
|
|
|
|
2007-06-29 00:02:58 -04:00
|
|
|
drag_info.pointer_frame_offset = drag_info.grab_frame - ((nframes_t) arv->audio_region()->fade_in()->back()->when + arv->region()->position());
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::fade_in_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
AudioRegionView* arv = static_cast<AudioRegionView*>(drag_info.data);
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t pos;
|
|
|
|
nframes_t fade_length;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-05-29 23:31:49 -04:00
|
|
|
if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) {
|
2005-09-25 14:42:24 -04:00
|
|
|
pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
pos = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
|
|
|
|
snap_to (pos);
|
|
|
|
}
|
2007-01-28 12:44:13 -05:00
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
if (pos < (arv->region()->position() + 64)) {
|
2005-09-25 14:42:24 -04:00
|
|
|
fade_length = 64; // this should be a minimum defined somewhere
|
2006-08-29 17:21:48 -04:00
|
|
|
} else if (pos > arv->region()->last_frame()) {
|
|
|
|
fade_length = arv->region()->length();
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2006-08-29 17:21:48 -04:00
|
|
|
fade_length = pos - arv->region()->position();
|
2007-01-28 12:44:13 -05:00
|
|
|
}
|
|
|
|
/* mapover the region selection */
|
|
|
|
|
|
|
|
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
|
|
|
|
|
|
|
|
AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*i);
|
|
|
|
|
|
|
|
if (!tmp) {
|
|
|
|
continue;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
tmp->reset_fade_in_shape_width (fade_length);
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
show_verbose_duration_cursor (arv->region()->position(), arv->region()->position() + fade_length, 10);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
drag_info.first_move = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::fade_in_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
AudioRegionView* arv = static_cast<AudioRegionView*>(drag_info.data);
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t pos;
|
|
|
|
nframes_t fade_length;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
if (drag_info.first_move) return;
|
|
|
|
|
2007-05-29 23:31:49 -04:00
|
|
|
if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) {
|
2005-09-25 14:42:24 -04:00
|
|
|
pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
|
2007-01-28 12:44:13 -05:00
|
|
|
} else {
|
2005-09-25 14:42:24 -04:00
|
|
|
pos = 0;
|
|
|
|
}
|
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
if (pos < (arv->region()->position() + 64)) {
|
2005-09-25 14:42:24 -04:00
|
|
|
fade_length = 64; // this should be a minimum defined somewhere
|
2007-01-28 12:44:13 -05:00
|
|
|
} else if (pos > arv->region()->last_frame()) {
|
2006-08-29 17:21:48 -04:00
|
|
|
fade_length = arv->region()->length();
|
2007-01-28 12:44:13 -05:00
|
|
|
} else {
|
2006-08-29 17:21:48 -04:00
|
|
|
fade_length = pos - arv->region()->position();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2007-01-28 12:44:13 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
begin_reversible_command (_("change fade in length"));
|
2006-08-09 21:22:45 -04:00
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
|
|
|
|
|
|
|
|
AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*i);
|
|
|
|
|
|
|
|
if (!tmp) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
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_length (fade_length);
|
2008-02-16 17:43:18 -05:00
|
|
|
tmp->audio_region()->set_fade_in_active (true);
|
2007-01-28 12:44:13 -05:00
|
|
|
|
2007-06-29 00:02:58 -04:00
|
|
|
XMLNode &after = alist->get_state();
|
|
|
|
session->add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &after));
|
2007-01-28 12:44:13 -05:00
|
|
|
}
|
2006-08-09 21:22:45 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::start_fade_out_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
drag_info.item = item;
|
|
|
|
drag_info.motion_callback = &Editor::fade_out_drag_motion_callback;
|
|
|
|
drag_info.finished_callback = &Editor::fade_out_drag_finished_callback;
|
|
|
|
|
|
|
|
start_grab (event);
|
|
|
|
|
2005-11-28 17:36:26 -05:00
|
|
|
if ((drag_info.data = (item->get_data ("regionview"))) == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
fatal << _("programming error: fade out canvas item has no regionview data pointer!") << endmsg;
|
|
|
|
/*NOTREACHED*/
|
|
|
|
}
|
|
|
|
|
|
|
|
AudioRegionView* arv = static_cast<AudioRegionView*>(drag_info.data);
|
|
|
|
|
2007-06-29 00:02:58 -04:00
|
|
|
drag_info.pointer_frame_offset = drag_info.grab_frame - (arv->region()->length() - (nframes_t) arv->audio_region()->fade_out()->back()->when + arv->region()->position());
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::fade_out_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
AudioRegionView* arv = static_cast<AudioRegionView*>(drag_info.data);
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t pos;
|
|
|
|
nframes_t fade_length;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-05-31 17:15:28 -04:00
|
|
|
if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) {
|
2005-09-25 14:42:24 -04:00
|
|
|
pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
|
2007-05-31 17:15:28 -04:00
|
|
|
} else {
|
2005-09-25 14:42:24 -04:00
|
|
|
pos = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
|
|
|
|
snap_to (pos);
|
|
|
|
}
|
2007-01-28 12:44:13 -05:00
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
if (pos > (arv->region()->last_frame() - 64)) {
|
2005-09-25 14:42:24 -04:00
|
|
|
fade_length = 64; // this should really be a minimum fade defined somewhere
|
|
|
|
}
|
2006-08-29 17:21:48 -04:00
|
|
|
else if (pos < arv->region()->position()) {
|
|
|
|
fade_length = arv->region()->length();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
else {
|
2006-08-29 17:21:48 -04:00
|
|
|
fade_length = arv->region()->last_frame() - pos;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2007-01-28 12:44:13 -05:00
|
|
|
|
|
|
|
/* mapover the region selection */
|
|
|
|
|
|
|
|
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
|
|
|
|
|
|
|
|
AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*i);
|
|
|
|
|
|
|
|
if (!tmp) {
|
|
|
|
continue;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
tmp->reset_fade_out_shape_width (fade_length);
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
show_verbose_duration_cursor (arv->region()->last_frame() - fade_length, arv->region()->last_frame(), 10);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
drag_info.first_move = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::fade_out_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
if (drag_info.first_move) return;
|
|
|
|
|
|
|
|
AudioRegionView* arv = static_cast<AudioRegionView*>(drag_info.data);
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t pos;
|
|
|
|
nframes_t fade_length;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-05-29 23:31:49 -04:00
|
|
|
if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) {
|
2005-09-25 14:42:24 -04:00
|
|
|
pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
pos = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
|
|
|
|
snap_to (pos);
|
|
|
|
}
|
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
if (pos > (arv->region()->last_frame() - 64)) {
|
2005-09-25 14:42:24 -04:00
|
|
|
fade_length = 64; // this should really be a minimum fade defined somewhere
|
|
|
|
}
|
2006-08-29 17:21:48 -04:00
|
|
|
else if (pos < arv->region()->position()) {
|
|
|
|
fade_length = arv->region()->length();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
else {
|
2006-08-29 17:21:48 -04:00
|
|
|
fade_length = arv->region()->last_frame() - pos;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
begin_reversible_command (_("change fade out length"));
|
2006-08-09 21:22:45 -04:00
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
|
2006-08-09 21:22:45 -04:00
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*i);
|
|
|
|
|
|
|
|
if (!tmp) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
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_length (fade_length);
|
2008-02-16 17:43:18 -05:00
|
|
|
tmp->audio_region()->set_fade_out_active (true);
|
2007-01-28 12:44:13 -05:00
|
|
|
|
2007-06-29 00:02:58 -04:00
|
|
|
XMLNode &after = alist->get_state();
|
|
|
|
session->add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &after));
|
2007-01-28 12:44:13 -05:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
commit_reversible_command ();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::start_cursor_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
drag_info.item = item;
|
|
|
|
drag_info.motion_callback = &Editor::cursor_drag_motion_callback;
|
|
|
|
drag_info.finished_callback = &Editor::cursor_drag_finished_callback;
|
|
|
|
|
|
|
|
start_grab (event);
|
|
|
|
|
2005-11-28 17:36:26 -05:00
|
|
|
if ((drag_info.data = (item->get_data ("cursor"))) == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
fatal << _("programming error: cursor canvas item has no cursor data pointer!") << endmsg;
|
|
|
|
/*NOTREACHED*/
|
|
|
|
}
|
|
|
|
|
|
|
|
Cursor* cursor = (Cursor *) drag_info.data;
|
|
|
|
|
2007-01-09 18:24:54 -05:00
|
|
|
if (cursor == playhead_cursor) {
|
|
|
|
_dragging_playhead = true;
|
|
|
|
|
|
|
|
if (session && drag_info.was_rolling) {
|
2005-09-25 14:42:24 -04:00
|
|
|
session->request_stop ();
|
2007-04-12 19:20:37 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (session && session->is_auditioning()) {
|
|
|
|
session->cancel_audition ();
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
drag_info.pointer_frame_offset = drag_info.grab_frame - cursor->current_frame;
|
|
|
|
|
|
|
|
show_verbose_time_cursor (cursor->current_frame, 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::cursor_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
Cursor* cursor = (Cursor *) drag_info.data;
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t adjusted_frame;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-05-29 23:31:49 -04:00
|
|
|
if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) {
|
2005-09-25 14:42:24 -04:00
|
|
|
adjusted_frame = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
adjusted_frame = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
|
2008-01-10 16:20:59 -05:00
|
|
|
if (cursor == playhead_cursor) {
|
2005-09-25 14:42:24 -04:00
|
|
|
snap_to (adjusted_frame);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (adjusted_frame == drag_info.last_pointer_frame) return;
|
|
|
|
|
|
|
|
cursor->set_position (adjusted_frame);
|
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
UpdateAllTransportClocks (cursor->current_frame);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
show_verbose_time_cursor (cursor->current_frame, 10);
|
|
|
|
|
|
|
|
drag_info.last_pointer_frame = adjusted_frame;
|
|
|
|
drag_info.first_move = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::cursor_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
if (drag_info.first_move) return;
|
|
|
|
|
|
|
|
cursor_drag_motion_callback (item, event);
|
2007-01-09 18:24:54 -05:00
|
|
|
|
|
|
|
_dragging_playhead = false;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2005-11-22 00:10:12 -05:00
|
|
|
if (item == &playhead_cursor->canvas_item) {
|
2005-09-25 14:42:24 -04:00
|
|
|
if (session) {
|
|
|
|
session->request_locate (playhead_cursor->current_frame, drag_info.was_rolling);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::update_marker_drag_item (Location *location)
|
|
|
|
{
|
|
|
|
double x1 = frame_to_pixel (location->start());
|
|
|
|
double x2 = frame_to_pixel (location->end());
|
|
|
|
|
|
|
|
if (location->is_mark()) {
|
2007-08-10 16:55:27 -04:00
|
|
|
marker_drag_line_points.front().set_x(x1);
|
2005-11-25 19:06:46 -05:00
|
|
|
marker_drag_line_points.back().set_x(x1);
|
2005-11-27 17:35:04 -05:00
|
|
|
marker_drag_line->property_points() = marker_drag_line_points;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
else {
|
2005-11-27 17:35:04 -05:00
|
|
|
range_marker_drag_rect->property_x1() = x1;
|
|
|
|
range_marker_drag_rect->property_x2() = x2;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::start_marker_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
Marker* marker;
|
|
|
|
|
2005-11-28 17:36:26 -05:00
|
|
|
if ((marker = static_cast<Marker *> (item->get_data ("marker"))) == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
|
|
|
|
/*NOTREACHED*/
|
|
|
|
}
|
|
|
|
|
|
|
|
bool is_start;
|
|
|
|
|
|
|
|
Location *location = find_location_from_marker (marker, is_start);
|
|
|
|
|
|
|
|
drag_info.item = item;
|
|
|
|
drag_info.data = marker;
|
|
|
|
drag_info.motion_callback = &Editor::marker_drag_motion_callback;
|
|
|
|
drag_info.finished_callback = &Editor::marker_drag_finished_callback;
|
|
|
|
|
|
|
|
start_grab (event);
|
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
_dragging_edit_point = true;
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
drag_info.copied_location = new Location (*location);
|
|
|
|
drag_info.pointer_frame_offset = drag_info.grab_frame - (is_start ? location->start() : location->end());
|
2006-07-13 23:43:32 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
update_marker_drag_item (location);
|
|
|
|
|
|
|
|
if (location->is_mark()) {
|
2007-11-12 17:23:01 -05:00
|
|
|
// marker_drag_line->show();
|
|
|
|
// marker_drag_line->raise_to_top();
|
2007-11-06 21:42:27 -05:00
|
|
|
} else {
|
2005-10-28 18:19:45 -04:00
|
|
|
range_marker_drag_rect->show();
|
|
|
|
range_marker_drag_rect->raise_to_top();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2007-11-06 21:42:27 -05:00
|
|
|
|
|
|
|
if (is_start) {
|
|
|
|
show_verbose_time_cursor (location->start(), 10);
|
|
|
|
} else {
|
|
|
|
show_verbose_time_cursor (location->end(), 10);
|
|
|
|
}
|
2007-11-12 17:23:01 -05:00
|
|
|
|
|
|
|
Selection::Operation op = Keyboard::selection_type (event->button.state);
|
|
|
|
|
|
|
|
switch (op) {
|
|
|
|
case Selection::Toggle:
|
|
|
|
selection->toggle (marker);
|
|
|
|
break;
|
|
|
|
case Selection::Set:
|
|
|
|
selection->set (marker);
|
|
|
|
break;
|
|
|
|
case Selection::Extend:
|
|
|
|
selection->add (marker);
|
|
|
|
break;
|
|
|
|
case Selection::Add:
|
|
|
|
selection->add (marker);
|
|
|
|
break;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t f_delta;
|
2005-09-25 14:42:24 -04:00
|
|
|
Marker* marker = (Marker *) drag_info.data;
|
|
|
|
Location *real_location;
|
|
|
|
Location *copy_location;
|
|
|
|
bool is_start;
|
|
|
|
bool move_both = false;
|
|
|
|
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t newframe;
|
2007-05-29 23:31:49 -04:00
|
|
|
if (drag_info.pointer_frame_offset <= drag_info.current_pointer_frame) {
|
2005-09-25 14:42:24 -04:00
|
|
|
newframe = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
|
2007-05-31 17:15:28 -04:00
|
|
|
} else {
|
2005-09-25 14:42:24 -04:00
|
|
|
newframe = 0;
|
|
|
|
}
|
2006-06-13 03:27:52 -04:00
|
|
|
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t next = newframe;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
|
|
|
|
snap_to (newframe, 0, true);
|
|
|
|
}
|
|
|
|
|
2006-06-13 03:27:52 -04:00
|
|
|
if (drag_info.current_pointer_frame == drag_info.last_pointer_frame) {
|
|
|
|
return;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
/* call this to find out if its the start or end */
|
|
|
|
|
2007-11-12 17:23:01 -05:00
|
|
|
if ((real_location = find_location_from_marker (marker, is_start)) == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (real_location->locked()) {
|
|
|
|
return;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
/* use the copy that we're "dragging" around */
|
|
|
|
|
|
|
|
copy_location = drag_info.copied_location;
|
|
|
|
|
|
|
|
f_delta = copy_location->end() - copy_location->start();
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
|
2005-09-25 14:42:24 -04:00
|
|
|
move_both = true;
|
|
|
|
}
|
|
|
|
|
2006-07-13 23:43:32 -04:00
|
|
|
if (copy_location->is_mark()) {
|
|
|
|
/* just move it */
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-07-13 23:43:32 -04:00
|
|
|
copy_location->set_start (newframe);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-07-13 23:43:32 -04:00
|
|
|
} else {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-07-13 23:43:32 -04:00
|
|
|
if (is_start) { // start-of-range marker
|
|
|
|
|
|
|
|
if (move_both) {
|
|
|
|
copy_location->set_start (newframe);
|
|
|
|
copy_location->set_end (newframe + f_delta);
|
|
|
|
} else if (newframe < copy_location->end()) {
|
|
|
|
copy_location->set_start (newframe);
|
|
|
|
} else {
|
|
|
|
snap_to (next, 1, true);
|
|
|
|
copy_location->set_end (next);
|
|
|
|
copy_location->set_start (newframe);
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-07-13 23:43:32 -04:00
|
|
|
} else { // end marker
|
|
|
|
|
|
|
|
if (move_both) {
|
|
|
|
copy_location->set_end (newframe);
|
|
|
|
copy_location->set_start (newframe - f_delta);
|
|
|
|
} else if (newframe > copy_location->start()) {
|
|
|
|
copy_location->set_end (newframe);
|
|
|
|
|
|
|
|
} else if (newframe > 0) {
|
|
|
|
snap_to (next, -1, true);
|
|
|
|
copy_location->set_start (next);
|
|
|
|
copy_location->set_end (newframe);
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
drag_info.last_pointer_frame = drag_info.current_pointer_frame;
|
|
|
|
drag_info.first_move = false;
|
|
|
|
|
|
|
|
update_marker_drag_item (copy_location);
|
|
|
|
|
|
|
|
LocationMarkers* lm = find_location_markers (real_location);
|
|
|
|
lm->set_position (copy_location->start(), copy_location->end());
|
2007-11-12 17:23:01 -05:00
|
|
|
edit_point_clock.set (copy_location->start());
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
show_verbose_time_cursor (newframe, 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
if (drag_info.first_move) {
|
|
|
|
marker_drag_motion_callback (item, event);
|
|
|
|
|
|
|
|
}
|
2007-11-12 17:23:01 -05:00
|
|
|
|
|
|
|
_dragging_edit_point = false;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
Marker* marker = (Marker *) drag_info.data;
|
|
|
|
bool is_start;
|
2006-03-21 13:40:17 -05:00
|
|
|
|
|
|
|
begin_reversible_command ( _("move marker") );
|
2006-08-09 21:22:45 -04:00
|
|
|
XMLNode &before = session->locations()->get_state();
|
2006-03-21 13:40:17 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
Location * location = find_location_from_marker (marker, is_start);
|
2007-11-12 17:23:01 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (location) {
|
2007-11-12 17:23:01 -05:00
|
|
|
|
|
|
|
if (location->locked()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-07-13 23:43:32 -04:00
|
|
|
if (location->is_mark()) {
|
|
|
|
location->set_start (drag_info.copied_location->start());
|
|
|
|
} else {
|
|
|
|
location->set (drag_info.copied_location->start(), drag_info.copied_location->end());
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2006-03-21 13:40:17 -05:00
|
|
|
|
2006-08-09 21:22:45 -04:00
|
|
|
XMLNode &after = session->locations()->get_state();
|
2006-08-24 03:37:17 -04:00
|
|
|
session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
|
2006-03-21 13:40:17 -05:00
|
|
|
commit_reversible_command ();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2005-10-28 18:19:45 -04:00
|
|
|
marker_drag_line->hide();
|
|
|
|
range_marker_drag_rect->hide();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::start_meter_marker_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
Marker* marker;
|
|
|
|
MeterMarker* meter_marker;
|
|
|
|
|
2005-11-28 17:36:26 -05:00
|
|
|
if ((marker = reinterpret_cast<Marker *> (item->get_data ("marker"))) == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
fatal << _("programming error: meter marker canvas item has no marker object pointer!") << endmsg;
|
|
|
|
/*NOTREACHED*/
|
|
|
|
}
|
|
|
|
|
|
|
|
meter_marker = dynamic_cast<MeterMarker*> (marker);
|
|
|
|
|
|
|
|
MetricSection& section (meter_marker->meter());
|
|
|
|
|
|
|
|
if (!section.movable()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
drag_info.item = item;
|
2007-11-17 16:02:05 -05:00
|
|
|
drag_info.copy = false;
|
2005-09-25 14:42:24 -04:00
|
|
|
drag_info.data = marker;
|
|
|
|
drag_info.motion_callback = &Editor::meter_marker_drag_motion_callback;
|
|
|
|
drag_info.finished_callback = &Editor::meter_marker_drag_finished_callback;
|
|
|
|
|
|
|
|
start_grab (event);
|
|
|
|
|
|
|
|
drag_info.pointer_frame_offset = drag_info.grab_frame - meter_marker->meter().frame();
|
|
|
|
|
|
|
|
show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
|
|
|
|
}
|
|
|
|
|
2006-03-05 14:39:16 -05:00
|
|
|
void
|
|
|
|
Editor::start_meter_marker_copy_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
|
|
|
{
|
|
|
|
Marker* marker;
|
|
|
|
MeterMarker* meter_marker;
|
|
|
|
|
|
|
|
if ((marker = reinterpret_cast<Marker *> (item->get_data ("marker"))) == 0) {
|
|
|
|
fatal << _("programming error: meter marker canvas item has no marker object pointer!") << endmsg;
|
|
|
|
/*NOTREACHED*/
|
|
|
|
}
|
|
|
|
|
|
|
|
meter_marker = dynamic_cast<MeterMarker*> (marker);
|
|
|
|
|
|
|
|
// create a dummy marker for visual representation of moving the copy.
|
|
|
|
// The actual copying is not done before we reach the finish callback.
|
|
|
|
char name[64];
|
|
|
|
snprintf (name, sizeof(name), "%g/%g", meter_marker->meter().beats_per_bar(), meter_marker->meter().note_divisor ());
|
2007-06-29 13:13:09 -04:00
|
|
|
MeterMarker* new_marker = new MeterMarker(*this, *meter_group, ARDOUR_UI::config()->canvasvar_MeterMarker.get(), name,
|
2006-03-05 14:39:16 -05:00
|
|
|
*new MeterSection(meter_marker->meter()));
|
|
|
|
|
|
|
|
drag_info.item = &new_marker->the_item();
|
|
|
|
drag_info.copy = true;
|
|
|
|
drag_info.data = new_marker;
|
|
|
|
drag_info.motion_callback = &Editor::meter_marker_drag_motion_callback;
|
|
|
|
drag_info.finished_callback = &Editor::meter_marker_drag_finished_callback;
|
|
|
|
|
|
|
|
start_grab (event);
|
|
|
|
|
|
|
|
drag_info.pointer_frame_offset = drag_info.grab_frame - meter_marker->meter().frame();
|
|
|
|
|
|
|
|
show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::meter_marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
MeterMarker* marker = (MeterMarker *) drag_info.data;
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t adjusted_frame;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-05-29 23:31:49 -04:00
|
|
|
if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) {
|
2005-09-25 14:42:24 -04:00
|
|
|
adjusted_frame = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
adjusted_frame = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
|
|
|
|
snap_to (adjusted_frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (adjusted_frame == drag_info.last_pointer_frame) return;
|
|
|
|
|
|
|
|
marker->set_position (adjusted_frame);
|
|
|
|
|
|
|
|
|
|
|
|
drag_info.last_pointer_frame = adjusted_frame;
|
|
|
|
drag_info.first_move = false;
|
|
|
|
|
|
|
|
show_verbose_time_cursor (adjusted_frame, 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::meter_marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
if (drag_info.first_move) return;
|
|
|
|
|
2006-03-05 14:39:16 -05:00
|
|
|
meter_marker_drag_motion_callback (drag_info.item, event);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
MeterMarker* marker = (MeterMarker *) drag_info.data;
|
|
|
|
BBT_Time when;
|
|
|
|
|
|
|
|
TempoMap& map (session->tempo_map());
|
|
|
|
map.bbt_time (drag_info.last_pointer_frame, when);
|
|
|
|
|
2006-03-05 14:39:16 -05:00
|
|
|
if (drag_info.copy == true) {
|
|
|
|
begin_reversible_command (_("copy meter mark"));
|
2007-08-10 16:55:27 -04:00
|
|
|
XMLNode &before = map.get_state();
|
2006-03-05 14:39:16 -05:00
|
|
|
map.add_meter (marker->meter(), when);
|
2006-08-09 21:22:45 -04:00
|
|
|
XMLNode &after = map.get_state();
|
2007-08-10 16:55:27 -04:00
|
|
|
session->add_command(new MementoCommand<TempoMap>(map, &before, &after));
|
2006-03-05 14:39:16 -05:00
|
|
|
commit_reversible_command ();
|
2007-08-10 16:55:27 -04:00
|
|
|
|
2006-03-05 14:39:16 -05:00
|
|
|
// delete the dummy marker we used for visual representation of copying.
|
|
|
|
// a new visual marker will show up automatically.
|
|
|
|
delete marker;
|
|
|
|
} else {
|
|
|
|
begin_reversible_command (_("move meter mark"));
|
2006-08-09 21:22:45 -04:00
|
|
|
XMLNode &before = map.get_state();
|
2006-03-05 14:39:16 -05:00
|
|
|
map.move_meter (marker->meter(), when);
|
2006-08-09 21:22:45 -04:00
|
|
|
XMLNode &after = map.get_state();
|
2007-08-10 16:55:27 -04:00
|
|
|
session->add_command(new MementoCommand<TempoMap>(map, &before, &after));
|
2006-03-05 14:39:16 -05:00
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::start_tempo_marker_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
Marker* marker;
|
|
|
|
TempoMarker* tempo_marker;
|
|
|
|
|
2005-12-08 13:53:43 -05:00
|
|
|
if ((marker = reinterpret_cast<Marker *> (item->get_data ("marker"))) == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
fatal << _("programming error: tempo marker canvas item has no marker object pointer!") << endmsg;
|
|
|
|
/*NOTREACHED*/
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((tempo_marker = dynamic_cast<TempoMarker *> (marker)) == 0) {
|
|
|
|
fatal << _("programming error: marker for tempo is not a tempo marker!") << endmsg;
|
|
|
|
/*NOTREACHED*/
|
|
|
|
}
|
|
|
|
|
|
|
|
MetricSection& section (tempo_marker->tempo());
|
|
|
|
|
|
|
|
if (!section.movable()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
drag_info.item = item;
|
2007-11-17 16:02:05 -05:00
|
|
|
drag_info.copy = false;
|
2005-09-25 14:42:24 -04:00
|
|
|
drag_info.data = marker;
|
|
|
|
drag_info.motion_callback = &Editor::tempo_marker_drag_motion_callback;
|
|
|
|
drag_info.finished_callback = &Editor::tempo_marker_drag_finished_callback;
|
|
|
|
|
|
|
|
start_grab (event);
|
|
|
|
|
|
|
|
drag_info.pointer_frame_offset = drag_info.grab_frame - tempo_marker->tempo().frame();
|
|
|
|
show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
|
|
|
|
}
|
|
|
|
|
2006-03-05 14:39:16 -05:00
|
|
|
void
|
|
|
|
Editor::start_tempo_marker_copy_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
|
|
|
{
|
|
|
|
Marker* marker;
|
|
|
|
TempoMarker* tempo_marker;
|
|
|
|
|
|
|
|
if ((marker = reinterpret_cast<Marker *> (item->get_data ("marker"))) == 0) {
|
|
|
|
fatal << _("programming error: tempo marker canvas item has no marker object pointer!") << endmsg;
|
|
|
|
/*NOTREACHED*/
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((tempo_marker = dynamic_cast<TempoMarker *> (marker)) == 0) {
|
|
|
|
fatal << _("programming error: marker for tempo is not a tempo marker!") << endmsg;
|
|
|
|
/*NOTREACHED*/
|
|
|
|
}
|
|
|
|
|
|
|
|
// create a dummy marker for visual representation of moving the copy.
|
|
|
|
// The actual copying is not done before we reach the finish callback.
|
|
|
|
char name[64];
|
|
|
|
snprintf (name, sizeof (name), "%.2f", tempo_marker->tempo().beats_per_minute());
|
2007-06-29 13:13:09 -04:00
|
|
|
TempoMarker* new_marker = new TempoMarker(*this, *tempo_group, ARDOUR_UI::config()->canvasvar_TempoMarker.get(), name,
|
2006-03-05 14:39:16 -05:00
|
|
|
*new TempoSection(tempo_marker->tempo()));
|
|
|
|
|
|
|
|
drag_info.item = &new_marker->the_item();
|
|
|
|
drag_info.copy = true;
|
|
|
|
drag_info.data = new_marker;
|
|
|
|
drag_info.motion_callback = &Editor::tempo_marker_drag_motion_callback;
|
|
|
|
drag_info.finished_callback = &Editor::tempo_marker_drag_finished_callback;
|
|
|
|
|
|
|
|
start_grab (event);
|
|
|
|
|
|
|
|
drag_info.pointer_frame_offset = drag_info.grab_frame - tempo_marker->tempo().frame();
|
|
|
|
|
|
|
|
show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::tempo_marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
TempoMarker* marker = (TempoMarker *) drag_info.data;
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t adjusted_frame;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-05-29 23:31:49 -04:00
|
|
|
if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) {
|
2005-09-25 14:42:24 -04:00
|
|
|
adjusted_frame = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
adjusted_frame = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
|
|
|
|
snap_to (adjusted_frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (adjusted_frame == drag_info.last_pointer_frame) return;
|
|
|
|
|
|
|
|
/* OK, we've moved far enough to make it worth actually move the thing. */
|
|
|
|
|
|
|
|
marker->set_position (adjusted_frame);
|
|
|
|
|
|
|
|
show_verbose_time_cursor (adjusted_frame, 10);
|
|
|
|
|
|
|
|
drag_info.last_pointer_frame = adjusted_frame;
|
|
|
|
drag_info.first_move = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::tempo_marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
if (drag_info.first_move) return;
|
|
|
|
|
2006-03-05 14:39:16 -05:00
|
|
|
tempo_marker_drag_motion_callback (drag_info.item, event);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
TempoMarker* marker = (TempoMarker *) drag_info.data;
|
|
|
|
BBT_Time when;
|
|
|
|
|
|
|
|
TempoMap& map (session->tempo_map());
|
|
|
|
map.bbt_time (drag_info.last_pointer_frame, when);
|
2006-08-09 21:22:45 -04:00
|
|
|
|
2006-03-05 14:39:16 -05:00
|
|
|
if (drag_info.copy == true) {
|
|
|
|
begin_reversible_command (_("copy tempo mark"));
|
2006-08-09 21:22:45 -04:00
|
|
|
XMLNode &before = map.get_state();
|
2006-03-05 14:39:16 -05:00
|
|
|
map.add_tempo (marker->tempo(), when);
|
2006-08-09 21:22:45 -04:00
|
|
|
XMLNode &after = map.get_state();
|
2006-08-24 03:37:17 -04:00
|
|
|
session->add_command (new MementoCommand<TempoMap>(map, &before, &after));
|
2006-03-05 14:39:16 -05:00
|
|
|
commit_reversible_command ();
|
|
|
|
|
|
|
|
// delete the dummy marker we used for visual representation of copying.
|
|
|
|
// a new visual marker will show up automatically.
|
|
|
|
delete marker;
|
|
|
|
} else {
|
|
|
|
begin_reversible_command (_("move tempo mark"));
|
2007-08-10 16:55:27 -04:00
|
|
|
XMLNode &before = map.get_state();
|
2006-03-05 14:39:16 -05:00
|
|
|
map.move_tempo (marker->tempo(), when);
|
2007-08-10 16:55:27 -04:00
|
|
|
XMLNode &after = map.get_state();
|
|
|
|
session->add_command (new MementoCommand<TempoMap>(map, &before, &after));
|
2006-03-05 14:39:16 -05:00
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::remove_gain_control_point (ArdourCanvas::Item*item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
ControlPoint* control_point;
|
|
|
|
|
2005-11-28 17:36:26 -05:00
|
|
|
if ((control_point = reinterpret_cast<ControlPoint *> (item->get_data ("control_point"))) == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
fatal << _("programming error: control point canvas item has no control point object pointer!") << endmsg;
|
|
|
|
/*NOTREACHED*/
|
|
|
|
}
|
|
|
|
|
|
|
|
// We shouldn't remove the first or last gain point
|
2007-07-06 23:19:04 -04:00
|
|
|
if (control_point->line().is_last_point(*control_point) ||
|
|
|
|
control_point->line().is_first_point(*control_point)) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-07-06 23:19:04 -04:00
|
|
|
control_point->line().remove_point (*control_point);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-07-06 23:19:04 -04:00
|
|
|
Editor::remove_control_point (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
ControlPoint* control_point;
|
|
|
|
|
2005-11-28 17:36:26 -05:00
|
|
|
if ((control_point = reinterpret_cast<ControlPoint *> (item->get_data ("control_point"))) == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
fatal << _("programming error: control point canvas item has no control point object pointer!") << endmsg;
|
|
|
|
/*NOTREACHED*/
|
|
|
|
}
|
|
|
|
|
2007-07-06 23:19:04 -04:00
|
|
|
control_point->line().remove_point (*control_point);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::start_control_point_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
ControlPoint* control_point;
|
2007-05-17 06:41:14 -04:00
|
|
|
|
2005-11-28 17:36:26 -05:00
|
|
|
if ((control_point = reinterpret_cast<ControlPoint *> (item->get_data ("control_point"))) == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
fatal << _("programming error: control point canvas item has no control point object pointer!") << endmsg;
|
|
|
|
/*NOTREACHED*/
|
|
|
|
}
|
|
|
|
|
|
|
|
drag_info.item = item;
|
|
|
|
drag_info.data = control_point;
|
|
|
|
drag_info.motion_callback = &Editor::control_point_drag_motion_callback;
|
|
|
|
drag_info.finished_callback = &Editor::control_point_drag_finished_callback;
|
|
|
|
|
|
|
|
start_grab (event, fader_cursor);
|
|
|
|
|
2007-11-06 08:33:39 -05:00
|
|
|
// start the grab at the center of the control point so
|
|
|
|
// the point doesn't 'jump' to the mouse after the first drag
|
|
|
|
drag_info.grab_x = control_point->get_x();
|
|
|
|
drag_info.grab_y = control_point->get_y();
|
|
|
|
control_point->line().parent_group().i2w(drag_info.grab_x, drag_info.grab_y);
|
2007-11-07 20:40:25 -05:00
|
|
|
track_canvas.w2c(drag_info.grab_x, drag_info.grab_y, drag_info.grab_x, drag_info.grab_y);
|
2007-11-06 08:33:39 -05:00
|
|
|
|
|
|
|
drag_info.grab_frame = pixel_to_frame(drag_info.grab_x);
|
|
|
|
|
2007-07-06 23:19:04 -04:00
|
|
|
control_point->line().start_drag (control_point, drag_info.grab_frame, 0);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-07-06 23:19:04 -04:00
|
|
|
double fraction = 1.0 - ((control_point->get_y() - control_point->line().y_position()) / (double)control_point->line().height());
|
|
|
|
set_verbose_canvas_cursor (control_point->line().get_verbose_cursor_string (fraction),
|
2005-09-25 14:42:24 -04:00
|
|
|
drag_info.current_pointer_x + 20, drag_info.current_pointer_y + 20);
|
|
|
|
|
|
|
|
show_verbose_canvas_cursor ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::control_point_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
ControlPoint* cp = reinterpret_cast<ControlPoint *> (drag_info.data);
|
|
|
|
|
2007-11-05 10:38:19 -05:00
|
|
|
double dx = drag_info.current_pointer_x - drag_info.last_pointer_x;
|
|
|
|
double dy = drag_info.current_pointer_y - drag_info.last_pointer_y;
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (event->button.state & Keyboard::SecondaryModifier) {
|
2007-11-05 10:38:19 -05:00
|
|
|
dx *= 0.1;
|
|
|
|
dy *= 0.1;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-11-05 10:38:19 -05:00
|
|
|
double cx = drag_info.grab_x + drag_info.cumulative_x_drag + dx;
|
|
|
|
double cy = drag_info.grab_y + drag_info.cumulative_y_drag + dy;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-11-06 08:33:39 -05:00
|
|
|
// calculate zero crossing point. back off by .01 to stay on the
|
|
|
|
// positive side of zero
|
|
|
|
double _unused = 0;
|
|
|
|
double zero_gain_y = (1.0 - ZERO_GAIN_FRACTION) * cp->line().height() - .01;
|
|
|
|
cp->line().parent_group().i2w(_unused, zero_gain_y);
|
|
|
|
|
|
|
|
// make sure we hit zero when passing through
|
|
|
|
if ((cy < zero_gain_y and (cy - dy) > zero_gain_y)
|
|
|
|
or (cy > zero_gain_y and (cy - dy) < zero_gain_y)) {
|
|
|
|
cy = zero_gain_y;
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (drag_info.x_constrained) {
|
2006-04-27 05:04:24 -04:00
|
|
|
cx = drag_info.grab_x;
|
|
|
|
}
|
|
|
|
if (drag_info.y_constrained) {
|
|
|
|
cy = drag_info.grab_y;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-11-05 10:38:19 -05:00
|
|
|
drag_info.cumulative_x_drag = cx - drag_info.grab_x;
|
|
|
|
drag_info.cumulative_y_drag = cy - drag_info.grab_y;
|
|
|
|
|
2007-07-06 23:19:04 -04:00
|
|
|
cp->line().parent_group().w2i (cx, cy);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
cx = max (0.0, cx);
|
|
|
|
cy = max (0.0, cy);
|
2007-07-06 23:19:04 -04:00
|
|
|
cy = min ((double) (cp->line().y_position() + cp->line().height()), cy);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
//translate cx to frames
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t cx_frames = unit_to_frame (cx);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-04-27 05:04:24 -04:00
|
|
|
if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier()) && !drag_info.x_constrained) {
|
2005-09-25 14:42:24 -04:00
|
|
|
snap_to (cx_frames);
|
|
|
|
}
|
|
|
|
|
2007-07-06 23:19:04 -04:00
|
|
|
const double fraction = 1.0 - ((cy - cp->line().y_position()) / (double)cp->line().height());
|
2007-05-17 06:41:14 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
bool push;
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::PrimaryModifier)) {
|
2005-09-25 14:42:24 -04:00
|
|
|
push = true;
|
|
|
|
} else {
|
|
|
|
push = false;
|
|
|
|
}
|
|
|
|
|
2007-07-06 23:19:04 -04:00
|
|
|
cp->line().point_drag (*cp, cx_frames , fraction, push);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-07-06 23:19:04 -04:00
|
|
|
set_verbose_canvas_cursor_text (cp->line().get_verbose_cursor_string (fraction));
|
2006-05-19 16:10:35 -04:00
|
|
|
|
|
|
|
drag_info.first_move = false;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::control_point_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
ControlPoint* cp = reinterpret_cast<ControlPoint *> (drag_info.data);
|
2006-05-19 16:10:35 -04:00
|
|
|
|
|
|
|
if (drag_info.first_move) {
|
|
|
|
|
|
|
|
/* just a click */
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if ((event->type == GDK_BUTTON_RELEASE) && (event->button.button == 1) && Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
|
2006-05-19 16:10:35 -04:00
|
|
|
reset_point_selection ();
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
control_point_drag_motion_callback (item, event);
|
|
|
|
}
|
2007-07-06 23:19:04 -04:00
|
|
|
cp->line().end_drag (cp);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::start_line_grab_from_regionview (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
switch (mouse_mode) {
|
|
|
|
case MouseGain:
|
2006-07-23 08:03:19 -04:00
|
|
|
assert(dynamic_cast<AudioRegionView*>(clicked_regionview));
|
|
|
|
start_line_grab (dynamic_cast<AudioRegionView*>(clicked_regionview)->get_gain_line(), event);
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::start_line_grab_from_line (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
AutomationLine* al;
|
|
|
|
|
2005-11-28 17:36:26 -05:00
|
|
|
if ((al = reinterpret_cast<AutomationLine*> (item->get_data ("line"))) == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
fatal << _("programming error: line canvas item has no line pointer!") << endmsg;
|
|
|
|
/*NOTREACHED*/
|
|
|
|
}
|
|
|
|
|
|
|
|
start_line_grab (al, event);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::start_line_grab (AutomationLine* line, GdkEvent* event)
|
|
|
|
{
|
|
|
|
double cx;
|
|
|
|
double cy;
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t frame_within_region;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
/* need to get x coordinate in terms of parent (TimeAxisItemView)
|
|
|
|
origin.
|
|
|
|
*/
|
|
|
|
|
|
|
|
cx = event->button.x;
|
|
|
|
cy = event->button.y;
|
2005-11-22 00:10:12 -05:00
|
|
|
line->parent_group().w2i (cx, cy);
|
2006-10-21 15:01:50 -04:00
|
|
|
frame_within_region = (nframes_t) floor (cx * frames_per_unit);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (!line->control_points_adjacent (frame_within_region, current_line_drag_info.before,
|
|
|
|
current_line_drag_info.after)) {
|
|
|
|
/* no adjacent points */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-11-22 00:10:12 -05:00
|
|
|
drag_info.item = &line->grab_item();
|
2005-09-25 14:42:24 -04:00
|
|
|
drag_info.data = line;
|
|
|
|
drag_info.motion_callback = &Editor::line_drag_motion_callback;
|
|
|
|
drag_info.finished_callback = &Editor::line_drag_finished_callback;
|
|
|
|
|
|
|
|
start_grab (event, fader_cursor);
|
|
|
|
|
2007-07-04 18:57:13 -04:00
|
|
|
const double fraction = 1.0 - ((cy - line->y_position()) / (double)line->height());
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-01-09 18:24:54 -05:00
|
|
|
line->start_drag (0, drag_info.grab_frame, fraction);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
set_verbose_canvas_cursor (line->get_verbose_cursor_string (fraction),
|
|
|
|
drag_info.current_pointer_x + 20, drag_info.current_pointer_y + 20);
|
|
|
|
show_verbose_canvas_cursor ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::line_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
AutomationLine* line = reinterpret_cast<AutomationLine *> (drag_info.data);
|
2007-11-05 10:38:19 -05:00
|
|
|
|
|
|
|
double dy = drag_info.current_pointer_y - drag_info.last_pointer_y;
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (event->button.state & Keyboard::SecondaryModifier) {
|
2007-11-05 10:38:19 -05:00
|
|
|
dy *= 0.1;
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
double cx = drag_info.current_pointer_x;
|
2007-11-05 10:38:19 -05:00
|
|
|
double cy = drag_info.grab_y + drag_info.cumulative_y_drag + dy;
|
|
|
|
|
2007-11-06 08:33:39 -05:00
|
|
|
// calculate zero crossing point. back off by .01 to stay on the
|
|
|
|
// positive side of zero
|
|
|
|
double _unused = 0;
|
|
|
|
double zero_gain_y = (1.0 - ZERO_GAIN_FRACTION) * line->height() - .01;
|
|
|
|
line->parent_group().i2w(_unused, zero_gain_y);
|
|
|
|
|
|
|
|
// make sure we hit zero when passing through
|
|
|
|
if ((cy < zero_gain_y and (cy - dy) > zero_gain_y)
|
|
|
|
or (cy > zero_gain_y and (cy - dy) < zero_gain_y)) {
|
|
|
|
cy = zero_gain_y;
|
|
|
|
}
|
|
|
|
|
2007-11-05 10:38:19 -05:00
|
|
|
drag_info.cumulative_y_drag = cy - drag_info.grab_y;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2005-11-22 00:10:12 -05:00
|
|
|
line->parent_group().w2i (cx, cy);
|
2007-11-05 10:38:19 -05:00
|
|
|
|
|
|
|
cy = max (0.0, cy);
|
|
|
|
cy = min ((double) line->height(), cy);
|
|
|
|
|
2007-07-04 18:57:13 -04:00
|
|
|
const double fraction = 1.0 - ((cy - line->y_position()) / (double)line->height());
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
bool push;
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::PrimaryModifier)) {
|
2005-09-25 14:42:24 -04:00
|
|
|
push = false;
|
|
|
|
} else {
|
|
|
|
push = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
line->line_drag (current_line_drag_info.before, current_line_drag_info.after, fraction, push);
|
|
|
|
|
|
|
|
set_verbose_canvas_cursor_text (line->get_verbose_cursor_string (fraction));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::line_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
AutomationLine* line = reinterpret_cast<AutomationLine *> (drag_info.data);
|
|
|
|
line_drag_motion_callback (item, event);
|
|
|
|
line->end_drag (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2006-07-23 08:03:19 -04:00
|
|
|
if (selection->regions.empty() || clicked_regionview == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
drag_info.copy = false;
|
|
|
|
drag_info.item = item;
|
|
|
|
drag_info.data = clicked_regionview;
|
2008-01-10 16:20:59 -05:00
|
|
|
|
|
|
|
if (Config->get_edit_mode() == Splice) {
|
|
|
|
drag_info.motion_callback = &Editor::region_drag_splice_motion_callback;
|
|
|
|
drag_info.finished_callback = &Editor::region_drag_splice_finished_callback;
|
|
|
|
} else {
|
|
|
|
drag_info.motion_callback = &Editor::region_drag_motion_callback;
|
|
|
|
drag_info.finished_callback = &Editor::region_drag_finished_callback;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
start_grab (event);
|
|
|
|
|
|
|
|
double speed = 1.0;
|
2006-08-16 16:36:14 -04:00
|
|
|
TimeAxisView* tvp = clicked_axisview;
|
2006-07-23 08:03:19 -04:00
|
|
|
RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-08-14 04:44:14 -04:00
|
|
|
if (tv && tv->is_track()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
speed = tv->get_diskstream()->speed();
|
|
|
|
}
|
|
|
|
|
2006-10-21 15:01:50 -04:00
|
|
|
drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed);
|
2005-09-25 14:42:24 -04:00
|
|
|
drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
|
|
|
|
drag_info.last_trackview = &clicked_regionview->get_time_axis_view();
|
|
|
|
// we want a move threshold
|
|
|
|
drag_info.want_move_threshold = true;
|
|
|
|
|
|
|
|
show_verbose_time_cursor (drag_info.last_frame_position, 10);
|
|
|
|
|
|
|
|
begin_reversible_command (_("move region(s)"));
|
|
|
|
}
|
|
|
|
|
2007-10-14 01:45:31 -04:00
|
|
|
void
|
|
|
|
Editor::start_create_region_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
|
|
|
{
|
|
|
|
drag_info.copy = false;
|
|
|
|
drag_info.item = item;
|
|
|
|
drag_info.data = clicked_axisview;
|
|
|
|
drag_info.last_trackview = clicked_axisview;
|
|
|
|
drag_info.motion_callback = &Editor::create_region_drag_motion_callback;
|
|
|
|
drag_info.finished_callback = &Editor::create_region_drag_finished_callback;
|
|
|
|
|
|
|
|
start_grab (event);
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2006-07-23 08:03:19 -04:00
|
|
|
if (selection->regions.empty() || clicked_regionview == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
drag_info.copy = true;
|
2006-06-13 03:27:52 -04:00
|
|
|
drag_info.item = item;
|
|
|
|
drag_info.data = clicked_regionview;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
start_grab(event);
|
|
|
|
|
|
|
|
TimeAxisView* tv = &clicked_regionview->get_time_axis_view();
|
2006-08-14 04:44:14 -04:00
|
|
|
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(tv);
|
2005-09-25 14:42:24 -04:00
|
|
|
double speed = 1.0;
|
|
|
|
|
2006-08-14 04:44:14 -04:00
|
|
|
if (rtv && rtv->is_track()) {
|
|
|
|
speed = rtv->get_diskstream()->speed();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
drag_info.last_trackview = &clicked_regionview->get_time_axis_view();
|
2006-10-21 15:01:50 -04:00
|
|
|
drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed);
|
2005-09-25 14:42:24 -04:00
|
|
|
drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
|
|
|
|
// we want a move threshold
|
|
|
|
drag_info.want_move_threshold = true;
|
2006-06-13 03:27:52 -04:00
|
|
|
drag_info.motion_callback = &Editor::region_drag_motion_callback;
|
|
|
|
drag_info.finished_callback = &Editor::region_drag_finished_callback;
|
2007-01-09 18:24:54 -05:00
|
|
|
show_verbose_time_cursor (drag_info.last_frame_position, 10);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::start_region_brush_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2008-01-10 16:20:59 -05:00
|
|
|
if (selection->regions.empty() || clicked_regionview == 0 || Config->get_edit_mode() == Splice) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
drag_info.copy = false;
|
|
|
|
drag_info.item = item;
|
|
|
|
drag_info.data = clicked_regionview;
|
|
|
|
drag_info.motion_callback = &Editor::region_drag_motion_callback;
|
|
|
|
drag_info.finished_callback = &Editor::region_drag_finished_callback;
|
|
|
|
|
|
|
|
start_grab (event);
|
|
|
|
|
|
|
|
double speed = 1.0;
|
2006-08-16 16:36:14 -04:00
|
|
|
TimeAxisView* tvp = clicked_axisview;
|
2006-07-23 08:03:19 -04:00
|
|
|
RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-08-14 04:44:14 -04:00
|
|
|
if (tv && tv->is_track()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
speed = tv->get_diskstream()->speed();
|
|
|
|
}
|
|
|
|
|
2006-10-21 15:01:50 -04:00
|
|
|
drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed);
|
2005-09-25 14:42:24 -04:00
|
|
|
drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
|
|
|
|
drag_info.last_trackview = &clicked_regionview->get_time_axis_view();
|
|
|
|
// we want a move threshold
|
|
|
|
drag_info.want_move_threshold = true;
|
|
|
|
drag_info.brushing = true;
|
|
|
|
|
|
|
|
begin_reversible_command (_("Drag region brush"));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-01-10 16:20:59 -05:00
|
|
|
Editor::possibly_copy_regions_during_grab (GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2006-06-13 03:27:52 -04:00
|
|
|
if (drag_info.copy && drag_info.move_threshold_passed && drag_info.want_move_threshold) {
|
|
|
|
|
|
|
|
drag_info.want_move_threshold = false; // don't copy again
|
|
|
|
|
|
|
|
/* duplicate the region(s) */
|
2007-04-29 13:23:11 -04:00
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
vector<RegionView*> new_regionviews;
|
2006-06-13 03:27:52 -04:00
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
|
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
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
RegionView* rv;
|
2007-03-18 02:07:08 -04:00
|
|
|
RegionView* nrv;
|
|
|
|
|
2006-06-13 03:27:52 -04:00
|
|
|
rv = (*i);
|
2007-01-15 13:33:54 -05:00
|
|
|
|
2007-05-07 10:13:25 -04:00
|
|
|
AudioRegionView* arv = dynamic_cast<AudioRegionView*>(rv);
|
|
|
|
MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(rv);
|
|
|
|
|
|
|
|
if (arv) {
|
2007-03-18 02:07:08 -04:00
|
|
|
nrv = new AudioRegionView (*arv);
|
2007-05-07 10:13:25 -04:00
|
|
|
} else if (mrv) {
|
2007-03-18 02:07:08 -04:00
|
|
|
nrv = new MidiRegionView (*mrv);
|
2007-05-07 10:13:25 -04:00
|
|
|
} else {
|
2007-03-18 02:07:08 -04:00
|
|
|
continue;
|
2007-05-07 10:13:25 -04:00
|
|
|
}
|
2006-08-29 17:21:48 -04:00
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
nrv->get_canvas_group()->show ();
|
2006-07-23 08:03:19 -04:00
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
new_regionviews.push_back (nrv);
|
2006-06-13 03:27:52 -04:00
|
|
|
}
|
2007-01-09 18:24:54 -05:00
|
|
|
|
2006-06-13 03:27:52 -04:00
|
|
|
if (new_regionviews.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
2007-03-18 02:07:08 -04:00
|
|
|
|
2006-06-13 03:27:52 -04:00
|
|
|
/* reset selection to new regionviews */
|
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
|
|
|
|
2006-06-13 03:27:52 -04:00
|
|
|
selection->set (new_regionviews);
|
2008-01-15 12:23:57 -05:00
|
|
|
|
2006-06-13 03:27:52 -04:00
|
|
|
/* reset drag_info data to reflect the fact that we are dragging the copies */
|
|
|
|
|
|
|
|
drag_info.data = new_regionviews.front();
|
2007-04-29 13:23:11 -04:00
|
|
|
|
2006-06-13 03:27:52 -04:00
|
|
|
swap_grab (new_regionviews.front()->get_canvas_group (), 0, event->motion.time);
|
|
|
|
}
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
2006-06-13 03:27:52 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
bool
|
|
|
|
Editor::check_region_drag_possible (RouteTimeAxisView** tv)
|
|
|
|
{
|
2005-09-25 14:42:24 -04:00
|
|
|
/* Which trackview is this ? */
|
|
|
|
|
|
|
|
TimeAxisView* tvp = trackview_by_y_position (drag_info.current_pointer_y);
|
2008-01-10 16:20:59 -05:00
|
|
|
(*tv) = dynamic_cast<RouteTimeAxisView*>(tvp);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
/* The region motion is only processed if the pointer is over
|
|
|
|
an audio track.
|
|
|
|
*/
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (!(*tv) || !(*tv)->is_track()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
/* To make sure we hide the verbose canvas cursor when the mouse is
|
2008-01-10 16:20:59 -05:00
|
|
|
not held over and audiotrack.
|
2005-09-25 14:42:24 -04:00
|
|
|
*/
|
|
|
|
hide_verbose_canvas_cursor ();
|
2008-01-10 16:20:59 -05:00
|
|
|
return false;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct RegionSelectionByPosition {
|
|
|
|
bool operator() (RegionView*a, RegionView* b) {
|
|
|
|
return a->region()->position () < b->region()->position();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::region_drag_splice_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
|
|
|
{
|
|
|
|
RouteTimeAxisView* tv;
|
|
|
|
|
|
|
|
if (!check_region_drag_possible (&tv)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!drag_info.move_threshold_passed) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int dir;
|
|
|
|
|
|
|
|
if (drag_info.current_pointer_x - drag_info.grab_x > 0) {
|
|
|
|
dir = 1;
|
|
|
|
} else {
|
|
|
|
dir = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
RegionSelection copy (selection->regions);
|
|
|
|
|
|
|
|
RegionSelectionByPosition cmp;
|
|
|
|
copy.sort (cmp);
|
|
|
|
|
|
|
|
for (RegionSelection::iterator i = copy.begin(); i != copy.end(); ++i) {
|
|
|
|
|
|
|
|
RouteTimeAxisView* atv = dynamic_cast<RouteTimeAxisView*> (&(*i)->get_time_axis_view());
|
|
|
|
|
|
|
|
if (!atv) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
boost::shared_ptr<Playlist> playlist;
|
|
|
|
|
|
|
|
if ((playlist = atv->playlist()) == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!playlist->region_is_shuffle_constrained ((*i)->region())) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dir > 0) {
|
|
|
|
if (drag_info.current_pointer_frame < (*i)->region()->last_frame() + 1) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (drag_info.current_pointer_frame > (*i)->region()->first_frame()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
playlist->shuffle ((*i)->region(), dir);
|
|
|
|
|
|
|
|
drag_info.grab_x = drag_info.current_pointer_x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::region_drag_splice_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
|
|
|
{
|
|
|
|
double x_delta;
|
|
|
|
double y_delta = 0;
|
|
|
|
RegionView* rv = reinterpret_cast<RegionView*> (drag_info.data);
|
|
|
|
nframes_t pending_region_position = 0;
|
|
|
|
int32_t pointer_y_span = 0, canvas_pointer_y_span = 0, original_pointer_order;
|
|
|
|
int32_t visible_y_high = 0, visible_y_low = 512; //high meaning higher numbered.. not the height on the screen
|
|
|
|
bool clamp_y_axis = false;
|
|
|
|
vector<int32_t> height_list(512) ;
|
|
|
|
vector<int32_t>::iterator j;
|
|
|
|
RouteTimeAxisView* tv;
|
|
|
|
|
|
|
|
possibly_copy_regions_during_grab (event);
|
|
|
|
|
|
|
|
if (!check_region_drag_possible (&tv)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
original_pointer_order = drag_info.last_trackview->order;
|
|
|
|
|
|
|
|
/************************************************************
|
2007-08-10 16:55:27 -04:00
|
|
|
Y-Delta Computation
|
2005-09-25 14:42:24 -04:00
|
|
|
************************************************************/
|
|
|
|
|
|
|
|
if (drag_info.brushing) {
|
|
|
|
clamp_y_axis = true;
|
|
|
|
pointer_y_span = 0;
|
|
|
|
goto y_axis_done;
|
|
|
|
}
|
2008-01-10 16:20:59 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if ((pointer_y_span = (drag_info.last_trackview->order - tv->order)) != 0) {
|
|
|
|
|
|
|
|
int32_t children = 0, numtracks = 0;
|
2006-01-03 00:40:21 -05:00
|
|
|
// XXX hard coding track limit, oh my, so very very bad
|
|
|
|
bitset <1024> tracks (0x00);
|
2005-09-25 14:42:24 -04:00
|
|
|
/* get a bitmask representing the visible tracks */
|
|
|
|
|
|
|
|
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
|
|
|
TimeAxisView *tracklist_timeview;
|
|
|
|
tracklist_timeview = (*i);
|
2006-08-14 04:44:14 -04:00
|
|
|
RouteTimeAxisView* rtv2 = dynamic_cast<RouteTimeAxisView*>(tracklist_timeview);
|
2007-06-30 14:41:50 -04:00
|
|
|
TimeAxisView::Children children_list;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
/* zeroes are audio tracks. ones are other types. */
|
|
|
|
|
2006-08-14 04:44:14 -04:00
|
|
|
if (!rtv2->hidden()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-08-14 04:44:14 -04:00
|
|
|
if (visible_y_high < rtv2->order) {
|
|
|
|
visible_y_high = rtv2->order;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2006-08-14 04:44:14 -04:00
|
|
|
if (visible_y_low > rtv2->order) {
|
|
|
|
visible_y_low = rtv2->order;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2006-08-14 04:44:14 -04:00
|
|
|
if (!rtv2->is_track()) {
|
|
|
|
tracks = tracks |= (0x01 << rtv2->order);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2006-08-14 04:44:14 -04:00
|
|
|
height_list[rtv2->order] = (*i)->height;
|
2005-09-25 14:42:24 -04:00
|
|
|
children = 1;
|
2006-08-14 04:44:14 -04:00
|
|
|
if ((children_list = rtv2->get_child_list()).size() > 0) {
|
2007-06-30 14:41:50 -04:00
|
|
|
for (TimeAxisView::Children::iterator j = children_list.begin(); j != children_list.end(); ++j) {
|
2006-08-14 04:44:14 -04:00
|
|
|
tracks = tracks |= (0x01 << (rtv2->order + children));
|
|
|
|
height_list[rtv2->order + children] = (*j)->height;
|
2005-09-25 14:42:24 -04:00
|
|
|
numtracks++;
|
|
|
|
children++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
numtracks++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* find the actual span according to the canvas */
|
|
|
|
|
|
|
|
canvas_pointer_y_span = pointer_y_span;
|
|
|
|
if (drag_info.last_trackview->order >= tv->order) {
|
|
|
|
int32_t y;
|
|
|
|
for (y = tv->order; y < drag_info.last_trackview->order; y++) {
|
|
|
|
if (height_list[y] == 0 ) {
|
|
|
|
canvas_pointer_y_span--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
int32_t y;
|
|
|
|
for (y = drag_info.last_trackview->order;y <= tv->order; y++) {
|
|
|
|
if ( height_list[y] == 0 ) {
|
|
|
|
canvas_pointer_y_span++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
|
|
|
|
RegionView* rv2 = (*i);
|
2005-09-25 14:42:24 -04:00
|
|
|
double ix1, ix2, iy1, iy2;
|
|
|
|
int32_t n = 0;
|
|
|
|
|
2005-11-12 22:53:51 -05:00
|
|
|
rv2->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
|
|
|
|
rv2->get_canvas_group()->i2w (ix1, iy1);
|
2005-09-25 14:42:24 -04:00
|
|
|
TimeAxisView* tvp2 = trackview_by_y_position (iy1);
|
2006-08-14 04:44:14 -04:00
|
|
|
RouteTimeAxisView* rtv2 = dynamic_cast<RouteTimeAxisView*>(tvp2);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-08-14 04:44:14 -04:00
|
|
|
if (rtv2->order != original_pointer_order) {
|
2005-09-25 14:42:24 -04:00
|
|
|
/* this isn't the pointer track */
|
|
|
|
|
|
|
|
if (canvas_pointer_y_span > 0) {
|
|
|
|
|
|
|
|
/* moving up the canvas */
|
2006-08-14 04:44:14 -04:00
|
|
|
if ((rtv2->order - canvas_pointer_y_span) >= visible_y_low) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
int32_t visible_tracks = 0;
|
|
|
|
while (visible_tracks < canvas_pointer_y_span ) {
|
|
|
|
visible_tracks++;
|
|
|
|
|
2006-08-14 04:44:14 -04:00
|
|
|
while (height_list[rtv2->order - (visible_tracks - n)] == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
/* we're passing through a hidden track */
|
|
|
|
n--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-14 04:44:14 -04:00
|
|
|
if (tracks[rtv2->order - (canvas_pointer_y_span - n)] != 0x00) {
|
2005-09-25 14:42:24 -04:00
|
|
|
clamp_y_axis = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
clamp_y_axis = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (canvas_pointer_y_span < 0) {
|
|
|
|
|
|
|
|
/*moving down the canvas*/
|
|
|
|
|
2006-08-14 04:44:14 -04:00
|
|
|
if ((rtv2->order - (canvas_pointer_y_span - n)) <= visible_y_high) { // we will overflow
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
|
|
|
|
int32_t visible_tracks = 0;
|
|
|
|
|
|
|
|
while (visible_tracks > canvas_pointer_y_span ) {
|
|
|
|
visible_tracks--;
|
|
|
|
|
2006-08-14 04:44:14 -04:00
|
|
|
while (height_list[rtv2->order - (visible_tracks - n)] == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
n++;
|
|
|
|
}
|
|
|
|
}
|
2006-08-14 04:44:14 -04:00
|
|
|
if ( tracks[rtv2->order - ( canvas_pointer_y_span - n)] != 0x00) {
|
2005-09-25 14:42:24 -04:00
|
|
|
clamp_y_axis = true;
|
|
|
|
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
|
|
|
|
clamp_y_axis = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
/* this is the pointer's track */
|
2006-08-14 04:44:14 -04:00
|
|
|
if ((rtv2->order - pointer_y_span) > visible_y_high) { // we will overflow
|
2005-09-25 14:42:24 -04:00
|
|
|
clamp_y_axis = true;
|
2006-08-14 04:44:14 -04:00
|
|
|
} else if ((rtv2->order - pointer_y_span) < visible_y_low) { // we will underflow
|
2005-09-25 14:42:24 -04:00
|
|
|
clamp_y_axis = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (clamp_y_axis) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (drag_info.last_trackview == tv) {
|
|
|
|
clamp_y_axis = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
y_axis_done:
|
|
|
|
if (!clamp_y_axis) {
|
|
|
|
drag_info.last_trackview = tv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************
|
2007-08-10 16:55:27 -04:00
|
|
|
X DELTA COMPUTATION
|
2005-09-25 14:42:24 -04:00
|
|
|
************************************************************/
|
|
|
|
|
|
|
|
/* compute the amount of pointer motion in frames, and where
|
|
|
|
the region would be if we moved it by that much.
|
|
|
|
*/
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
if ( drag_info.move_threshold_passed ) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-05-29 23:31:49 -04:00
|
|
|
if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t sync_frame;
|
|
|
|
nframes_t sync_offset;
|
2005-09-25 14:42:24 -04:00
|
|
|
int32_t sync_dir;
|
2008-02-16 17:43:18 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
pending_region_position = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
|
2007-05-31 17:15:28 -04:00
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
sync_offset = rv->region()->sync_offset (sync_dir);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
/* we don't handle a sync point that lies before zero.
|
2005-09-25 14:42:24 -04:00
|
|
|
*/
|
2008-02-16 17:43:18 -05:00
|
|
|
if (sync_dir >= 0 || (sync_dir < 0 && pending_region_position >= sync_offset)) {
|
|
|
|
sync_frame = pending_region_position + (sync_dir*sync_offset);
|
|
|
|
|
|
|
|
/* we snap if the snap modifier is not enabled.
|
|
|
|
*/
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
|
|
|
|
snap_to (sync_frame);
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
pending_region_position = rv->region()->adjust_to_sync (sync_frame);
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2008-02-16 17:43:18 -05:00
|
|
|
pending_region_position = drag_info.last_frame_position;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
pending_region_position = 0;
|
|
|
|
}
|
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
if (pending_region_position > max_frames - rv->region()->length()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
pending_region_position = drag_info.last_frame_position;
|
|
|
|
}
|
|
|
|
|
|
|
|
// printf ("3: pending_region_position= %lu %lu\n", pending_region_position, drag_info.last_frame_position );
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
bool x_move_allowed = ( !drag_info.x_constrained && (Config->get_edit_mode() != Lock)) || ( drag_info.x_constrained && (Config->get_edit_mode() == Lock)) ;
|
|
|
|
if ( pending_region_position != drag_info.last_frame_position && x_move_allowed ) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
/* now compute the canvas unit distance we need to move the regionview
|
2005-09-25 14:42:24 -04:00
|
|
|
to make it appear at the new location.
|
|
|
|
*/
|
2007-05-29 23:31:49 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (pending_region_position > drag_info.last_frame_position) {
|
|
|
|
x_delta = ((double) (pending_region_position - drag_info.last_frame_position) / frames_per_unit);
|
|
|
|
} else {
|
|
|
|
x_delta = -((double) (drag_info.last_frame_position - pending_region_position) / frames_per_unit);
|
|
|
|
}
|
2007-05-31 17:15:28 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
drag_info.last_frame_position = pending_region_position;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
x_delta = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
/* threshold not passed */
|
|
|
|
|
|
|
|
x_delta = 0;
|
|
|
|
}
|
2008-02-16 17:43:18 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
/*************************************************************
|
2007-08-10 16:55:27 -04:00
|
|
|
PREPARE TO MOVE
|
2005-09-25 14:42:24 -04:00
|
|
|
************************************************************/
|
|
|
|
|
|
|
|
if (x_delta == 0 && (pointer_y_span == 0)) {
|
|
|
|
/* haven't reached next snap point, and we're not switching
|
|
|
|
trackviews. nothing to do.
|
|
|
|
*/
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-05-31 17:15:28 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (x_delta < 0) {
|
2006-07-23 08:03:19 -04:00
|
|
|
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
RegionView* rv2 = (*i);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
// If any regionview is at zero, we need to know so we can stop further leftward motion.
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
double ix1, ix2, iy1, iy2;
|
2005-11-12 22:53:51 -05:00
|
|
|
rv2->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
|
|
|
|
rv2->get_canvas_group()->i2w (ix1, iy1);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (ix1 <= 1) {
|
|
|
|
x_delta = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*************************************************************
|
2007-08-10 16:55:27 -04:00
|
|
|
MOTION
|
2005-09-25 14:42:24 -04:00
|
|
|
************************************************************/
|
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
bool do_move;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
if (drag_info.first_move) {
|
|
|
|
if (drag_info.move_threshold_passed) {
|
|
|
|
do_move = true;
|
|
|
|
} else {
|
|
|
|
do_move = false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
do_move = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (do_move) {
|
|
|
|
|
|
|
|
pair<set<boost::shared_ptr<Playlist> >::iterator,bool> insert_result;
|
|
|
|
const list<RegionView*>& layered_regions = selection->regions.by_layer();
|
2008-01-15 12:23:57 -05:00
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
for (list<RegionView*>::const_iterator i = layered_regions.begin(); i != layered_regions.end(); ++i) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
RegionView* rv = (*i);
|
|
|
|
double ix1, ix2, iy1, iy2;
|
|
|
|
int32_t temp_pointer_y_span = pointer_y_span;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
/* get item BBox, which will be relative to parent. so we have
|
|
|
|
to query on a child, then convert to world coordinates using
|
|
|
|
the parent.
|
|
|
|
*/
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
|
|
|
|
rv->get_canvas_group()->i2w (ix1, iy1);
|
|
|
|
TimeAxisView* tvp2 = trackview_by_y_position (iy1);
|
|
|
|
RouteTimeAxisView* canvas_rtv = dynamic_cast<RouteTimeAxisView*>(tvp2);
|
|
|
|
RouteTimeAxisView* temp_rtv;
|
|
|
|
|
|
|
|
if ((pointer_y_span != 0) && !clamp_y_axis) {
|
|
|
|
y_delta = 0;
|
|
|
|
int32_t x = 0;
|
|
|
|
for (j = height_list.begin(); j!= height_list.end(); j++) {
|
|
|
|
if (x == canvas_rtv->order) {
|
|
|
|
/* we found the track the region is on */
|
|
|
|
if (x != original_pointer_order) {
|
|
|
|
/*this isn't from the same track we're dragging from */
|
|
|
|
temp_pointer_y_span = canvas_pointer_y_span;
|
|
|
|
}
|
|
|
|
while (temp_pointer_y_span > 0) {
|
|
|
|
/* we're moving up canvas-wise,
|
|
|
|
so we need to find the next track height
|
|
|
|
*/
|
|
|
|
if (j != height_list.begin()) {
|
|
|
|
j--;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2007-03-18 02:07:08 -04:00
|
|
|
if (x != original_pointer_order) {
|
|
|
|
/* we're not from the dragged track, so ignore hidden tracks. */
|
|
|
|
if ((*j) == 0) {
|
|
|
|
temp_pointer_y_span++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
y_delta -= (*j);
|
|
|
|
temp_pointer_y_span--;
|
|
|
|
}
|
|
|
|
while (temp_pointer_y_span < 0) {
|
|
|
|
y_delta += (*j);
|
|
|
|
if (x != original_pointer_order) {
|
|
|
|
if ((*j) == 0) {
|
|
|
|
temp_pointer_y_span--;
|
|
|
|
}
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
if (j != height_list.end()) {
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
temp_pointer_y_span++;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2007-03-18 02:07:08 -04:00
|
|
|
/* find out where we'll be when we move and set height accordingly */
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
tvp2 = trackview_by_y_position (iy1 + y_delta);
|
|
|
|
temp_rtv = dynamic_cast<RouteTimeAxisView*>(tvp2);
|
2007-05-17 06:41:14 -04:00
|
|
|
rv->set_y_position_and_height (0, temp_rtv->height);
|
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
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
/* if you un-comment the following, the region colours will follow the track colours whilst dragging,
|
|
|
|
personally, i think this can confuse things, but never mind.
|
|
|
|
*/
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
//const GdkColor& col (temp_rtv->view->get_region_color());
|
|
|
|
//rv->set_color (const_cast<GdkColor&>(col));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
x++;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
/* prevent the regionview from being moved to before
|
|
|
|
the zero position on the canvas.
|
|
|
|
*/
|
|
|
|
/* clamp */
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
if (x_delta < 0) {
|
|
|
|
if (-x_delta > ix1) {
|
|
|
|
x_delta = -ix1;
|
|
|
|
}
|
2007-05-29 23:31:49 -04:00
|
|
|
} else if ((x_delta > 0) && (rv->region()->last_frame() > max_frames - x_delta)) {
|
2007-03-18 02:07:08 -04:00
|
|
|
x_delta = max_frames - rv->region()->last_frame();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2007-05-31 17:15:28 -04:00
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
if (drag_info.first_move) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
/* hide any dependent views */
|
|
|
|
|
|
|
|
rv->get_time_axis_view().hide_dependent_views (*rv);
|
|
|
|
|
|
|
|
/* this is subtle. raising the regionview itself won't help,
|
|
|
|
because raise_to_top() just puts the item on the top of
|
|
|
|
its parent's stack. so, we need to put the trackview canvas_display group
|
|
|
|
on the top, since its parent is the whole canvas.
|
|
|
|
*/
|
|
|
|
|
|
|
|
rv->get_canvas_group()->raise_to_top();
|
|
|
|
rv->get_time_axis_view().canvas_display->raise_to_top();
|
|
|
|
cursor_group->raise_to_top();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
rv->fake_set_opaque (true);
|
|
|
|
}
|
2008-01-10 16:20:59 -05:00
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
if (drag_info.brushing) {
|
|
|
|
mouse_brush_insert_region (rv, pending_region_position);
|
|
|
|
} else {
|
|
|
|
rv->move (x_delta, y_delta);
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
} /* foreach region */
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
} /* if do_move */
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
if (drag_info.first_move && drag_info.move_threshold_passed) {
|
2005-10-28 18:19:45 -04:00
|
|
|
cursor_group->raise_to_top();
|
2007-03-18 02:07:08 -04:00
|
|
|
drag_info.first_move = false;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2007-03-18 02:07:08 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (x_delta != 0 && !drag_info.brushing) {
|
|
|
|
show_verbose_time_cursor (drag_info.last_frame_position, 10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t where;
|
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
|
|
|
RegionView* rvdi = reinterpret_cast<RegionView *> (drag_info.data);
|
2007-01-09 18:24:54 -05:00
|
|
|
pair<set<boost::shared_ptr<Playlist> >::iterator,bool> insert_result;
|
2005-09-25 14:42:24 -04:00
|
|
|
bool nocommit = true;
|
|
|
|
double speed;
|
2007-03-18 02:07:08 -04:00
|
|
|
RouteTimeAxisView* rtv;
|
2005-09-25 14:42:24 -04:00
|
|
|
bool regionview_y_movement;
|
|
|
|
bool regionview_x_movement;
|
2007-04-29 13:23:11 -04:00
|
|
|
vector<RegionView*> copies;
|
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;
|
|
|
|
list <sigc::connection > used_connections;
|
|
|
|
bool preserve_selection = false;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
/* first_move is set to false if the regionview has been moved in the
|
|
|
|
motion handler.
|
|
|
|
*/
|
|
|
|
|
2007-06-01 18:51:01 -04:00
|
|
|
if (drag_info.first_move) {
|
2005-09-25 14:42:24 -04:00
|
|
|
/* just a click */
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
nocommit = false;
|
|
|
|
|
|
|
|
/* The regionview has been moved at some stage during the grab so we need
|
|
|
|
to account for any mouse movement between this event and the last one.
|
|
|
|
*/
|
|
|
|
|
|
|
|
region_drag_motion_callback (item, event);
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (Config->get_edit_mode() == Splice && !pre_drag_region_selection.empty()) {
|
|
|
|
selection->set (pre_drag_region_selection);
|
|
|
|
pre_drag_region_selection.clear ();
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (drag_info.brushing) {
|
|
|
|
/* all changes were made during motion event handlers */
|
2007-04-29 13:23:11 -04:00
|
|
|
|
|
|
|
if (drag_info.copy) {
|
|
|
|
for (list<RegionView*>::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
|
|
|
|
copies.push_back (*i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* adjust for track speed */
|
|
|
|
speed = 1.0;
|
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
rtv = dynamic_cast<RouteTimeAxisView*> (drag_info.last_trackview);
|
|
|
|
if (rtv && rtv->get_diskstream()) {
|
|
|
|
speed = rtv->get_diskstream()->speed();
|
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
|
|
|
regionview_x_movement = (drag_info.last_frame_position != (nframes_t) (rvdi->region()->position()/speed));
|
|
|
|
regionview_y_movement = (drag_info.last_trackview != &rvdi->get_time_axis_view());
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
//printf ("last_frame: %s position is %lu %g\n", rv->get_time_axis_view().name().c_str(), drag_info.last_frame_position, speed);
|
|
|
|
//printf ("last_rackview: %s \n", drag_info.last_trackview->name().c_str());
|
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
char* op_string;
|
|
|
|
|
|
|
|
if (drag_info.copy) {
|
|
|
|
if (drag_info.x_constrained) {
|
|
|
|
op_string = _("fixed time region copy");
|
|
|
|
} else {
|
|
|
|
op_string = _("region copy");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (drag_info.x_constrained) {
|
|
|
|
op_string = _("fixed time region drag");
|
|
|
|
} else {
|
|
|
|
op_string = _("region drag");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
begin_reversible_command (op_string);
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (regionview_y_movement) {
|
|
|
|
|
2008-01-12 18:45:50 -05:00
|
|
|
/* moved to a different track. */
|
2007-04-12 19:20:37 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
vector<RegionView*> new_selection;
|
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ) {
|
2007-04-29 13:23:11 -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
|
|
|
RegionView* rv = (*i);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
double ix1, ix2, iy1, iy2;
|
2007-03-18 02:07:08 -04:00
|
|
|
|
|
|
|
rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
|
|
|
|
rv->get_canvas_group()->i2w (ix1, iy1);
|
2007-01-09 18:24:54 -05: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
|
|
|
RouteTimeAxisView* rtv2 = dynamic_cast<RouteTimeAxisView*>(trackview_by_y_position (iy1));
|
|
|
|
|
2008-01-12 18:45:50 -05:00
|
|
|
boost::shared_ptr<Playlist> from_playlist = rv->region()->playlist();
|
2007-03-18 02:07:08 -04:00
|
|
|
boost::shared_ptr<Playlist> to_playlist = rtv2->playlist();
|
2008-01-12 18:45:50 -05:00
|
|
|
|
|
|
|
where = (nframes_t) (unit_to_frame (ix1) * speed);
|
|
|
|
boost::shared_ptr<Region> new_region (RegionFactory::create (rv->region()));
|
2007-05-09 22:23:12 -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
|
|
|
if (! to_playlist->frozen()) {
|
|
|
|
/*
|
|
|
|
we haven't seen this playlist before.
|
|
|
|
we want to freeze it because we don't want to relayer per-region.
|
|
|
|
its much better to do that just once if the playlist is large.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
connect so the selection is changed when the new regionview finally appears (after thaw).
|
|
|
|
keep track of it so we can disconnect later.
|
|
|
|
*/
|
|
|
|
|
|
|
|
sigc::connection c = rtv2->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_and_select_new_region_view));
|
|
|
|
used_connections.push_back (c);
|
|
|
|
|
|
|
|
/* undo */
|
|
|
|
session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));
|
|
|
|
|
|
|
|
/* remember used playlists so we can thaw them later */
|
|
|
|
used_playlists.push_back(to_playlist);
|
|
|
|
to_playlist->freeze();
|
|
|
|
}
|
|
|
|
|
2008-01-12 18:45:50 -05:00
|
|
|
/* undo the previous hide_dependent_views so that xfades don't
|
|
|
|
disappear on copying regions
|
|
|
|
*/
|
2007-04-12 19:20:37 -04:00
|
|
|
|
2008-01-12 18:45:50 -05:00
|
|
|
rv->get_time_axis_view().reveal_dependent_views (*rv);
|
2007-04-12 19:20:37 -04:00
|
|
|
|
2008-01-12 18:45:50 -05:00
|
|
|
if (!drag_info.copy) {
|
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
/* the region that used to be in the old playlist is not
|
|
|
|
moved to the new one - we make a copy of it. as a result,
|
|
|
|
any existing editor for the region should no longer be
|
|
|
|
visible.
|
|
|
|
*/
|
2008-01-12 18:45:50 -05:00
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
rv->hide_region_editor();
|
|
|
|
rv->fake_set_opaque (false);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-01-12 18:45:50 -05:00
|
|
|
session->add_command (new MementoCommand<Playlist>(*from_playlist, &from_playlist->get_state(), 0));
|
2007-03-18 02:07:08 -04:00
|
|
|
from_playlist->remove_region ((rv->region()));
|
2008-01-12 18:45:50 -05:00
|
|
|
session->add_command (new MementoCommand<Playlist>(*from_playlist, 0, &from_playlist->get_state()));
|
2007-04-29 13:23:11 -04:00
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
/* the regionview we dragged around is a temporary copy, queue it for deletion */
|
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
|
|
|
|
2007-04-29 13:23:11 -04:00
|
|
|
copies.push_back (rv);
|
2007-03-18 02:07:08 -04:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
latest_regionviews.clear ();
|
|
|
|
sigc::connection c = rtv2->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
|
|
|
|
session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 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
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
to_playlist->add_region (new_region, where);
|
2008-01-10 16:20:59 -05:00
|
|
|
session->add_command (new MementoCommand<Playlist>(*to_playlist, 0, &to_playlist->get_state()));
|
|
|
|
c.disconnect ();
|
|
|
|
|
|
|
|
if (!latest_regionviews.empty()) {
|
|
|
|
new_selection.insert (new_selection.end(), latest_regionviews.begin(), latest_regionviews.end());
|
|
|
|
}
|
2007-03-18 02:07:08 -04:00
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
/* OK, this is where it gets tricky. If the playlist was being used by >1 tracks, and the region
|
|
|
|
was selected in all of them, then removing it from the playlist will have removed all
|
|
|
|
trace of it from the selection (i.e. there were N regions selected, we removed 1,
|
|
|
|
but since its the same playlist for N tracks, all N tracks updated themselves, removed the
|
|
|
|
corresponding regionview, and the selection is now empty).
|
|
|
|
|
|
|
|
this could have invalidated any and all iterators into the region selection.
|
|
|
|
|
|
|
|
the heuristic we use here is: if the region selection is empty, break out of the loop
|
|
|
|
here. if the region selection is not empty, then restart the loop because we know that
|
|
|
|
we must have removed at least the region(view) we've just been working on as well as any
|
|
|
|
that we processed on previous iterations.
|
2007-04-29 13:23:11 -04:00
|
|
|
|
|
|
|
EXCEPT .... if we are doing a copy drag, then the selection hasn't been modified and
|
|
|
|
we can just iterate.
|
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
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
*/
|
|
|
|
|
2007-04-29 13:23:11 -04:00
|
|
|
if (drag_info.copy) {
|
|
|
|
++i;
|
|
|
|
} else {
|
|
|
|
if (selection->regions.empty()) {
|
|
|
|
break;
|
|
|
|
} else {
|
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
|
|
|
/*
|
|
|
|
XXX see above .. but we just froze the playlists.. we have to keep iterating, right?
|
|
|
|
*/
|
|
|
|
|
|
|
|
//i = selection->regions.by_layer().begin();
|
|
|
|
++i;
|
2007-04-29 13:23:11 -04:00
|
|
|
}
|
2007-04-12 19:20:37 -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
|
|
|
}
|
2007-04-12 19:20:37 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
|
|
|
|
|
|
|
/* motion within a single track */
|
2007-03-18 02:07:08 -04:00
|
|
|
|
|
|
|
list<RegionView*> regions = selection->regions.by_layer();
|
|
|
|
|
|
|
|
for (list<RegionView*>::iterator i = regions.begin(); i != regions.end(); ++i) {
|
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
|
|
|
RegionView* rv = (*i);
|
|
|
|
boost::shared_ptr<Playlist> to_playlist = (*i)->region()->playlist();
|
|
|
|
RouteTimeAxisView* from_rtv = dynamic_cast<RouteTimeAxisView*> (&(rv->get_time_axis_view()));
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-05-14 12:16:54 -04:00
|
|
|
if (!rv->region()->can_move()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
continue;
|
|
|
|
}
|
2007-03-18 02:07:08 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (regionview_x_movement) {
|
|
|
|
double ownspeed = 1.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
|
|
|
if (from_rtv && from_rtv->get_diskstream()) {
|
|
|
|
ownspeed = from_rtv->get_diskstream()->speed();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* base the new region position on the current position of the regionview.*/
|
|
|
|
|
|
|
|
double ix1, ix2, iy1, iy2;
|
|
|
|
|
2005-11-12 22:53:51 -05:00
|
|
|
rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
|
|
|
|
rv->get_canvas_group()->i2w (ix1, iy1);
|
2006-10-21 15:01:50 -04:00
|
|
|
where = (nframes_t) (unit_to_frame (ix1) * ownspeed);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
} else {
|
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
where = rv->region()->position();
|
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
|
|
|
if (! to_playlist->frozen()) {
|
|
|
|
sigc::connection c = from_rtv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_and_select_new_region_view));
|
|
|
|
used_connections.push_back (c);
|
2006-01-07 21:56:49 -05: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
|
|
|
/* add the undo */
|
|
|
|
session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));
|
2007-04-12 19:20:37 -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
|
|
|
used_playlists.push_back(to_playlist);
|
|
|
|
to_playlist->freeze();
|
|
|
|
}
|
2007-03-18 02:07:08 -04:00
|
|
|
|
|
|
|
if (drag_info.copy) {
|
|
|
|
|
|
|
|
boost::shared_ptr<Region> newregion;
|
|
|
|
boost::shared_ptr<Region> ar;
|
2007-06-03 20:05:33 -04:00
|
|
|
boost::shared_ptr<Region> mr;
|
2007-03-18 02:07:08 -04:00
|
|
|
|
|
|
|
if ((ar = boost::dynamic_pointer_cast<AudioRegion>(rv->region())) != 0) {
|
|
|
|
newregion = RegionFactory::create (ar);
|
2007-06-03 20:05:33 -04:00
|
|
|
} else if ((mr = boost::dynamic_pointer_cast<MidiRegion>(rv->region())) != 0) {
|
|
|
|
newregion = RegionFactory::create (mr);
|
2007-03-18 02:07:08 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* add it */
|
2007-05-09 22:23:12 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
latest_regionviews.clear ();
|
|
|
|
sigc::connection c = rtv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
|
|
|
|
to_playlist->add_region (newregion, (nframes_t) (where * rtv->get_diskstream()->speed()));
|
|
|
|
c.disconnect ();
|
2008-01-15 12:23:57 -05:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (!latest_regionviews.empty()) {
|
|
|
|
// XXX why just the first one ? we only expect one
|
|
|
|
rtv->reveal_dependent_views (*latest_regionviews.front());
|
|
|
|
selection->add (latest_regionviews);
|
|
|
|
}
|
2007-03-18 02:07:08 -04:00
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
/* just change the model */
|
|
|
|
|
|
|
|
rv->region()->set_position (where, (void*) this);
|
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
|
|
|
preserve_selection = true;
|
2007-03-18 02:07:08 -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
|
|
|
}
|
2007-03-18 02:07:08 -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
|
|
|
}
|
|
|
|
if (! preserve_selection) {
|
|
|
|
//selection->clear_regions();
|
|
|
|
}
|
|
|
|
while (used_playlists.size() > 0) {
|
2007-03-18 02:07:08 -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 > >::iterator i = used_playlists.begin();
|
|
|
|
(*i)->thaw();
|
|
|
|
|
|
|
|
if (used_connections.size()) {
|
|
|
|
sigc::connection c = used_connections.front();
|
|
|
|
c.disconnect();
|
|
|
|
used_connections.pop_front();
|
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
|
|
|
/* add the redo */
|
|
|
|
|
|
|
|
session->add_command (new MementoCommand<Playlist>(*(*i), 0, &(*i)->get_state()));
|
|
|
|
used_playlists.pop_front();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
2007-03-18 02:07:08 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (!nocommit) {
|
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
2007-04-29 13:23:11 -04:00
|
|
|
|
|
|
|
for (vector<RegionView*>::iterator x = copies.begin(); x != copies.end(); ++x) {
|
|
|
|
delete *x;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2007-10-14 01:45:31 -04:00
|
|
|
|
|
|
|
void
|
|
|
|
Editor::create_region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
|
|
|
{
|
|
|
|
if (drag_info.move_threshold_passed) {
|
|
|
|
if (drag_info.first_move) {
|
|
|
|
// TODO: create region-create-drag region view here
|
|
|
|
drag_info.first_move = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: resize region-create-drag region view here
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::create_region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
|
|
|
{
|
|
|
|
MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (drag_info.last_trackview);
|
|
|
|
if (!mtv)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const boost::shared_ptr<MidiDiskstream> diskstream =
|
|
|
|
boost::dynamic_pointer_cast<MidiDiskstream>(mtv->view()->trackview().track()->diskstream());
|
|
|
|
|
|
|
|
if (!diskstream) {
|
|
|
|
warning << "Cannot create non-MIDI region" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (drag_info.first_move) {
|
|
|
|
begin_reversible_command (_("create region"));
|
|
|
|
XMLNode &before = mtv->playlist()->get_state();
|
|
|
|
|
|
|
|
nframes_t start = drag_info.grab_frame;
|
|
|
|
snap_to (start, -1);
|
|
|
|
const Meter& m = session->tempo_map().meter_at(start);
|
|
|
|
const Tempo& t = session->tempo_map().tempo_at(start);
|
2007-11-07 20:40:25 -05:00
|
|
|
double length = floor (m.frames_per_bar(t, session->frame_rate()));
|
2007-10-14 01:45:31 -04:00
|
|
|
|
|
|
|
boost::shared_ptr<Source> src = session->create_midi_source_for_session(*diskstream.get());
|
|
|
|
|
2007-11-07 20:40:25 -05:00
|
|
|
mtv->playlist()->add_region (boost::dynamic_pointer_cast<MidiRegion>
|
|
|
|
(RegionFactory::create(src, 0, (nframes_t) length,
|
|
|
|
PBD::basename_nosuffix(src->name()))), start);
|
2007-10-14 01:45:31 -04:00
|
|
|
XMLNode &after = mtv->playlist()->get_state();
|
|
|
|
session->add_command(new MementoCommand<Playlist>(*mtv->playlist().get(), &before, &after));
|
|
|
|
commit_reversible_command();
|
|
|
|
|
|
|
|
} else {
|
|
|
|
create_region_drag_motion_callback (item, event);
|
|
|
|
// TODO: create region-create-drag region here
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
|
|
|
Editor::region_view_item_click (AudioRegionView& rv, GdkEventButton* event)
|
|
|
|
{
|
|
|
|
/* Either add to or set the set the region selection, unless
|
|
|
|
this is an alignment click (control used)
|
|
|
|
*/
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (Keyboard::modifier_state_contains (event->state, Keyboard::PrimaryModifier)) {
|
2005-09-25 14:42:24 -04:00
|
|
|
TimeAxisView* tv = &rv.get_time_axis_view();
|
2007-03-18 02:07:08 -04:00
|
|
|
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(tv);
|
2005-09-25 14:42:24 -04:00
|
|
|
double speed = 1.0;
|
2007-03-18 02:07:08 -04:00
|
|
|
if (rtv && rtv->is_track()) {
|
|
|
|
speed = rtv->get_diskstream()->speed();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2007-11-07 20:40:25 -05:00
|
|
|
nframes64_t where = get_preferred_edit_position();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-11-07 20:40:25 -05:00
|
|
|
if (where >= 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
|
2007-11-07 20:40:25 -05:00
|
|
|
|
|
|
|
align_region (rv.region(), SyncPoint, (nframes_t) (where * speed));
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
} else if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
|
2007-11-07 20:40:25 -05:00
|
|
|
|
|
|
|
align_region (rv.region(), End, (nframes_t) (where * speed));
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
align_region (rv.region(), Start, (nframes_t) (where * speed));
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2006-10-21 15:01:50 -04:00
|
|
|
Editor::show_verbose_time_cursor (nframes_t frame, double offset, double xpos, double ypos)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
char buf[128];
|
2006-06-08 19:46:42 -04:00
|
|
|
SMPTE::Time smpte;
|
2005-09-25 14:42:24 -04:00
|
|
|
BBT_Time bbt;
|
2007-01-09 18:24:54 -05:00
|
|
|
int hours, mins;
|
|
|
|
nframes_t frame_rate;
|
2005-09-25 14:42:24 -04:00
|
|
|
float secs;
|
|
|
|
|
|
|
|
if (session == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-04-12 19:20:37 -04:00
|
|
|
switch (Profile->get_small_screen() ? ARDOUR_UI::instance()->primary_clock.mode () : ARDOUR_UI::instance()->secondary_clock.mode ()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
case AudioClock::BBT:
|
|
|
|
session->bbt_time (frame, bbt);
|
|
|
|
snprintf (buf, sizeof (buf), "%02" PRIu32 "|%02" PRIu32 "|%02" PRIu32, bbt.bars, bbt.beats, bbt.ticks);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AudioClock::SMPTE:
|
|
|
|
session->smpte_time (frame, smpte);
|
|
|
|
snprintf (buf, sizeof (buf), "%02" PRId32 ":%02" PRId32 ":%02" PRId32 ":%02" PRId32, smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AudioClock::MinSec:
|
2007-01-09 18:24:54 -05:00
|
|
|
/* XXX this is copied from show_verbose_duration_cursor() */
|
|
|
|
frame_rate = session->frame_rate();
|
|
|
|
hours = frame / (frame_rate * 3600);
|
|
|
|
frame = frame % (frame_rate * 3600);
|
|
|
|
mins = frame / (frame_rate * 60);
|
|
|
|
frame = frame % (frame_rate * 60);
|
|
|
|
secs = (float) frame / (float) frame_rate;
|
|
|
|
snprintf (buf, sizeof (buf), "%02" PRId32 ":%02" PRId32 ":%.4f", hours, mins, secs);
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
snprintf (buf, sizeof(buf), "%u", frame);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xpos >= 0 && ypos >=0) {
|
|
|
|
set_verbose_canvas_cursor (buf, xpos + offset, ypos + offset);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
set_verbose_canvas_cursor (buf, drag_info.current_pointer_x + offset, drag_info.current_pointer_y + offset);
|
|
|
|
}
|
|
|
|
show_verbose_canvas_cursor ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2006-10-21 15:01:50 -04:00
|
|
|
Editor::show_verbose_duration_cursor (nframes_t start, nframes_t end, double offset, double xpos, double ypos)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
char buf[128];
|
2006-06-08 19:46:42 -04:00
|
|
|
SMPTE::Time smpte;
|
2005-09-25 14:42:24 -04:00
|
|
|
BBT_Time sbbt;
|
|
|
|
BBT_Time ebbt;
|
2007-01-09 18:24:54 -05:00
|
|
|
int hours, mins;
|
|
|
|
nframes_t distance, frame_rate;
|
2005-09-25 14:42:24 -04:00
|
|
|
float secs;
|
|
|
|
Meter meter_at_start(session->tempo_map().meter_at(start));
|
|
|
|
|
|
|
|
if (session == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (ARDOUR_UI::instance()->secondary_clock.mode ()) {
|
|
|
|
case AudioClock::BBT:
|
|
|
|
session->bbt_time (start, sbbt);
|
|
|
|
session->bbt_time (end, ebbt);
|
|
|
|
|
|
|
|
/* subtract */
|
|
|
|
/* XXX this computation won't work well if the
|
|
|
|
user makes a selection that spans any meter changes.
|
|
|
|
*/
|
|
|
|
|
|
|
|
ebbt.bars -= sbbt.bars;
|
|
|
|
if (ebbt.beats >= sbbt.beats) {
|
|
|
|
ebbt.beats -= sbbt.beats;
|
|
|
|
} else {
|
|
|
|
ebbt.bars--;
|
|
|
|
ebbt.beats = int(meter_at_start.beats_per_bar()) + ebbt.beats - sbbt.beats;
|
|
|
|
}
|
|
|
|
if (ebbt.ticks >= sbbt.ticks) {
|
|
|
|
ebbt.ticks -= sbbt.ticks;
|
|
|
|
} else {
|
|
|
|
ebbt.beats--;
|
|
|
|
ebbt.ticks = int(Meter::ticks_per_beat) + ebbt.ticks - sbbt.ticks;
|
|
|
|
}
|
|
|
|
|
|
|
|
snprintf (buf, sizeof (buf), "%02" PRIu32 "|%02" PRIu32 "|%02" PRIu32, ebbt.bars, ebbt.beats, ebbt.ticks);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AudioClock::SMPTE:
|
|
|
|
session->smpte_duration (end - start, smpte);
|
|
|
|
snprintf (buf, sizeof (buf), "%02" PRId32 ":%02" PRId32 ":%02" PRId32 ":%02" PRId32, smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AudioClock::MinSec:
|
2007-01-09 18:24:54 -05:00
|
|
|
/* XXX this stuff should be elsewhere.. */
|
|
|
|
distance = end - start;
|
|
|
|
frame_rate = session->frame_rate();
|
|
|
|
hours = distance / (frame_rate * 3600);
|
|
|
|
distance = distance % (frame_rate * 3600);
|
|
|
|
mins = distance / (frame_rate * 60);
|
|
|
|
distance = distance % (frame_rate * 60);
|
|
|
|
secs = (float) distance / (float) frame_rate;
|
|
|
|
snprintf (buf, sizeof (buf), "%02" PRId32 ":%02" PRId32 ":%.4f", hours, mins, secs);
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
snprintf (buf, sizeof(buf), "%u", end - start);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xpos >= 0 && ypos >=0) {
|
|
|
|
set_verbose_canvas_cursor (buf, xpos + offset, ypos + offset);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
set_verbose_canvas_cursor (buf, drag_info.current_pointer_x + offset, drag_info.current_pointer_y + offset);
|
|
|
|
}
|
|
|
|
show_verbose_canvas_cursor ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2006-07-23 08:03:19 -04:00
|
|
|
Editor::collect_new_region_view (RegionView* rv)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2008-01-10 16:20:59 -05:00
|
|
|
latest_regionviews.push_back (rv);
|
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
|
|
|
void
|
|
|
|
Editor::collect_and_select_new_region_view (RegionView* rv)
|
|
|
|
{
|
|
|
|
selection->add(rv);
|
2008-01-10 16:20:59 -05:00
|
|
|
latest_regionviews.push_back (rv);
|
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
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
if (clicked_regionview == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* lets try to create new Region for the selection */
|
|
|
|
|
2008-02-16 17:43:18 -05:00
|
|
|
vector<boost::shared_ptr<Region> > new_regions;
|
2005-09-25 14:42:24 -04:00
|
|
|
create_region_from_selection (new_regions);
|
|
|
|
|
|
|
|
if (new_regions.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX fix me one day to use all new regions */
|
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
boost::shared_ptr<Region> region (new_regions.front());
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
/* add it to the current stream/playlist.
|
|
|
|
|
|
|
|
tricky: the streamview for the track will add a new regionview. we will
|
|
|
|
catch the signal it sends when it creates the regionview to
|
|
|
|
set the regionview we want to then drag.
|
|
|
|
*/
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
latest_regionviews.clear();
|
2006-08-16 16:36:14 -04:00
|
|
|
sigc::connection c = clicked_routeview->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
/* A selection grab currently creates two undo/redo operations, one for
|
|
|
|
creating the new region and another for moving it.
|
|
|
|
*/
|
|
|
|
|
|
|
|
begin_reversible_command (_("selection grab"));
|
|
|
|
|
2007-01-09 18:24:54 -05:00
|
|
|
boost::shared_ptr<Playlist> playlist = clicked_axisview->playlist();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
XMLNode *before = &(playlist->get_state());
|
|
|
|
clicked_routeview->playlist()->add_region (region, selection->time[clicked_selection].start);
|
|
|
|
XMLNode *after = &(playlist->get_state());
|
2006-08-24 03:37:17 -04:00
|
|
|
session->add_command(new MementoCommand<Playlist>(*playlist, before, after));
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
commit_reversible_command ();
|
|
|
|
|
|
|
|
c.disconnect ();
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (latest_regionviews.empty()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
/* something went wrong */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* we need to deselect all other regionviews, and select this one
|
2008-01-10 16:20:59 -05:00
|
|
|
i'm ignoring undo stuff, because the region creation will take care of it
|
|
|
|
*/
|
|
|
|
selection->set (latest_regionviews);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
drag_info.item = latest_regionviews.front()->get_canvas_group();
|
|
|
|
drag_info.data = latest_regionviews.front();
|
2005-09-25 14:42:24 -04:00
|
|
|
drag_info.motion_callback = &Editor::region_drag_motion_callback;
|
|
|
|
drag_info.finished_callback = &Editor::region_drag_finished_callback;
|
|
|
|
|
|
|
|
start_grab (event);
|
|
|
|
|
2006-08-16 16:36:14 -04:00
|
|
|
drag_info.last_trackview = clicked_axisview;
|
2008-01-10 16:20:59 -05:00
|
|
|
drag_info.last_frame_position = latest_regionviews.front()->region()->position();
|
2005-09-25 14:42:24 -04:00
|
|
|
drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
|
|
|
|
|
|
|
|
show_verbose_time_cursor (drag_info.last_frame_position, 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::cancel_selection ()
|
|
|
|
{
|
2007-08-10 16:55:27 -04:00
|
|
|
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
2005-09-25 14:42:24 -04:00
|
|
|
(*i)->hide_selection ();
|
|
|
|
}
|
|
|
|
selection->clear ();
|
|
|
|
clicked_selection = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::start_selection_op (ArdourCanvas::Item* item, GdkEvent* event, SelectionOp op)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t start = 0;
|
|
|
|
nframes_t end = 0;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (session == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
drag_info.item = item;
|
|
|
|
drag_info.motion_callback = &Editor::drag_selection;
|
|
|
|
drag_info.finished_callback = &Editor::end_selection_op;
|
|
|
|
|
|
|
|
selection_op = op;
|
|
|
|
|
|
|
|
switch (op) {
|
|
|
|
case CreateSelection:
|
2008-01-10 16:20:59 -05:00
|
|
|
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
|
2005-09-25 14:42:24 -04:00
|
|
|
drag_info.copy = true;
|
|
|
|
} else {
|
|
|
|
drag_info.copy = false;
|
|
|
|
}
|
|
|
|
start_grab (event, selector_cursor);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SelectionStartTrim:
|
2006-08-16 16:36:14 -04:00
|
|
|
if (clicked_axisview) {
|
|
|
|
clicked_axisview->order_selection_trims (item, true);
|
2006-06-13 03:27:52 -04:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
start_grab (event, trimmer_cursor);
|
|
|
|
start = selection->time[clicked_selection].start;
|
|
|
|
drag_info.pointer_frame_offset = drag_info.grab_frame - start;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SelectionEndTrim:
|
2006-08-16 16:36:14 -04:00
|
|
|
if (clicked_axisview) {
|
|
|
|
clicked_axisview->order_selection_trims (item, false);
|
2006-06-13 03:27:52 -04:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
start_grab (event, trimmer_cursor);
|
|
|
|
end = selection->time[clicked_selection].end;
|
|
|
|
drag_info.pointer_frame_offset = drag_info.grab_frame - end;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SelectionMove:
|
|
|
|
start = selection->time[clicked_selection].start;
|
|
|
|
start_grab (event);
|
|
|
|
drag_info.pointer_frame_offset = drag_info.grab_frame - start;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (selection_op == SelectionMove) {
|
|
|
|
show_verbose_time_cursor(start, 10);
|
|
|
|
} else {
|
|
|
|
show_verbose_time_cursor(drag_info.current_pointer_frame, 10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::drag_selection (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t start = 0;
|
|
|
|
nframes_t end = 0;
|
|
|
|
nframes_t length;
|
|
|
|
nframes_t pending_position;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-05-29 23:31:49 -04:00
|
|
|
if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) {
|
2005-09-25 14:42:24 -04:00
|
|
|
pending_position = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
|
2007-05-29 23:31:49 -04:00
|
|
|
} else {
|
2005-09-25 14:42:24 -04:00
|
|
|
pending_position = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
|
|
|
|
snap_to (pending_position);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* only alter selection if the current frame is
|
|
|
|
different from the last frame position (adjusted)
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (pending_position == drag_info.last_pointer_frame) return;
|
|
|
|
|
|
|
|
switch (selection_op) {
|
|
|
|
case CreateSelection:
|
|
|
|
|
|
|
|
if (drag_info.first_move) {
|
|
|
|
snap_to (drag_info.grab_frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pending_position < drag_info.grab_frame) {
|
|
|
|
start = pending_position;
|
|
|
|
end = drag_info.grab_frame;
|
|
|
|
} else {
|
|
|
|
end = pending_position;
|
|
|
|
start = drag_info.grab_frame;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* first drag: Either add to the selection
|
|
|
|
or create a new selection->
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (drag_info.first_move) {
|
|
|
|
|
|
|
|
begin_reversible_command (_("range selection"));
|
|
|
|
|
|
|
|
if (drag_info.copy) {
|
|
|
|
/* adding to the selection */
|
|
|
|
clicked_selection = selection->add (start, end);
|
|
|
|
drag_info.copy = false;
|
|
|
|
} else {
|
|
|
|
/* new selection-> */
|
2006-08-16 16:36:14 -04:00
|
|
|
clicked_selection = selection->set (clicked_axisview, start, end);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SelectionStartTrim:
|
|
|
|
|
|
|
|
if (drag_info.first_move) {
|
|
|
|
begin_reversible_command (_("trim selection start"));
|
|
|
|
}
|
|
|
|
|
|
|
|
start = selection->time[clicked_selection].start;
|
|
|
|
end = selection->time[clicked_selection].end;
|
|
|
|
|
|
|
|
if (pending_position > end) {
|
|
|
|
start = end;
|
|
|
|
} else {
|
|
|
|
start = pending_position;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SelectionEndTrim:
|
|
|
|
|
|
|
|
if (drag_info.first_move) {
|
|
|
|
begin_reversible_command (_("trim selection end"));
|
|
|
|
}
|
|
|
|
|
|
|
|
start = selection->time[clicked_selection].start;
|
|
|
|
end = selection->time[clicked_selection].end;
|
|
|
|
|
|
|
|
if (pending_position < start) {
|
|
|
|
end = start;
|
|
|
|
} else {
|
|
|
|
end = pending_position;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SelectionMove:
|
|
|
|
|
|
|
|
if (drag_info.first_move) {
|
|
|
|
begin_reversible_command (_("move selection"));
|
|
|
|
}
|
|
|
|
|
|
|
|
start = selection->time[clicked_selection].start;
|
|
|
|
end = selection->time[clicked_selection].end;
|
|
|
|
|
|
|
|
length = end - start;
|
|
|
|
|
|
|
|
start = pending_position;
|
|
|
|
snap_to (start);
|
|
|
|
|
|
|
|
end = start + length;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-12-12 15:54:55 -05:00
|
|
|
if (event->button.x >= horizontal_adjustment.get_value() + canvas_width) {
|
2005-09-25 14:42:24 -04:00
|
|
|
start_canvas_autoscroll (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (start != end) {
|
|
|
|
selection->replace (clicked_selection, start, end);
|
|
|
|
}
|
|
|
|
|
|
|
|
drag_info.last_pointer_frame = pending_position;
|
|
|
|
drag_info.first_move = false;
|
|
|
|
|
|
|
|
if (selection_op == SelectionMove) {
|
|
|
|
show_verbose_time_cursor(start, 10);
|
|
|
|
} else {
|
|
|
|
show_verbose_time_cursor(pending_position, 10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::end_selection_op (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
if (!drag_info.first_move) {
|
|
|
|
drag_selection (item, event);
|
|
|
|
/* XXX this is not object-oriented programming at all. ick */
|
|
|
|
if (selection->time.consolidate()) {
|
|
|
|
selection->TimeChanged ();
|
|
|
|
}
|
|
|
|
commit_reversible_command ();
|
|
|
|
} else {
|
|
|
|
/* just a click, no pointer movement.*/
|
|
|
|
|
|
|
|
if (Keyboard::no_modifier_keys_pressed (&event->button)) {
|
|
|
|
|
|
|
|
selection->clear_time();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX what happens if its a music selection? */
|
|
|
|
session->set_audio_range (selection->time);
|
|
|
|
stop_canvas_autoscroll ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::start_trim (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
double speed = 1.0;
|
2006-08-16 16:36:14 -04:00
|
|
|
TimeAxisView* tvp = clicked_axisview;
|
2006-08-14 04:44:14 -04:00
|
|
|
RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-08-14 04:44:14 -04:00
|
|
|
if (tv && tv->is_track()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
speed = tv->get_diskstream()->speed();
|
|
|
|
}
|
|
|
|
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t region_start = (nframes_t) (clicked_regionview->region()->position() / speed);
|
|
|
|
nframes_t region_end = (nframes_t) (clicked_regionview->region()->last_frame() / speed);
|
|
|
|
nframes_t region_length = (nframes_t) (clicked_regionview->region()->length() / speed);
|
2006-01-19 13:00:07 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
//drag_info.item = clicked_regionview->get_name_highlight();
|
|
|
|
drag_info.item = item;
|
|
|
|
drag_info.motion_callback = &Editor::trim_motion_callback;
|
|
|
|
drag_info.finished_callback = &Editor::trim_finished_callback;
|
|
|
|
|
|
|
|
start_grab (event, trimmer_cursor);
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
|
2005-09-25 14:42:24 -04:00
|
|
|
trim_op = ContentsTrim;
|
|
|
|
} else {
|
|
|
|
/* These will get overridden for a point trim.*/
|
|
|
|
if (drag_info.current_pointer_frame < (region_start + region_length/2)) {
|
|
|
|
/* closer to start */
|
|
|
|
trim_op = StartTrim;
|
|
|
|
} else if (drag_info.current_pointer_frame > (region_end - region_length/2)) {
|
|
|
|
/* closer to end */
|
|
|
|
trim_op = EndTrim;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (trim_op) {
|
|
|
|
case StartTrim:
|
|
|
|
show_verbose_time_cursor(region_start, 10);
|
|
|
|
break;
|
|
|
|
case EndTrim:
|
|
|
|
show_verbose_time_cursor(region_end, 10);
|
|
|
|
break;
|
|
|
|
case ContentsTrim:
|
|
|
|
show_verbose_time_cursor(drag_info.current_pointer_frame, 10);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2006-07-23 08:03:19 -04:00
|
|
|
RegionView* rv = clicked_regionview;
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t frame_delta = 0;
|
2005-09-25 14:42:24 -04:00
|
|
|
bool left_direction;
|
|
|
|
bool obey_snap = !Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier());
|
|
|
|
|
|
|
|
/* snap modifier works differently here..
|
|
|
|
its' current state has to be passed to the
|
|
|
|
various trim functions in order to work properly
|
|
|
|
*/
|
|
|
|
|
|
|
|
double speed = 1.0;
|
2006-08-16 16:36:14 -04:00
|
|
|
TimeAxisView* tvp = clicked_axisview;
|
2006-07-23 08:03:19 -04:00
|
|
|
RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
|
2007-01-09 18:24:54 -05:00
|
|
|
pair<set<boost::shared_ptr<Playlist> >::iterator,bool> insert_result;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-08-14 04:44:14 -04:00
|
|
|
if (tv && tv->is_track()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
speed = tv->get_diskstream()->speed();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (drag_info.last_pointer_frame > drag_info.current_pointer_frame) {
|
|
|
|
left_direction = true;
|
|
|
|
} else {
|
|
|
|
left_direction = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (obey_snap) {
|
|
|
|
snap_to (drag_info.current_pointer_frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (drag_info.current_pointer_frame == drag_info.last_pointer_frame) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (drag_info.first_move) {
|
|
|
|
|
|
|
|
string trim_type;
|
|
|
|
|
|
|
|
switch (trim_op) {
|
|
|
|
case StartTrim:
|
|
|
|
trim_type = "Region start trim";
|
|
|
|
break;
|
|
|
|
case EndTrim:
|
|
|
|
trim_type = "Region end trim";
|
|
|
|
break;
|
|
|
|
case ContentsTrim:
|
|
|
|
trim_type = "Region content trim";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
begin_reversible_command (trim_type);
|
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
|
2007-03-18 02:07:08 -04:00
|
|
|
(*i)->fake_set_opaque(false);
|
2006-08-29 17:21:48 -04:00
|
|
|
(*i)->region()->freeze ();
|
2006-07-23 08:03:19 -04:00
|
|
|
|
|
|
|
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
|
|
|
|
if (arv)
|
|
|
|
arv->temporarily_hide_envelope ();
|
2006-01-19 13:00:07 -05:00
|
|
|
|
2007-01-09 18:24:54 -05:00
|
|
|
boost::shared_ptr<Playlist> pl = (*i)->region()->playlist();
|
2006-01-19 13:00:07 -05:00
|
|
|
insert_result = motion_frozen_playlists.insert (pl);
|
|
|
|
if (insert_result.second) {
|
2007-08-10 16:55:27 -04:00
|
|
|
session->add_command(new MementoCommand<Playlist>(*pl, &pl->get_state(), 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
|
|
|
pl->freeze();
|
2006-01-19 13:00:07 -05:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (left_direction) {
|
|
|
|
frame_delta = (drag_info.last_pointer_frame - drag_info.current_pointer_frame);
|
|
|
|
} else {
|
|
|
|
frame_delta = (drag_info.current_pointer_frame - drag_info.last_pointer_frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (trim_op) {
|
|
|
|
case StartTrim:
|
2006-08-29 17:21:48 -04:00
|
|
|
if ((left_direction == false) && (drag_info.current_pointer_frame <= rv->region()->first_frame()/speed)) {
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
2007-08-10 16:55:27 -04:00
|
|
|
} else {
|
2006-07-23 08:03:19 -04:00
|
|
|
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
|
2005-09-25 14:42:24 -04:00
|
|
|
single_start_trim (**i, frame_delta, left_direction, obey_snap);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case EndTrim:
|
2006-10-21 15:01:50 -04:00
|
|
|
if ((left_direction == true) && (drag_info.current_pointer_frame > (nframes_t) (rv->region()->last_frame()/speed))) {
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
} else {
|
2006-07-23 08:03:19 -04:00
|
|
|
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
|
2005-09-25 14:42:24 -04:00
|
|
|
single_end_trim (**i, frame_delta, left_direction, obey_snap);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case ContentsTrim:
|
|
|
|
{
|
|
|
|
bool swap_direction = false;
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
|
2005-09-25 14:42:24 -04:00
|
|
|
swap_direction = true;
|
|
|
|
}
|
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin();
|
|
|
|
i != selection->regions.by_layer().end(); ++i)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
single_contents_trim (**i, frame_delta, left_direction, swap_direction, obey_snap);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (trim_op) {
|
|
|
|
case StartTrim:
|
2006-10-21 15:01:50 -04:00
|
|
|
show_verbose_time_cursor((nframes_t) (rv->region()->position()/speed), 10);
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
case EndTrim:
|
2006-10-21 15:01:50 -04:00
|
|
|
show_verbose_time_cursor((nframes_t) (rv->region()->last_frame()/speed), 10);
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
case ContentsTrim:
|
|
|
|
show_verbose_time_cursor(drag_info.current_pointer_frame, 10);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
drag_info.last_pointer_frame = drag_info.current_pointer_frame;
|
|
|
|
drag_info.first_move = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2006-10-21 15:01:50 -04:00
|
|
|
Editor::single_contents_trim (RegionView& rv, nframes_t frame_delta, bool left_direction, bool swap_direction, bool obey_snap)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2006-08-29 17:21:48 -04:00
|
|
|
boost::shared_ptr<Region> region (rv.region());
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
if (region->locked()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t new_bound;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
double speed = 1.0;
|
2006-08-16 16:36:14 -04:00
|
|
|
TimeAxisView* tvp = clicked_axisview;
|
2006-07-23 08:03:19 -04:00
|
|
|
RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-08-14 04:44:14 -04:00
|
|
|
if (tv && tv->is_track()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
speed = tv->get_diskstream()->speed();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (left_direction) {
|
|
|
|
if (swap_direction) {
|
2006-10-21 15:01:50 -04:00
|
|
|
new_bound = (nframes_t) (region->position()/speed) + frame_delta;
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2006-10-21 15:01:50 -04:00
|
|
|
new_bound = (nframes_t) (region->position()/speed) - frame_delta;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (swap_direction) {
|
2006-10-21 15:01:50 -04:00
|
|
|
new_bound = (nframes_t) (region->position()/speed) - frame_delta;
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2006-10-21 15:01:50 -04:00
|
|
|
new_bound = (nframes_t) (region->position()/speed) + frame_delta;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (obey_snap) {
|
|
|
|
snap_to (new_bound);
|
|
|
|
}
|
2006-10-21 15:01:50 -04:00
|
|
|
region->trim_start ((nframes_t) (new_bound * speed), this);
|
2005-09-25 14:42:24 -04:00
|
|
|
rv.region_changed (StartChanged);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2006-10-21 15:01:50 -04:00
|
|
|
Editor::single_start_trim (RegionView& rv, nframes_t frame_delta, bool left_direction, bool obey_snap)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2006-08-29 17:21:48 -04:00
|
|
|
boost::shared_ptr<Region> region (rv.region());
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
if (region->locked()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t new_bound;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
double speed = 1.0;
|
2006-08-16 16:36:14 -04:00
|
|
|
TimeAxisView* tvp = clicked_axisview;
|
2006-08-14 04:44:14 -04:00
|
|
|
RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-08-14 04:44:14 -04:00
|
|
|
if (tv && tv->is_track()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
speed = tv->get_diskstream()->speed();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (left_direction) {
|
2006-10-21 15:01:50 -04:00
|
|
|
new_bound = (nframes_t) (region->position()/speed) - frame_delta;
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2006-10-21 15:01:50 -04:00
|
|
|
new_bound = (nframes_t) (region->position()/speed) + frame_delta;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (obey_snap) {
|
|
|
|
snap_to (new_bound, (left_direction ? 0 : 1));
|
|
|
|
}
|
|
|
|
|
2006-10-21 15:01:50 -04:00
|
|
|
region->trim_front ((nframes_t) (new_bound * speed), this);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
rv.region_changed (Change (LengthChanged|PositionChanged|StartChanged));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2006-10-21 15:01:50 -04:00
|
|
|
Editor::single_end_trim (RegionView& rv, nframes_t frame_delta, bool left_direction, bool obey_snap)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2006-08-29 17:21:48 -04:00
|
|
|
boost::shared_ptr<Region> region (rv.region());
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
if (region->locked()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t new_bound;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
double speed = 1.0;
|
2006-08-16 16:36:14 -04:00
|
|
|
TimeAxisView* tvp = clicked_axisview;
|
2006-08-14 04:44:14 -04:00
|
|
|
RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-08-14 04:44:14 -04:00
|
|
|
if (tv && tv->is_track()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
speed = tv->get_diskstream()->speed();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (left_direction) {
|
2006-10-21 15:01:50 -04:00
|
|
|
new_bound = (nframes_t) ((region->last_frame() + 1)/speed) - frame_delta;
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2006-10-21 15:01:50 -04:00
|
|
|
new_bound = (nframes_t) ((region->last_frame() + 1)/speed) + frame_delta;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (obey_snap) {
|
|
|
|
snap_to (new_bound);
|
|
|
|
}
|
2006-10-21 15:01:50 -04:00
|
|
|
region->trim_end ((nframes_t) (new_bound * speed), this);
|
2005-09-25 14:42:24 -04:00
|
|
|
rv.region_changed (LengthChanged);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::trim_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
if (!drag_info.first_move) {
|
|
|
|
trim_motion_callback (item, event);
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (!selection->selected (clicked_regionview)) {
|
2005-09-25 14:42:24 -04:00
|
|
|
thaw_region_after_trim (*clicked_regionview);
|
|
|
|
} else {
|
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin();
|
|
|
|
i != selection->regions.by_layer().end(); ++i)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
thaw_region_after_trim (**i);
|
2007-03-18 02:07:08 -04:00
|
|
|
(*i)->fake_set_opaque (true);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
2006-01-19 13:00:07 -05:00
|
|
|
|
2007-01-09 18:24:54 -05:00
|
|
|
for (set<boost::shared_ptr<Playlist> >::iterator p = motion_frozen_playlists.begin(); p != motion_frozen_playlists.end(); ++p) {
|
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
|
|
|
(*p)->thaw ();
|
2007-08-10 16:55:27 -04:00
|
|
|
session->add_command (new MementoCommand<Playlist>(*(*p).get(), 0, &(*p)->get_state()));
|
|
|
|
}
|
2006-01-19 13:00:07 -05:00
|
|
|
|
|
|
|
motion_frozen_playlists.clear ();
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
commit_reversible_command();
|
|
|
|
} else {
|
|
|
|
/* no mouse movement */
|
|
|
|
point_trim (event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::point_trim (GdkEvent* event)
|
|
|
|
{
|
2006-07-23 08:03:19 -04:00
|
|
|
RegionView* rv = clicked_regionview;
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t new_bound = drag_info.current_pointer_frame;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
|
|
|
|
snap_to (new_bound);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Choose action dependant on which button was pressed */
|
|
|
|
switch (event->button.button) {
|
|
|
|
case 1:
|
|
|
|
trim_op = StartTrim;
|
|
|
|
begin_reversible_command (_("Start point trim"));
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (selection->selected (rv)) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin();
|
|
|
|
i != selection->regions.by_layer().end(); ++i)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2006-08-29 17:21:48 -04:00
|
|
|
if (!(*i)->region()->locked()) {
|
2007-01-09 18:24:54 -05:00
|
|
|
boost::shared_ptr<Playlist> pl = (*i)->region()->playlist();
|
2007-08-10 16:55:27 -04:00
|
|
|
XMLNode &before = pl->get_state();
|
2006-08-29 17:21:48 -04:00
|
|
|
(*i)->region()->trim_front (new_bound, this);
|
2007-08-10 16:55:27 -04:00
|
|
|
XMLNode &after = pl->get_state();
|
|
|
|
session->add_command(new MementoCommand<Playlist>(*pl.get(), &before, &after));
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
if (!rv->region()->locked()) {
|
2007-01-09 18:24:54 -05:00
|
|
|
boost::shared_ptr<Playlist> pl = rv->region()->playlist();
|
2006-08-09 21:22:45 -04:00
|
|
|
XMLNode &before = pl->get_state();
|
2006-08-29 17:21:48 -04:00
|
|
|
rv->region()->trim_front (new_bound, this);
|
2007-08-10 16:55:27 -04:00
|
|
|
XMLNode &after = pl->get_state();
|
2007-01-09 18:24:54 -05:00
|
|
|
session->add_command(new MementoCommand<Playlist>(*pl.get(), &before, &after));
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
commit_reversible_command();
|
|
|
|
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
trim_op = EndTrim;
|
|
|
|
begin_reversible_command (_("End point trim"));
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (selection->selected (rv)) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2006-08-29 17:21:48 -04:00
|
|
|
if (!(*i)->region()->locked()) {
|
2007-01-09 18:24:54 -05:00
|
|
|
boost::shared_ptr<Playlist> pl = (*i)->region()->playlist();
|
2006-08-09 21:22:45 -04:00
|
|
|
XMLNode &before = pl->get_state();
|
2006-08-29 17:21:48 -04:00
|
|
|
(*i)->region()->trim_end (new_bound, this);
|
2006-08-09 21:22:45 -04:00
|
|
|
XMLNode &after = pl->get_state();
|
2007-01-09 18:24:54 -05:00
|
|
|
session->add_command(new MementoCommand<Playlist>(*pl.get(), &before, &after));
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
if (!rv->region()->locked()) {
|
2007-01-09 18:24:54 -05:00
|
|
|
boost::shared_ptr<Playlist> pl = rv->region()->playlist();
|
2006-08-09 21:22:45 -04:00
|
|
|
XMLNode &before = pl->get_state();
|
2006-08-29 17:21:48 -04:00
|
|
|
rv->region()->trim_end (new_bound, this);
|
2007-08-10 16:55:27 -04:00
|
|
|
XMLNode &after = pl->get_state();
|
2007-01-09 18:24:54 -05:00
|
|
|
session->add_command (new MementoCommand<Playlist>(*pl.get(), &before, &after));
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
commit_reversible_command();
|
|
|
|
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2006-07-23 08:03:19 -04:00
|
|
|
Editor::thaw_region_after_trim (RegionView& rv)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2006-08-29 17:21:48 -04:00
|
|
|
boost::shared_ptr<Region> region (rv.region());
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
if (region->locked()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
region->thaw (_("trimmed region"));
|
2007-08-10 16:55:27 -04:00
|
|
|
XMLNode &after = region->playlist()->get_state();
|
2006-08-29 17:21:48 -04:00
|
|
|
session->add_command (new MementoCommand<Playlist>(*(region->playlist()), 0, &after));
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
AudioRegionView* arv = dynamic_cast<AudioRegionView*>(&rv);
|
|
|
|
if (arv)
|
|
|
|
arv->unhide_envelope ();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::hide_marker (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
Marker* marker;
|
|
|
|
bool is_start;
|
|
|
|
|
2005-11-28 17:36:26 -05:00
|
|
|
if ((marker = static_cast<Marker *> (item->get_data ("marker"))) == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
|
|
|
|
/*NOTREACHED*/
|
|
|
|
}
|
|
|
|
|
|
|
|
Location* location = find_location_from_marker (marker, is_start);
|
|
|
|
location->set_hidden (true, this);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::start_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event, RangeMarkerOp op)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
if (session == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
drag_info.item = item;
|
|
|
|
drag_info.motion_callback = &Editor::drag_range_markerbar_op;
|
|
|
|
drag_info.finished_callback = &Editor::end_range_markerbar_op;
|
|
|
|
|
|
|
|
range_marker_op = op;
|
|
|
|
|
|
|
|
if (!temp_location) {
|
|
|
|
temp_location = new Location;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (op) {
|
|
|
|
case CreateRangeMarker:
|
|
|
|
case CreateTransportMarker:
|
2008-01-10 16:20:59 -05:00
|
|
|
case CreateCDMarker:
|
|
|
|
|
|
|
|
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
|
2005-09-25 14:42:24 -04:00
|
|
|
drag_info.copy = true;
|
|
|
|
} else {
|
|
|
|
drag_info.copy = false;
|
|
|
|
}
|
|
|
|
start_grab (event, selector_cursor);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
show_verbose_time_cursor(drag_info.current_pointer_frame, 10);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::drag_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t start = 0;
|
|
|
|
nframes_t end = 0;
|
2008-02-16 17:43:18 -05:00
|
|
|
ArdourCanvas::SimpleRect *crect;
|
|
|
|
|
|
|
|
switch (range_marker_op) {
|
|
|
|
case CreateRangeMarker:
|
|
|
|
crect = range_bar_drag_rect;
|
|
|
|
break;
|
|
|
|
case CreateTransportMarker:
|
|
|
|
crect = transport_bar_drag_rect;
|
|
|
|
break;
|
|
|
|
case CreateCDMarker:
|
|
|
|
crect = cd_marker_bar_drag_rect;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
cerr << "Error: unknown range marker op passed to Editor::drag_range_markerbar_op ()" << endl;
|
|
|
|
return;
|
|
|
|
break;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
|
|
|
|
snap_to (drag_info.current_pointer_frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* only alter selection if the current frame is
|
|
|
|
different from the last frame position.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (drag_info.current_pointer_frame == drag_info.last_pointer_frame) return;
|
|
|
|
|
|
|
|
switch (range_marker_op) {
|
|
|
|
case CreateRangeMarker:
|
|
|
|
case CreateTransportMarker:
|
2008-01-10 16:20:59 -05:00
|
|
|
case CreateCDMarker:
|
2005-09-25 14:42:24 -04:00
|
|
|
if (drag_info.first_move) {
|
|
|
|
snap_to (drag_info.grab_frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (drag_info.current_pointer_frame < drag_info.grab_frame) {
|
|
|
|
start = drag_info.current_pointer_frame;
|
|
|
|
end = drag_info.grab_frame;
|
|
|
|
} else {
|
|
|
|
end = drag_info.current_pointer_frame;
|
|
|
|
start = drag_info.grab_frame;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* first drag: Either add to the selection
|
2006-06-13 03:27:52 -04:00
|
|
|
or create a new selection.
|
2005-09-25 14:42:24 -04:00
|
|
|
*/
|
|
|
|
|
|
|
|
if (drag_info.first_move) {
|
|
|
|
|
|
|
|
temp_location->set (start, end);
|
|
|
|
|
2005-11-12 17:07:07 -05:00
|
|
|
crect->show ();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
update_marker_drag_item (temp_location);
|
2005-10-28 18:19:45 -04:00
|
|
|
range_marker_drag_rect->show();
|
|
|
|
range_marker_drag_rect->raise_to_top();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-12-12 15:54:55 -05:00
|
|
|
if (event->button.x >= horizontal_adjustment.get_value() + canvas_width) {
|
2005-09-25 14:42:24 -04:00
|
|
|
start_canvas_autoscroll (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (start != end) {
|
|
|
|
temp_location->set (start, end);
|
|
|
|
|
|
|
|
double x1 = frame_to_pixel (start);
|
|
|
|
double x2 = frame_to_pixel (end);
|
2005-11-27 17:35:04 -05:00
|
|
|
crect->property_x1() = x1;
|
|
|
|
crect->property_x2() = x2;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
update_marker_drag_item (temp_location);
|
|
|
|
}
|
|
|
|
|
|
|
|
drag_info.last_pointer_frame = drag_info.current_pointer_frame;
|
|
|
|
drag_info.first_move = false;
|
|
|
|
|
|
|
|
show_verbose_time_cursor(drag_info.current_pointer_frame, 10);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::end_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
Location * newloc = 0;
|
2007-01-09 18:24:54 -05:00
|
|
|
string rangename;
|
2008-01-10 16:20:59 -05:00
|
|
|
int flags;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (!drag_info.first_move) {
|
|
|
|
drag_range_markerbar_op (item, event);
|
|
|
|
|
2005-12-08 13:53:43 -05:00
|
|
|
switch (range_marker_op) {
|
2005-09-25 14:42:24 -04:00
|
|
|
case CreateRangeMarker:
|
2008-01-10 16:20:59 -05:00
|
|
|
case CreateCDMarker:
|
2006-08-09 21:22:45 -04:00
|
|
|
{
|
2005-09-25 14:42:24 -04:00
|
|
|
begin_reversible_command (_("new range marker"));
|
2007-08-10 16:55:27 -04:00
|
|
|
XMLNode &before = session->locations()->get_state();
|
2007-01-09 18:24:54 -05:00
|
|
|
session->locations()->next_available_name(rangename,"unnamed");
|
2008-01-10 16:20:59 -05:00
|
|
|
if (range_marker_op == CreateCDMarker) {
|
|
|
|
flags = Location::IsRangeMarker|Location::IsCDMarker;
|
2008-02-16 17:43:18 -05:00
|
|
|
cd_marker_bar_drag_rect->hide();
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
flags = Location::IsRangeMarker;
|
2008-02-16 17:43:18 -05:00
|
|
|
range_bar_drag_rect->hide();
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
newloc = new Location(temp_location->start(), temp_location->end(), rangename, (Location::Flags) flags);
|
2005-09-25 14:42:24 -04:00
|
|
|
session->locations()->add (newloc, true);
|
2007-08-10 16:55:27 -04:00
|
|
|
XMLNode &after = session->locations()->get_state();
|
2006-08-24 03:37:17 -04:00
|
|
|
session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
|
2005-09-25 14:42:24 -04:00
|
|
|
commit_reversible_command ();
|
|
|
|
|
2005-10-28 18:19:45 -04:00
|
|
|
range_marker_drag_rect->hide();
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
2006-08-09 21:22:45 -04:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
case CreateTransportMarker:
|
|
|
|
// popup menu to pick loop or punch
|
|
|
|
new_transport_marker_context_menu (&event->button, item);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
2006-06-13 03:27:52 -04:00
|
|
|
/* just a click, no pointer movement. remember that context menu stuff was handled elsewhere */
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (Keyboard::no_modifier_keys_pressed (&event->button) && range_marker_op != CreateCDMarker) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t start;
|
|
|
|
nframes_t end;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-06-13 03:27:52 -04:00
|
|
|
start = session->locations()->first_mark_before (drag_info.grab_frame);
|
|
|
|
end = session->locations()->first_mark_after (drag_info.grab_frame);
|
|
|
|
|
|
|
|
if (end == max_frames) {
|
|
|
|
end = session->current_end_frame ();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (start == 0) {
|
|
|
|
start = session->current_start_frame ();
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (mouse_mode) {
|
|
|
|
case MouseObject:
|
|
|
|
/* find the two markers on either side and then make the selection from it */
|
2007-04-19 14:23:23 -04:00
|
|
|
select_all_within (start, end, 0.0f, FLT_MAX, track_views, Selection::Set);
|
2006-06-13 03:27:52 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseRange:
|
|
|
|
/* find the two markers on either side of the click and make the range out of it */
|
|
|
|
selection->set (0, start, end);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
stop_canvas_autoscroll ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::start_mouse_zoom (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
drag_info.item = item;
|
|
|
|
drag_info.motion_callback = &Editor::drag_mouse_zoom;
|
|
|
|
drag_info.finished_callback = &Editor::end_mouse_zoom;
|
|
|
|
|
|
|
|
start_grab (event, zoom_cursor);
|
|
|
|
|
|
|
|
show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::drag_mouse_zoom (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t start;
|
|
|
|
nframes_t end;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
|
|
|
|
snap_to (drag_info.current_pointer_frame);
|
|
|
|
|
|
|
|
if (drag_info.first_move) {
|
|
|
|
snap_to (drag_info.grab_frame);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (drag_info.current_pointer_frame == drag_info.last_pointer_frame) return;
|
|
|
|
|
|
|
|
/* base start and end on initial click position */
|
|
|
|
if (drag_info.current_pointer_frame < drag_info.grab_frame) {
|
|
|
|
start = drag_info.current_pointer_frame;
|
|
|
|
end = drag_info.grab_frame;
|
|
|
|
} else {
|
|
|
|
end = drag_info.current_pointer_frame;
|
|
|
|
start = drag_info.grab_frame;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (start != end) {
|
|
|
|
|
|
|
|
if (drag_info.first_move) {
|
2005-10-28 18:19:45 -04:00
|
|
|
zoom_rect->show();
|
|
|
|
zoom_rect->raise_to_top();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
reposition_zoom_rect(start, end);
|
|
|
|
|
|
|
|
drag_info.last_pointer_frame = drag_info.current_pointer_frame;
|
|
|
|
drag_info.first_move = false;
|
|
|
|
|
|
|
|
show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::end_mouse_zoom (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
if (!drag_info.first_move) {
|
|
|
|
drag_mouse_zoom (item, event);
|
|
|
|
|
|
|
|
if (drag_info.grab_frame < drag_info.last_pointer_frame) {
|
|
|
|
temporal_zoom_by_frame (drag_info.grab_frame, drag_info.last_pointer_frame, "mouse zoom");
|
|
|
|
} else {
|
|
|
|
temporal_zoom_by_frame (drag_info.last_pointer_frame, drag_info.grab_frame, "mouse zoom");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
temporal_zoom_to_frame (false, drag_info.grab_frame);
|
|
|
|
/*
|
|
|
|
temporal_zoom_step (false);
|
|
|
|
center_screen (drag_info.grab_frame);
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
2005-10-28 18:19:45 -04:00
|
|
|
zoom_rect->hide();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2006-10-21 15:01:50 -04:00
|
|
|
Editor::reposition_zoom_rect (nframes_t start, nframes_t end)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
double x1 = frame_to_pixel (start);
|
|
|
|
double x2 = frame_to_pixel (end);
|
2007-01-09 18:24:54 -05:00
|
|
|
double y2 = full_canvas_height - 1.0;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2005-11-27 17:35:04 -05:00
|
|
|
zoom_rect->property_x1() = x1;
|
|
|
|
zoom_rect->property_y1() = 1.0;
|
|
|
|
zoom_rect->property_x2() = x2;
|
|
|
|
zoom_rect->property_y2() = y2;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::start_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
drag_info.item = item;
|
|
|
|
drag_info.motion_callback = &Editor::drag_rubberband_select;
|
|
|
|
drag_info.finished_callback = &Editor::end_rubberband_select;
|
|
|
|
|
|
|
|
start_grab (event, cross_hair_cursor);
|
|
|
|
|
|
|
|
show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::drag_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t start;
|
|
|
|
nframes_t end;
|
2005-09-25 14:42:24 -04:00
|
|
|
double y1;
|
|
|
|
double y2;
|
|
|
|
|
|
|
|
/* use a bigger drag threshold than the default */
|
|
|
|
|
|
|
|
if (abs ((int) (drag_info.current_pointer_frame - drag_info.grab_frame)) < 8) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-02-17 12:49:38 -05:00
|
|
|
if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier()) && Config->get_rubberbanding_snaps_to_grid()) {
|
2007-01-28 12:44:13 -05:00
|
|
|
if (drag_info.first_move) {
|
|
|
|
snap_to (drag_info.grab_frame);
|
|
|
|
}
|
|
|
|
snap_to (drag_info.current_pointer_frame);
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
/* base start and end on initial click position */
|
2007-01-28 12:44:13 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (drag_info.current_pointer_frame < drag_info.grab_frame) {
|
|
|
|
start = drag_info.current_pointer_frame;
|
|
|
|
end = drag_info.grab_frame;
|
|
|
|
} else {
|
|
|
|
end = drag_info.current_pointer_frame;
|
|
|
|
start = drag_info.grab_frame;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (drag_info.current_pointer_y < drag_info.grab_y) {
|
|
|
|
y1 = drag_info.current_pointer_y;
|
|
|
|
y2 = drag_info.grab_y;
|
2007-01-28 12:44:13 -05:00
|
|
|
} else {
|
2005-09-25 14:42:24 -04:00
|
|
|
y2 = drag_info.current_pointer_y;
|
|
|
|
y1 = drag_info.grab_y;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (start != end || y1 != y2) {
|
|
|
|
|
|
|
|
double x1 = frame_to_pixel (start);
|
|
|
|
double x2 = frame_to_pixel (end);
|
|
|
|
|
2005-11-28 17:36:26 -05:00
|
|
|
rubberband_rect->property_x1() = x1;
|
|
|
|
rubberband_rect->property_y1() = y1;
|
|
|
|
rubberband_rect->property_x2() = x2;
|
|
|
|
rubberband_rect->property_y2() = y2;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2005-10-28 18:19:45 -04:00
|
|
|
rubberband_rect->show();
|
|
|
|
rubberband_rect->raise_to_top();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
drag_info.last_pointer_frame = drag_info.current_pointer_frame;
|
|
|
|
drag_info.first_move = false;
|
|
|
|
|
|
|
|
show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::end_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
if (!drag_info.first_move) {
|
|
|
|
|
|
|
|
drag_rubberband_select (item, event);
|
|
|
|
|
|
|
|
double y1,y2;
|
|
|
|
if (drag_info.current_pointer_y < drag_info.grab_y) {
|
|
|
|
y1 = drag_info.current_pointer_y;
|
|
|
|
y2 = drag_info.grab_y;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
y2 = drag_info.current_pointer_y;
|
|
|
|
y1 = drag_info.grab_y;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-03-05 14:39:16 -05:00
|
|
|
Selection::Operation op = Keyboard::selection_type (event->button.state);
|
2005-09-25 14:42:24 -04:00
|
|
|
bool commit;
|
|
|
|
|
2007-01-28 12:44:13 -05:00
|
|
|
begin_reversible_command (_("rubberband selection"));
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (drag_info.grab_frame < drag_info.last_pointer_frame) {
|
2007-04-19 14:23:23 -04:00
|
|
|
commit = select_all_within (drag_info.grab_frame, drag_info.last_pointer_frame, y1, y2, track_views, op);
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2007-04-19 14:23:23 -04:00
|
|
|
commit = select_all_within (drag_info.last_pointer_frame, drag_info.grab_frame, y1, y2, track_views, op);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (commit) {
|
|
|
|
commit_reversible_command ();
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
2007-01-28 12:44:13 -05:00
|
|
|
selection->clear_tracks();
|
2006-07-23 08:03:19 -04:00
|
|
|
selection->clear_regions();
|
2005-09-25 14:42:24 -04:00
|
|
|
selection->clear_points ();
|
|
|
|
selection->clear_lines ();
|
|
|
|
}
|
|
|
|
|
2005-10-28 18:19:45 -04:00
|
|
|
rubberband_rect->hide();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
gint
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::mouse_rename_region (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2005-09-25 16:33:00 -04:00
|
|
|
using namespace Gtkmm2ext;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
ArdourPrompter prompter (false);
|
|
|
|
|
|
|
|
prompter.set_prompt (_("Name for region:"));
|
2006-08-29 17:21:48 -04:00
|
|
|
prompter.set_initial_text (clicked_regionview->region()->name());
|
2006-04-19 16:42:17 -04:00
|
|
|
prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
|
2006-04-22 11:28:59 -04:00
|
|
|
prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
|
2005-09-25 14:42:24 -04:00
|
|
|
prompter.show_all ();
|
2005-10-26 21:10:36 -04:00
|
|
|
switch (prompter.run ()) {
|
2006-01-13 14:48:55 -05:00
|
|
|
case Gtk::RESPONSE_ACCEPT:
|
2007-08-10 16:55:27 -04:00
|
|
|
string str;
|
2005-10-26 21:10:36 -04:00
|
|
|
prompter.get_result(str);
|
|
|
|
if (str.length()) {
|
2007-04-29 13:23:11 -04:00
|
|
|
clicked_regionview->region()->set_name (str);
|
2005-10-26 21:10:36 -04:00
|
|
|
}
|
|
|
|
break;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::start_time_fx (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
drag_info.item = item;
|
|
|
|
drag_info.motion_callback = &Editor::time_fx_motion;
|
|
|
|
drag_info.finished_callback = &Editor::end_time_fx;
|
|
|
|
|
|
|
|
start_grab (event);
|
|
|
|
|
|
|
|
show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::time_fx_motion (ArdourCanvas::Item *item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2006-07-23 08:03:19 -04:00
|
|
|
RegionView* rv = clicked_regionview;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
|
|
|
|
snap_to (drag_info.current_pointer_frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (drag_info.current_pointer_frame == drag_info.last_pointer_frame) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
if (drag_info.current_pointer_frame > rv->region()->position()) {
|
|
|
|
rv->get_time_axis_view().show_timestretch (rv->region()->position(), drag_info.current_pointer_frame);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
drag_info.last_pointer_frame = drag_info.current_pointer_frame;
|
|
|
|
drag_info.first_move = false;
|
|
|
|
|
|
|
|
show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-11-23 12:21:12 -05:00
|
|
|
Editor::end_time_fx (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
clicked_regionview->get_time_axis_view().hide_timestretch ();
|
|
|
|
|
|
|
|
if (drag_info.first_move) {
|
|
|
|
return;
|
|
|
|
}
|
2007-10-11 18:07:47 -04:00
|
|
|
|
|
|
|
if (drag_info.last_pointer_frame < clicked_regionview->region()->position()) {
|
|
|
|
/* backwards drag of the left edge - not usable */
|
|
|
|
return;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2006-10-21 15:01:50 -04:00
|
|
|
nframes_t newlen = drag_info.last_pointer_frame - clicked_regionview->region()->position();
|
2008-01-16 19:37:46 -05:00
|
|
|
|
|
|
|
float percentage = (double) newlen / (double) clicked_regionview->region()->length();
|
|
|
|
|
|
|
|
#ifndef USE_RUBBERBAND
|
|
|
|
// Soundtouch uses percentage / 100 instead of normal (/ 1)
|
|
|
|
if (clicked_regionview->region()->data_type() == DataType::AUDIO) {
|
|
|
|
percentage = (float) ((double) newlen - (double) clicked_regionview->region()->length()) / ((double) newlen) * 100.0f;
|
2008-01-10 16:20:59 -05:00
|
|
|
#endif
|
2008-01-16 19:37:46 -05:00
|
|
|
}
|
2008-01-10 16:20:59 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
begin_reversible_command (_("timestretch"));
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
// XXX how do timeFX on multiple regions ?
|
|
|
|
|
|
|
|
RegionSelection rs;
|
|
|
|
rs.add (clicked_regionview);
|
|
|
|
|
|
|
|
if (time_stretch (rs, percentage) == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
session->commit_reversible_command ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2006-10-21 15:01:50 -04:00
|
|
|
Editor::mouse_brush_insert_region (RegionView* rv, nframes_t pos)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
/* no brushing without a useful snap setting */
|
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
// FIXME
|
|
|
|
AudioRegionView* arv = dynamic_cast<AudioRegionView*>(rv);
|
|
|
|
assert(arv);
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
switch (snap_mode) {
|
|
|
|
case SnapMagnetic:
|
|
|
|
return; /* can't work because it allows region to be placed anywhere */
|
|
|
|
default:
|
|
|
|
break; /* OK */
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (snap_type) {
|
|
|
|
case SnapToMark:
|
|
|
|
return;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* don't brush a copy over the original */
|
|
|
|
|
2006-08-29 17:21:48 -04:00
|
|
|
if (pos == rv->region()->position()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(&arv->get_time_axis_view());
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
if (rtv == 0 || !rtv->is_track()) {
|
2005-09-25 14:42:24 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-03-18 02:07:08 -04:00
|
|
|
boost::shared_ptr<Playlist> playlist = rtv->playlist();
|
|
|
|
double speed = rtv->get_diskstream()->speed();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2007-08-10 16:55:27 -04:00
|
|
|
XMLNode &before = playlist->get_state();
|
2006-10-21 15:01:50 -04:00
|
|
|
playlist->add_region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (arv->audio_region())), (nframes_t) (pos * speed));
|
2007-08-10 16:55:27 -04:00
|
|
|
XMLNode &after = playlist->get_state();
|
2007-01-09 18:24:54 -05:00
|
|
|
session->add_command(new MementoCommand<Playlist>(*playlist.get(), &before, &after));
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
// playlist is frozen, so we have to update manually
|
|
|
|
|
2006-10-21 18:59:29 -04:00
|
|
|
playlist->Modified(); /* EMIT SIGNAL */
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
gint
|
|
|
|
Editor::track_height_step_timeout ()
|
|
|
|
{
|
|
|
|
struct timeval now;
|
|
|
|
struct timeval delta;
|
|
|
|
|
|
|
|
gettimeofday (&now, 0);
|
|
|
|
timersub (&now, &last_track_height_step_timestamp, &delta);
|
|
|
|
|
|
|
|
if (delta.tv_sec * 1000000 + delta.tv_usec > 250000) { /* milliseconds */
|
|
|
|
current_stepping_trackview = 0;
|
2006-03-07 21:50:53 -05:00
|
|
|
return false;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2007-10-11 18:07:47 -04:00
|
|
|
|