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>
|
|
|
|
|
2009-02-25 13:26:51 -05:00
|
|
|
#include "pbd/error.h"
|
2005-09-25 16:33:00 -04:00
|
|
|
#include <gtkmm2ext/utils.h>
|
2008-10-04 23:22:29 -04:00
|
|
|
#include <gtkmm2ext/tearoff.h>
|
2009-02-25 13:26:51 -05:00
|
|
|
#include "pbd/memento_command.h"
|
|
|
|
#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"
|
2008-12-18 12:46:28 -05:00
|
|
|
#include "control_point_dialog.h"
|
2009-05-30 14:25:59 -04:00
|
|
|
#include "editor_drag.h"
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-02-25 13:26:51 -05:00
|
|
|
#include "ardour/types.h"
|
|
|
|
#include "ardour/profile.h"
|
|
|
|
#include "ardour/route.h"
|
|
|
|
#include "ardour/audio_track.h"
|
|
|
|
#include "ardour/audio_diskstream.h"
|
|
|
|
#include "ardour/midi_diskstream.h"
|
|
|
|
#include "ardour/playlist.h"
|
|
|
|
#include "ardour/audioplaylist.h"
|
|
|
|
#include "ardour/audioregion.h"
|
|
|
|
#include "ardour/midi_region.h"
|
|
|
|
#include "ardour/dB.h"
|
|
|
|
#include "ardour/utils.h"
|
|
|
|
#include "ardour/region_factory.h"
|
|
|
|
#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-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;
|
2008-03-17 16:54:03 -04:00
|
|
|
Glib::RefPtr<Gdk::Window> canvas_window = const_cast<Editor*>(this)->track_canvas->get_window();
|
2007-11-07 20:40:25 -05:00
|
|
|
Glib::RefPtr<const Gdk::Window> pointer_window;
|
2008-04-11 10:06:50 -04:00
|
|
|
|
|
|
|
if (!canvas_window) {
|
|
|
|
return false;
|
|
|
|
}
|
2007-11-07 20:40:25 -05:00
|
|
|
|
|
|
|
pointer_window = canvas_window->get_pointer (x, y, mask);
|
|
|
|
|
2008-03-17 16:54:03 -04:00
|
|
|
if (pointer_window == track_canvas->get_bin_window()) {
|
2008-09-10 17:27:39 -04:00
|
|
|
wx = x;
|
|
|
|
wy = y;
|
2007-11-07 20:40:25 -05:00
|
|
|
in_track_canvas = true;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
in_track_canvas = false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
2009-06-08 15:28:51 -04:00
|
|
|
Editor::event_frame (GdkEvent const * 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:
|
2008-09-10 17:27:39 -04:00
|
|
|
|
|
|
|
*pcx = event->button.x;
|
|
|
|
*pcy = event->button.y;
|
|
|
|
_trackview_group->w2i(*pcx, *pcy);
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
case GDK_MOTION_NOTIFY:
|
2008-09-10 17:27:39 -04:00
|
|
|
|
|
|
|
*pcx = event->motion.x;
|
|
|
|
*pcy = event->motion.y;
|
|
|
|
_trackview_group->w2i(*pcx, *pcy);
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
case GDK_ENTER_NOTIFY:
|
|
|
|
case GDK_LEAVE_NOTIFY:
|
2008-03-17 16:54:03 -04: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:
|
2008-03-17 16:54:03 -04:00
|
|
|
// track_canvas->w2c(event->key.x, event->key.y, *pcx, *pcy);
|
2006-01-28 08:33:54 -05:00
|
|
|
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:
|
|
|
|
break;
|
|
|
|
}
|
2008-09-10 17:27:39 -04:00
|
|
|
return grabber_cursor;
|
2008-02-16 17:43:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
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()) {
|
2008-03-17 16:54:03 -04:00
|
|
|
track_canvas->get_window()->set_cursor(*current_canvas_cursor);
|
2008-02-16 17:43:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
|
|
|
Editor::set_mouse_mode (MouseMode m, bool force)
|
|
|
|
{
|
2009-05-30 14:25:59 -04:00
|
|
|
if (_drag) {
|
2005-09-25 14:42:24 -04:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2008-10-04 23:22:29 -04:00
|
|
|
if (midi_tools_tearoff) {
|
|
|
|
if (mouse_mode == MouseNote) {
|
|
|
|
midi_tools_tearoff->show();
|
|
|
|
} else {
|
|
|
|
midi_tools_tearoff->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:
|
2008-12-12 09:43:24 -05:00
|
|
|
if (next) {
|
|
|
|
if (Profile->get_sae()) {
|
|
|
|
set_mouse_mode (MouseZoom);
|
|
|
|
} else {
|
|
|
|
set_mouse_mode (MouseRange);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
set_mouse_mode (MouseTimeFX);
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseRange:
|
|
|
|
if (next) set_mouse_mode (MouseZoom);
|
|
|
|
else set_mouse_mode (MouseObject);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseZoom:
|
2008-12-12 09:43:24 -05:00
|
|
|
if (next) {
|
|
|
|
if (Profile->get_sae()) {
|
|
|
|
set_mouse_mode (MouseTimeFX);
|
|
|
|
} else {
|
|
|
|
set_mouse_mode (MouseGain);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (Profile->get_sae()) {
|
|
|
|
set_mouse_mode (MouseObject);
|
|
|
|
} else {
|
|
|
|
set_mouse_mode (MouseRange);
|
|
|
|
}
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseGain:
|
|
|
|
if (next) set_mouse_mode (MouseTimeFX);
|
|
|
|
else set_mouse_mode (MouseZoom);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseTimeFX:
|
2008-12-12 09:43:24 -05:00
|
|
|
if (next) {
|
|
|
|
set_mouse_mode (MouseAudition);
|
|
|
|
} else {
|
|
|
|
if (Profile->get_sae()) {
|
|
|
|
set_mouse_mode (MouseZoom);
|
|
|
|
} else {
|
|
|
|
set_mouse_mode (MouseGain);
|
|
|
|
}
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
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
|
|
|
|
2008-03-26 07:11:47 -04:00
|
|
|
case MidiEditResize:
|
|
|
|
if (midi_tool_resize_button.get_active())
|
|
|
|
set_midi_edit_mode (m);
|
|
|
|
break;
|
|
|
|
|
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)
|
|
|
|
{
|
2009-05-30 14:25:59 -04:00
|
|
|
if (_drag) {
|
2007-08-08 15:13:36 -04:00
|
|
|
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;
|
|
|
|
|
2008-03-26 07:11:47 -04:00
|
|
|
case MidiEditResize:
|
|
|
|
midi_tool_resize_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()) {
|
2008-03-17 16:54:03 -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;
|
|
|
|
|
2008-03-26 07:11:47 -04:00
|
|
|
case MidiEditResize:
|
|
|
|
current_canvas_cursor = midi_resize_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
|
|
|
{
|
2008-12-12 09:43:24 -05:00
|
|
|
/* in object/audition/timefx/gain-automation 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.
|
2005-09-25 14:42:24 -04:00
|
|
|
|
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) &&
|
2008-12-12 09:43:24 -05:00
|
|
|
(mouse_mode != MouseGain) &&
|
2007-03-18 02:07:08 -04:00
|
|
|
(mouse_mode != MouseRange)) ||
|
|
|
|
|
2008-05-02 14:35:05 -04:00
|
|
|
((event->type != GDK_BUTTON_PRESS && event->type != GDK_BUTTON_RELEASE) || event->button.button > 3)) {
|
2006-06-13 03:27:52 -04:00
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
2008-12-12 09:43:24 -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)
|
|
|
|
{
|
2008-09-10 11:03:30 -04:00
|
|
|
Glib::RefPtr<Gdk::Window> canvas_window = const_cast<Editor*>(this)->track_canvas->get_window();
|
2008-12-12 09:43:24 -05:00
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
if (canvas_window) {
|
|
|
|
Glib::RefPtr<const Gdk::Window> pointer_window;
|
|
|
|
int x, y;
|
|
|
|
double wx, wy;
|
|
|
|
Gdk::ModifierType mask;
|
|
|
|
|
|
|
|
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);
|
|
|
|
allow_vertical_scroll = true;
|
|
|
|
} else {
|
|
|
|
allow_vertical_scroll = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-17 16:54:03 -04:00
|
|
|
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);
|
2008-12-12 09:43:24 -05:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
if (_drag == 0 &&
|
2005-09-25 14:42:24 -04:00
|
|
|
(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) {
|
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
if (_drag) {
|
|
|
|
_drag->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.
|
|
|
|
*/
|
2009-06-14 09:31:46 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
switch (item_type) {
|
|
|
|
case PlayheadCursorItem:
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new CursorDrag (this, item, true);
|
|
|
|
_drag->start_grab (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 {
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new MarkerDrag (this, item);
|
|
|
|
_drag->start_grab (event);
|
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
|
|
|
|
|
|
|
case TempoMarkerItem:
|
2009-06-09 04:41:43 -04:00
|
|
|
assert (_drag == 0);
|
2009-05-30 14:25:59 -04:00
|
|
|
_drag = new TempoMarkerDrag (
|
|
|
|
this,
|
|
|
|
item,
|
|
|
|
Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)
|
|
|
|
);
|
|
|
|
_drag->start_grab (event);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
case MeterMarkerItem:
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
|
|
|
|
_drag = new MeterMarkerDrag (
|
|
|
|
this,
|
|
|
|
item,
|
|
|
|
Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)
|
|
|
|
);
|
|
|
|
|
|
|
|
_drag->start_grab (event);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-12-12 09:43:24 -05:00
|
|
|
case MarkerBarItem:
|
2005-09-25 14:42:24 -04:00
|
|
|
case TempoBarItem:
|
|
|
|
case MeterBarItem:
|
2008-12-12 09:43:24 -05:00
|
|
|
if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new CursorDrag (this, &playhead_cursor->canvas_item, false);
|
|
|
|
_drag->start_grab (event);
|
2008-12-12 09:43:24 -05:00
|
|
|
}
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2008-12-12 09:43:24 -05:00
|
|
|
break;
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
case RangeMarkerBarItem:
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
2009-06-14 09:31:46 -04:00
|
|
|
if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
|
2009-05-30 14:25:59 -04:00
|
|
|
_drag = new CursorDrag (this, &playhead_cursor->canvas_item, false);
|
2008-12-12 09:43:24 -05:00
|
|
|
} else {
|
2009-05-30 14:25:59 -04:00
|
|
|
_drag = new RangeMarkerBarDrag (this, item, RangeMarkerBarDrag::CreateRangeMarker);
|
2008-12-12 09:43:24 -05:00
|
|
|
}
|
2009-05-30 14:25:59 -04:00
|
|
|
_drag->start_grab (event);
|
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:
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
2008-12-12 09:43:24 -05:00
|
|
|
if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
|
2009-05-30 14:25:59 -04:00
|
|
|
_drag = new CursorDrag (this, &playhead_cursor->canvas_item, false);
|
2008-12-12 09:43:24 -05:00
|
|
|
} else {
|
2009-05-30 14:25:59 -04:00
|
|
|
_drag = new RangeMarkerBarDrag (this, item, RangeMarkerBarDrag::CreateCDMarker);
|
2008-12-12 09:43:24 -05:00
|
|
|
}
|
2009-05-30 14:25:59 -04:00
|
|
|
_drag->start_grab (event);
|
2008-01-10 16:20:59 -05:00
|
|
|
return true;
|
|
|
|
break;
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
case TransportMarkerBarItem:
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
2008-12-12 09:43:24 -05:00
|
|
|
if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
|
2009-05-30 14:25:59 -04:00
|
|
|
_drag = new CursorDrag (this, &playhead_cursor->canvas_item, false);
|
2008-12-12 09:43:24 -05:00
|
|
|
} else {
|
2009-05-30 14:25:59 -04:00
|
|
|
_drag = new RangeMarkerBarDrag (this, item, RangeMarkerBarDrag::CreateTransportMarker);
|
2008-12-12 09:43:24 -05:00
|
|
|
}
|
2009-05-30 14:25:59 -04:00
|
|
|
_drag->start_grab (event);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
2008-12-12 09:43:24 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (mouse_mode) {
|
|
|
|
case MouseRange:
|
|
|
|
switch (item_type) {
|
|
|
|
case StartSelectionTrimItem:
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new SelectionDrag (this, item, SelectionDrag::SelectionStartTrim);
|
|
|
|
_drag->start_grab (event);
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case EndSelectionTrimItem:
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new SelectionDrag (this, item, SelectionDrag::SelectionEndTrim);
|
|
|
|
_drag->start_grab (event);
|
2005-09-25 14:42:24 -04:00
|
|
|
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 */
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new SelectionDrag (this, item, SelectionDrag::SelectionMove);
|
|
|
|
_drag->start_grab (event);
|
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 */
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new SelectionDrag (this, item, SelectionDrag::CreateSelection);
|
|
|
|
_drag->start_grab (event);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new SelectionDrag (this, item, SelectionDrag::CreateSelection);
|
|
|
|
_drag->start_grab (event);
|
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
|
|
|
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) {
|
2009-05-30 14:25:59 -04:00
|
|
|
|
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new RubberbandSelectDrag (this, item);
|
|
|
|
_drag->start_grab (event);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
} else if (event->type == GDK_BUTTON_PRESS) {
|
|
|
|
|
|
|
|
switch (item_type) {
|
|
|
|
case FadeInHandleItem:
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new FadeInDrag (this, item, reinterpret_cast<RegionView*> (item->get_data("regionview")), selection->regions);
|
|
|
|
_drag->start_grab (event);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
case FadeOutHandleItem:
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new FadeOutDrag (this, item, reinterpret_cast<RegionView*> (item->get_data("regionview")), selection->regions);
|
|
|
|
_drag->start_grab (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)) {
|
2009-05-30 14:25:59 -04:00
|
|
|
start_region_copy_grab (item, event, clicked_regionview);
|
2005-09-25 14:42:24 -04:00
|
|
|
} else if (Keyboard::the_keyboard().key_is_down (GDK_b)) {
|
2009-05-30 14:25:59 -04:00
|
|
|
start_region_brush_grab (item, event, clicked_regionview);
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2009-05-30 14:25:59 -04:00
|
|
|
start_region_grab (item, event, clicked_regionview);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2006-07-23 08:03:19 -04:00
|
|
|
case RegionViewNameHighlight:
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new TrimDrag (this, item, clicked_regionview, selection->regions.by_layer());
|
|
|
|
_drag->start_grab (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 */
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new TrimDrag (this, clicked_regionview->get_name_highlight(), clicked_regionview, selection->regions.by_layer());
|
|
|
|
_drag->start_grab (event);
|
2008-09-10 17:27:39 -04:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
2007-06-30 14:41:50 -04:00
|
|
|
case ControlPointItem:
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new ControlPointDrag (this, item);
|
|
|
|
_drag->start_grab (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:
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new LineDrag (this, item);
|
|
|
|
_drag->start_grab (event);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case StreamItem:
|
|
|
|
case AutomationTrackItem:
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new RubberbandSelectDrag (this, item);
|
|
|
|
_drag->start_grab (event);
|
2005-09-25 14:42:24 -04:00
|
|
|
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:
|
2008-12-12 09:43:24 -05:00
|
|
|
/* start a grab so that if we finish after moving
|
|
|
|
we can tell what happened.
|
|
|
|
*/
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new RegionGainDrag (this, item);
|
|
|
|
_drag->start_grab (event, current_canvas_cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GainLineItem:
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new LineDrag (this, item);
|
|
|
|
_drag->start_grab (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:
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new ControlPointDrag (this, item);
|
|
|
|
_drag->start_grab (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:
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new ControlPointDrag (this, item);
|
|
|
|
_drag->start_grab (event);
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
2007-06-30 14:41:50 -04:00
|
|
|
case AutomationLineItem:
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new LineDrag (this, item);
|
|
|
|
_drag->start_grab (event);
|
2005-09-25 14:42:24 -04:00
|
|
|
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) {
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new MouseZoomDrag (this, item);
|
|
|
|
_drag->start_grab (event);
|
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
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseTimeFX:
|
|
|
|
if (item_type == RegionItem) {
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new TimeFXDrag (this, item, clicked_regionview, selection->regions.by_layer());
|
|
|
|
_drag->start_grab (event);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MouseAudition:
|
2009-06-10 09:58:22 -04:00
|
|
|
_drag = new ScrubDrag (this, item);
|
|
|
|
_drag->start_grab (event);
|
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-03-17 16:54:03 -04:00
|
|
|
track_canvas->get_window()->set_cursor (*transparent_cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
break;
|
|
|
|
|
2007-10-14 01:45:31 -04:00
|
|
|
case MouseNote:
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new RegionCreateDrag (this, item, clicked_axisview);
|
|
|
|
_drag->start_grab (event);
|
2007-10-14 01:45:31 -04:00
|
|
|
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)) {
|
2009-05-30 14:25:59 -04:00
|
|
|
start_region_copy_grab (item, event, clicked_regionview);
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2009-05-30 14:25:59 -04:00
|
|
|
start_region_grab (item, event, clicked_regionview);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
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:
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new ControlPointDrag (this, item);
|
|
|
|
_drag->start_grab (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:
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new TrimDrag (this, item, clicked_regionview, selection->regions.by_layer());
|
|
|
|
_drag->start_grab (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:
|
2009-05-30 14:25:59 -04:00
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new TrimDrag (this, clicked_regionview->get_name_highlight(), clicked_regionview, selection->regions.by_layer());
|
|
|
|
_drag->start_grab (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
|
|
|
{
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_t where = event_frame (event, 0, 0);
|
2008-02-16 17:43:18 -05:00
|
|
|
AutomationTimeAxisView* atv = 0;
|
2008-12-12 09:43:24 -05:00
|
|
|
|
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 ... */
|
|
|
|
|
2009-06-01 20:39:57 -04:00
|
|
|
bool were_dragging = false;
|
2009-05-30 14:25:59 -04:00
|
|
|
if (_drag) {
|
|
|
|
bool const r = _drag->end_grab (event);
|
|
|
|
delete _drag;
|
|
|
|
_drag = 0;
|
|
|
|
if (r) {
|
2005-09-25 14:42:24 -04:00
|
|
|
/* grab dragged, so do nothing else */
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2009-06-01 20:39:57 -04:00
|
|
|
|
|
|
|
were_dragging = 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 */
|
2008-12-12 09:43:24 -05:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
if (_drag == 0 && Keyboard::is_edit_event (&event->button)) {
|
2005-09-25 14:42:24 -04:00
|
|
|
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;
|
|
|
|
|
2008-12-18 12:46:28 -05:00
|
|
|
case ControlPointItem:
|
|
|
|
edit_control_point (item);
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
/* context menu events get handled here */
|
|
|
|
|
|
|
|
if (Keyboard::is_context_menu_event (&event->button)) {
|
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
if (_drag == 0) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
/* 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:
|
2009-03-21 09:08:06 -04:00
|
|
|
popup_ruler_menu (where, item_type);
|
2005-09-25 14:42:24 -04:00
|
|
|
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 */
|
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
if (_drag == 0 && Keyboard::is_delete_event (&event->button)) {
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
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:
|
2008-12-12 09:43:24 -05:00
|
|
|
if (!_dragging_playhead) {
|
|
|
|
if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
|
|
|
|
snap_to (where, 0, true);
|
|
|
|
}
|
|
|
|
mouse_add_new_marker (where);
|
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
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
case CdMarkerBarItem:
|
2008-12-12 09:43:24 -05:00
|
|
|
if (!_dragging_playhead) {
|
|
|
|
// 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);
|
2008-01-10 16:20:59 -05:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
case TempoBarItem:
|
2008-12-12 09:43:24 -05:00
|
|
|
if (!_dragging_playhead) {
|
|
|
|
if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
|
|
|
|
snap_to (where);
|
|
|
|
}
|
|
|
|
mouse_add_new_tempo_event (where);
|
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
|
|
|
|
|
|
|
case MeterBarItem:
|
2008-12-12 09:43:24 -05:00
|
|
|
if (!_dragging_playhead) {
|
|
|
|
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;
|
|
|
|
}
|
2008-12-12 09:43:24 -05:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
switch (mouse_mode) {
|
|
|
|
case MouseObject:
|
|
|
|
switch (item_type) {
|
|
|
|
case AutomationTrackItem:
|
2009-06-11 12:46:03 -04:00
|
|
|
atv = dynamic_cast<AutomationTimeAxisView*>(clicked_axisview);
|
2008-02-16 17:43:18 -05:00
|
|
|
if (atv) {
|
|
|
|
atv->add_automation_event (item, event, where, event->button.y);
|
2009-06-11 12:46:03 -04:00
|
|
|
}
|
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:
|
2008-12-12 09:43:24 -05:00
|
|
|
/* check that we didn't drag before releasing, since
|
|
|
|
its really annoying to create new control
|
|
|
|
points when doing this.
|
|
|
|
*/
|
2009-06-01 20:39:57 -04:00
|
|
|
if (were_dragging) {
|
2008-12-12 09:43:24 -05: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:
|
2008-03-17 16:54:03 -04: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);
|
2008-10-03 14:24:38 -04:00
|
|
|
at_x += 10.0;
|
|
|
|
at_y += 10.0;
|
2007-03-18 02:07:08 -04:00
|
|
|
|
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
|
|
|
|
2009-06-10 17:09:46 -04:00
|
|
|
if (is_drawable() && dynamic_cast<ScrubDrag*> (_drag) == 0) {
|
2008-03-17 16:54:03 -04:00
|
|
|
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()) {
|
2008-03-17 16:54:03 -04: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()) {
|
2008-03-17 16:54:03 -04:00
|
|
|
track_canvas->get_window()->set_cursor (*fader_cursor);
|
2007-03-18 02:07:08 -04:00
|
|
|
}
|
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) {
|
2008-03-17 16:54:03 -04: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()) {
|
2008-03-17 16:54:03 -04: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:
|
2008-03-17 16:54:03 -04:00
|
|
|
track_canvas->get_window()->set_cursor (*grabber_edit_point_cursor);
|
2008-02-16 17:43:18 -05:00
|
|
|
break;
|
|
|
|
default:
|
2008-03-17 16:54:03 -04:00
|
|
|
track_canvas->get_window()->set_cursor (*grabber_cursor);
|
2008-02-16 17:43:18 -05:00
|
|
|
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()) {
|
2008-03-17 16:54:03 -04: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;
|
|
|
|
}
|
|
|
|
|
2008-03-17 16:54:03 -04: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()) {
|
2008-09-10 17:27:39 -04:00
|
|
|
track_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()) {
|
2008-09-10 17:27:39 -04:00
|
|
|
track_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()) {
|
2008-03-17 16:54:03 -04:00
|
|
|
track_canvas->get_window()->set_cursor (*current_canvas_cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
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()) {
|
2008-03-17 16:54:03 -04:00
|
|
|
track_canvas->get_window()->set_cursor (*current_canvas_cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
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()) {
|
2008-03-17 16:54:03 -04:00
|
|
|
track_canvas->get_window()->set_cursor (*current_canvas_cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
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) {
|
2008-03-17 16:54:03 -04:00
|
|
|
track_canvas->get_window()->set_cursor (*current_canvas_cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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()) {
|
2008-12-12 09:43:24 -05:00
|
|
|
track_canvas->get_window()->set_cursor (*current_canvas_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()) {
|
2008-09-10 17:27:39 -04:00
|
|
|
track_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()) {
|
2008-03-17 16:54:03 -04:00
|
|
|
track_canvas->get_window()->set_cursor (*current_canvas_cursor);
|
2005-09-25 14:42:24 -04:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2008-04-11 10:06:50 -04:00
|
|
|
void
|
|
|
|
Editor::scrub ()
|
|
|
|
{
|
|
|
|
double delta;
|
|
|
|
|
|
|
|
if (scrubbing_direction == 0) {
|
|
|
|
/* first move */
|
2009-05-30 14:25:59 -04:00
|
|
|
session->request_locate (_drag->current_pointer_frame(), false);
|
2008-04-11 10:06:50 -04:00
|
|
|
session->request_transport_speed (0.1);
|
|
|
|
scrubbing_direction = 1;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
if (last_scrub_x > _drag->current_pointer_x()) {
|
2008-04-11 10:06:50 -04:00
|
|
|
|
|
|
|
/* pointer moved to the left */
|
|
|
|
|
|
|
|
if (scrubbing_direction > 0) {
|
|
|
|
|
|
|
|
/* we reversed direction to go backwards */
|
|
|
|
|
|
|
|
scrub_reversals++;
|
2009-05-30 14:25:59 -04:00
|
|
|
scrub_reverse_distance += (int) (last_scrub_x - _drag->current_pointer_x());
|
2008-04-11 10:06:50 -04:00
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
/* still moving to the left (backwards) */
|
|
|
|
|
|
|
|
scrub_reversals = 0;
|
|
|
|
scrub_reverse_distance = 0;
|
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
delta = 0.01 * (last_scrub_x - _drag->current_pointer_x());
|
2008-04-11 10:06:50 -04:00
|
|
|
session->request_transport_speed (session->transport_speed() - delta);
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
/* pointer moved to the right */
|
|
|
|
|
|
|
|
if (scrubbing_direction < 0) {
|
|
|
|
/* we reversed direction to go forward */
|
|
|
|
|
|
|
|
scrub_reversals++;
|
2009-05-30 14:25:59 -04:00
|
|
|
scrub_reverse_distance += (int) (_drag->current_pointer_x() - last_scrub_x);
|
2008-04-11 10:06:50 -04:00
|
|
|
|
|
|
|
} else {
|
|
|
|
/* still moving to the right */
|
|
|
|
|
|
|
|
scrub_reversals = 0;
|
|
|
|
scrub_reverse_distance = 0;
|
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
delta = 0.01 * (_drag->current_pointer_x() - last_scrub_x);
|
2008-04-11 10:06:50 -04:00
|
|
|
session->request_transport_speed (session->transport_speed() + delta);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
scrub_reverse_distance = 0;
|
|
|
|
scrub_reversals = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
last_scrub_x = _drag->current_pointer_x();
|
2008-04-11 10:06:50 -04:00
|
|
|
}
|
|
|
|
|
2005-11-22 00:10:12 -05:00
|
|
|
bool
|
2009-05-30 14:25:59 -04:00
|
|
|
Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, 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.
|
|
|
|
*/
|
2008-09-10 17:27:39 -04:00
|
|
|
|
2008-03-17 16:54:03 -04:00
|
|
|
track_canvas->get_pointer (x, y);
|
2008-04-11 10:06:50 -04:00
|
|
|
}
|
2008-09-10 11:03:30 -04:00
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
bool handled = false;
|
|
|
|
if (_drag) {
|
|
|
|
handled = _drag->motion_handler (event, from_autoscroll);
|
|
|
|
}
|
2006-01-02 15:27:51 -05:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
if (!handled) {
|
|
|
|
return false;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2005-10-26 21:10:36 -04:00
|
|
|
track_canvas_motion (event);
|
2006-03-07 21:50:53 -05:00
|
|
|
return true;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2008-04-11 10:06:50 -04:00
|
|
|
void
|
2009-05-30 14:25:59 -04:00
|
|
|
Editor::remove_gain_control_point (ArdourCanvas::Item*item, GdkEvent* event)
|
2008-04-11 10:06:50 -04:00
|
|
|
{
|
2009-05-30 14:25:59 -04:00
|
|
|
ControlPoint* control_point;
|
2008-04-11 10:06:50 -04:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
if ((control_point = reinterpret_cast<ControlPoint *> (item->get_data ("control_point"))) == 0) {
|
|
|
|
fatal << _("programming error: control point canvas item has no control point object pointer!") << endmsg;
|
|
|
|
/*NOTREACHED*/
|
|
|
|
}
|
2008-04-11 10:06:50 -04:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
// We shouldn't remove the first or last gain point
|
|
|
|
if (control_point->line().is_last_point(*control_point) ||
|
|
|
|
control_point->line().is_first_point(*control_point)) {
|
|
|
|
return;
|
2008-04-11 10:06:50 -04:00
|
|
|
}
|
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
control_point->line().remove_point (*control_point);
|
2008-04-11 10:06:50 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-05-30 14:25:59 -04:00
|
|
|
Editor::remove_control_point (ArdourCanvas::Item* item, GdkEvent* event)
|
2008-04-11 10:06:50 -04:00
|
|
|
{
|
2009-05-30 14:25:59 -04:00
|
|
|
ControlPoint* control_point;
|
2008-04-11 10:06:50 -04:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
if ((control_point = reinterpret_cast<ControlPoint *> (item->get_data ("control_point"))) == 0) {
|
|
|
|
fatal << _("programming error: control point canvas item has no control point object pointer!") << endmsg;
|
2005-09-25 14:42:24 -04:00
|
|
|
/*NOTREACHED*/
|
|
|
|
}
|
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
control_point->line().remove_point (*control_point);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2006-06-13 03:27:52 -04:00
|
|
|
void
|
2009-05-30 14:25:59 -04:00
|
|
|
Editor::edit_control_point (ArdourCanvas::Item* item)
|
2006-06-13 03:27:52 -04:00
|
|
|
{
|
2009-05-30 14:25:59 -04:00
|
|
|
ControlPoint* p = reinterpret_cast<ControlPoint *> (item->get_data ("control_point"));
|
2006-06-13 03:27:52 -04:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
if (p == 0) {
|
|
|
|
fatal << _("programming error: control point canvas item has no control point object pointer!") << endmsg;
|
|
|
|
/*NOTREACHED*/
|
2006-06-13 03:27:52 -04:00
|
|
|
}
|
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
ControlPointDialog d (p);
|
|
|
|
d.set_position (Gtk::WIN_POS_MOUSE);
|
|
|
|
ensure_float (d);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
if (d.run () != RESPONSE_ACCEPT) {
|
|
|
|
return;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
p->line().modify_point_y (*p, d.get_y_fraction ());
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
|
2008-12-12 09:43:24 -05:00
|
|
|
void
|
2009-05-30 14:25:59 -04:00
|
|
|
Editor::visible_order_range (int* low, int* high) const
|
2008-12-12 09:43:24 -05:00
|
|
|
{
|
2009-05-30 14:25:59 -04:00
|
|
|
*low = TimeAxisView::max_order ();
|
|
|
|
*high = 0;
|
|
|
|
|
|
|
|
for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
|
|
|
|
|
|
|
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
|
|
|
|
|
|
|
|
if (!rtv->hidden()) {
|
|
|
|
|
|
|
|
if (*high < rtv->order()) {
|
|
|
|
*high = rtv->order ();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*low > rtv->order()) {
|
|
|
|
*low = rtv->order ();
|
|
|
|
}
|
|
|
|
}
|
2008-12-12 09:43:24 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
2009-05-30 14:25:59 -04:00
|
|
|
Editor::region_view_item_click (AudioRegionView& rv, GdkEventButton* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2009-05-30 14:25:59 -04:00
|
|
|
/* Either add to or set the set the region selection, unless
|
|
|
|
this is an alignment click (control used)
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (Keyboard::modifier_state_contains (event->state, Keyboard::PrimaryModifier)) {
|
|
|
|
TimeAxisView* tv = &rv.get_time_axis_view();
|
|
|
|
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(tv);
|
|
|
|
double speed = 1.0;
|
|
|
|
if (rtv && rtv->is_track()) {
|
|
|
|
speed = rtv->get_diskstream()->speed();
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
nframes64_t where = get_preferred_edit_position();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
if (where >= 0) {
|
2008-09-10 11:03:30 -04:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
|
|
|
|
|
|
|
|
align_region (rv.region(), SyncPoint, (nframes64_t) (where * speed));
|
|
|
|
|
|
|
|
} else if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
|
|
|
|
|
|
|
|
align_region (rv.region(), End, (nframes64_t) (where * speed));
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
align_region (rv.region(), Start, (nframes64_t) (where * speed));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-05-30 14:25:59 -04:00
|
|
|
Editor::show_verbose_time_cursor (nframes64_t frame, double offset, double xpos, double ypos)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2009-05-30 14:25:59 -04:00
|
|
|
char buf[128];
|
|
|
|
SMPTE::Time smpte;
|
|
|
|
BBT_Time bbt;
|
|
|
|
int hours, mins;
|
|
|
|
nframes64_t frame_rate;
|
|
|
|
float secs;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
if (session == 0) {
|
|
|
|
return;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
AudioClock::Mode m;
|
2007-01-28 12:44:13 -05:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
if (Profile->get_sae() || Profile->get_small_screen()) {
|
|
|
|
m = ARDOUR_UI::instance()->primary_clock.mode();
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2009-05-30 14:25:59 -04:00
|
|
|
m = ARDOUR_UI::instance()->secondary_clock.mode();
|
|
|
|
}
|
2007-01-28 12:44:13 -05:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
switch (m) {
|
|
|
|
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;
|
2007-01-28 12:44:13 -05:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
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:
|
|
|
|
/* 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);
|
|
|
|
break;
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
default:
|
|
|
|
snprintf (buf, sizeof(buf), "%" PRIi64, frame);
|
|
|
|
break;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
if (xpos >= 0 && ypos >=0) {
|
|
|
|
set_verbose_canvas_cursor (buf, xpos + offset, ypos + offset);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
set_verbose_canvas_cursor (buf, _drag->current_pointer_x() + offset - horizontal_adjustment.get_value(), _drag->current_pointer_y() + offset - vertical_adjustment.get_value() + canvas_timebars_vsize);
|
|
|
|
}
|
|
|
|
show_verbose_canvas_cursor ();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-05-30 14:25:59 -04:00
|
|
|
Editor::show_verbose_duration_cursor (nframes64_t start, nframes64_t end, double offset, double xpos, double ypos)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2009-05-30 14:25:59 -04:00
|
|
|
char buf[128];
|
|
|
|
SMPTE::Time smpte;
|
|
|
|
BBT_Time sbbt;
|
|
|
|
BBT_Time ebbt;
|
|
|
|
int hours, mins;
|
|
|
|
nframes64_t distance, frame_rate;
|
|
|
|
float secs;
|
|
|
|
Meter meter_at_start(session->tempo_map().meter_at(start));
|
2007-01-28 12:44:13 -05:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
if (session == 0) {
|
|
|
|
return;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
AudioClock::Mode m;
|
|
|
|
|
|
|
|
if (Profile->get_sae() || Profile->get_small_screen()) {
|
|
|
|
m = ARDOUR_UI::instance()->primary_clock.mode ();
|
2007-01-28 12:44:13 -05:00
|
|
|
} else {
|
2009-05-30 14:25:59 -04:00
|
|
|
m = ARDOUR_UI::instance()->secondary_clock.mode ();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2006-08-09 21:22:45 -04:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
switch (m) {
|
|
|
|
case AudioClock::BBT:
|
|
|
|
session->bbt_time (start, sbbt);
|
|
|
|
session->bbt_time (end, ebbt);
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
/* subtract */
|
|
|
|
/* XXX this computation won't work well if the
|
|
|
|
user makes a selection that spans any meter changes.
|
|
|
|
*/
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
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;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2006-07-23 08:03:19 -04:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
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;
|
2006-01-19 13:00:07 -05:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
case AudioClock::MinSec:
|
|
|
|
/* 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);
|
|
|
|
break;
|
2009-04-20 17:02:46 -04:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
default:
|
|
|
|
snprintf (buf, sizeof(buf), "%" PRIi64, end - start);
|
|
|
|
break;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
if (xpos >= 0 && ypos >=0) {
|
|
|
|
set_verbose_canvas_cursor (buf, xpos + offset, ypos + offset);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2009-05-30 14:25:59 -04:00
|
|
|
else {
|
|
|
|
set_verbose_canvas_cursor (buf, _drag->current_pointer_x() + offset, _drag->current_pointer_y() + offset);
|
2009-04-20 17:02:46 -04:00
|
|
|
}
|
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
show_verbose_canvas_cursor ();
|
|
|
|
}
|
2009-04-20 17:02:46 -04:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
void
|
|
|
|
Editor::collect_new_region_view (RegionView* rv)
|
|
|
|
{
|
|
|
|
latest_regionviews.push_back (rv);
|
|
|
|
}
|
2009-04-20 17:02:46 -04:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
void
|
|
|
|
Editor::collect_and_select_new_region_view (RegionView* rv)
|
|
|
|
{
|
|
|
|
selection->add(rv);
|
|
|
|
latest_regionviews.push_back (rv);
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
void
|
|
|
|
Editor::cancel_selection ()
|
|
|
|
{
|
|
|
|
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
|
|
|
(*i)->hide_selection ();
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
selection->clear ();
|
|
|
|
clicked_selection = 0;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
|
|
|
|
void
|
2008-09-10 11:03:30 -04:00
|
|
|
Editor::single_contents_trim (RegionView& rv, nframes64_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;
|
|
|
|
}
|
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_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) {
|
2008-09-10 11:03:30 -04:00
|
|
|
new_bound = (nframes64_t) (region->position()/speed) + frame_delta;
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2008-09-10 11:03:30 -04:00
|
|
|
new_bound = (nframes64_t) (region->position()/speed) - frame_delta;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (swap_direction) {
|
2008-09-10 11:03:30 -04:00
|
|
|
new_bound = (nframes64_t) (region->position()/speed) - frame_delta;
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2008-09-10 11:03:30 -04:00
|
|
|
new_bound = (nframes64_t) (region->position()/speed) + frame_delta;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (obey_snap) {
|
|
|
|
snap_to (new_bound);
|
|
|
|
}
|
2008-09-10 11:03:30 -04:00
|
|
|
region->trim_start ((nframes64_t) (new_bound * speed), this);
|
2005-09-25 14:42:24 -04:00
|
|
|
rv.region_changed (StartChanged);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-04-20 17:02:46 -04:00
|
|
|
Editor::single_start_trim (RegionView& rv, nframes64_t frame_delta, bool left_direction, bool obey_snap, bool no_overlap)
|
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;
|
|
|
|
}
|
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_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) {
|
2008-09-10 11:03:30 -04:00
|
|
|
new_bound = (nframes64_t) (region->position()/speed) - frame_delta;
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2008-09-10 11:03:30 -04:00
|
|
|
new_bound = (nframes64_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));
|
|
|
|
}
|
2009-04-20 17:02:46 -04:00
|
|
|
|
|
|
|
nframes64_t pre_trim_first_frame = region->first_frame();
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
region->trim_front ((nframes64_t) (new_bound * speed), this);
|
2009-04-20 17:02:46 -04:00
|
|
|
|
|
|
|
if (no_overlap) {
|
|
|
|
//Get the next region on the left of this region and shrink/expand it.
|
|
|
|
boost::shared_ptr<Playlist> playlist (region->playlist());
|
|
|
|
boost::shared_ptr<Region> region_left = playlist->find_next_region (pre_trim_first_frame, End, 0);
|
|
|
|
|
|
|
|
bool regions_touching = false;
|
|
|
|
|
|
|
|
if (region_left != 0 && (pre_trim_first_frame == region_left->last_frame() + 1)){
|
|
|
|
regions_touching = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Only trim region on the left if the first frame has gone beyond the left region's last frame.
|
|
|
|
if (region_left != 0 &&
|
|
|
|
(region_left->last_frame() > region->first_frame() || regions_touching))
|
|
|
|
{
|
|
|
|
region_left->trim_end(region->first_frame(), this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
|
|
|
|
rv.region_changed (Change (LengthChanged|PositionChanged|StartChanged));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-04-20 17:02:46 -04:00
|
|
|
Editor::single_end_trim (RegionView& rv, nframes64_t frame_delta, bool left_direction, bool obey_snap, bool no_overlap)
|
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;
|
|
|
|
}
|
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
nframes64_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();
|
|
|
|
}
|
2009-04-20 17:02:46 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
if (left_direction) {
|
2008-09-10 11:03:30 -04:00
|
|
|
new_bound = (nframes64_t) ((region->last_frame() + 1)/speed) - frame_delta;
|
2005-09-25 14:42:24 -04:00
|
|
|
} else {
|
2008-09-10 11:03:30 -04:00
|
|
|
new_bound = (nframes64_t) ((region->last_frame() + 1)/speed) + frame_delta;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (obey_snap) {
|
|
|
|
snap_to (new_bound);
|
|
|
|
}
|
2009-04-20 17:02:46 -04:00
|
|
|
|
|
|
|
nframes64_t pre_trim_last_frame = region->last_frame();
|
|
|
|
|
2008-09-10 11:03:30 -04:00
|
|
|
region->trim_end ((nframes64_t) (new_bound * speed), this);
|
2009-04-20 17:02:46 -04:00
|
|
|
|
|
|
|
if (no_overlap) {
|
|
|
|
//Get the next region on the right of this region and shrink/expand it.
|
|
|
|
boost::shared_ptr<Playlist> playlist (region->playlist());
|
|
|
|
boost::shared_ptr<Region> region_right = playlist->find_next_region (pre_trim_last_frame, Start, 1);
|
|
|
|
|
|
|
|
bool regions_touching = false;
|
|
|
|
|
|
|
|
if (region_right != 0 && (pre_trim_last_frame == region_right->first_frame() - 1)){
|
|
|
|
regions_touching = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Only trim region on the right if the last frame has gone beyond the right region's first frame.
|
|
|
|
if (region_right != 0 &&
|
|
|
|
(region_right->first_frame() < region->last_frame() || regions_touching))
|
|
|
|
{
|
|
|
|
region_right->trim_front(region->last_frame() + 1, this);
|
|
|
|
}
|
|
|
|
|
|
|
|
rv.region_changed (Change (LengthChanged|PositionChanged|StartChanged));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
rv.region_changed (LengthChanged);
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
2009-04-20 17:02:46 -04:00
|
|
|
|
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
|
|
|
Editor::point_trim (GdkEvent* event)
|
|
|
|
{
|
2006-07-23 08:03:19 -04:00
|
|
|
RegionView* rv = clicked_regionview;
|
2009-04-20 17:02:46 -04:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
nframes64_t new_bound = _drag->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:
|
|
|
|
begin_reversible_command (_("Start point trim"));
|
|
|
|
|
2008-01-10 16:20:59 -05:00
|
|
|
if (selection->selected (rv)) {
|
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
|
|
|
{
|
2009-04-20 17:02:46 -04:00
|
|
|
if ( (*i) == NULL){
|
|
|
|
cerr << "region view contains null region" << endl;
|
|
|
|
}
|
|
|
|
|
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();
|
2009-04-20 17:02:46 -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();
|
2009-04-20 17:02:46 -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:
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
} else {
|
2006-06-13 03:27:52 -04:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
if (!rv->region()->locked()) {
|
|
|
|
boost::shared_ptr<Playlist> pl = rv->region()->playlist();
|
|
|
|
XMLNode &before = pl->get_state();
|
|
|
|
rv->region()->trim_end (new_bound, this);
|
|
|
|
XMLNode &after = pl->get_state();
|
|
|
|
session->add_command (new MementoCommand<Playlist>(*pl.get(), &before, &after));
|
2006-06-13 03:27:52 -04:00
|
|
|
}
|
2009-05-30 14:25:59 -04:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
commit_reversible_command();
|
|
|
|
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-05-30 14:25:59 -04:00
|
|
|
Editor::thaw_region_after_trim (RegionView& rv)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2009-05-30 14:25:59 -04:00
|
|
|
boost::shared_ptr<Region> region (rv.region());
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
if (region->locked()) {
|
|
|
|
return;
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
region->thaw (_("trimmed region"));
|
2005-09-25 14:42:24 -04:00
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
AudioRegionView* arv = dynamic_cast<AudioRegionView*>(&rv);
|
2009-06-21 14:34:08 -04:00
|
|
|
|
|
|
|
if (arv) {
|
2009-05-30 14:25:59 -04:00
|
|
|
arv->unhide_envelope ();
|
2009-06-21 14:34:08 -04:00
|
|
|
}
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-05-30 14:25:59 -04:00
|
|
|
Editor::hide_marker (ArdourCanvas::Item* item, GdkEvent* event)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
2009-05-30 14:25:59 -04:00
|
|
|
Marker* marker;
|
|
|
|
bool is_start;
|
|
|
|
|
|
|
|
if ((marker = static_cast<Marker *> (item->get_data ("marker"))) == 0) {
|
|
|
|
fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
|
|
|
|
/*NOTREACHED*/
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
Location* location = find_location_from_marker (marker, is_start);
|
|
|
|
location->set_hidden (true, this);
|
2005-09-25 14:42:24 -04:00
|
|
|
}
|
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
|
2005-09-25 14:42:24 -04:00
|
|
|
void
|
2008-09-10 11:03:30 -04:00
|
|
|
Editor::reposition_zoom_rect (nframes64_t start, nframes64_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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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
|
2008-09-10 11:03:30 -04:00
|
|
|
Editor::mouse_brush_insert_region (RegionView* rv, nframes64_t pos)
|
2005-09-25 14:42:24 -04:00
|
|
|
{
|
|
|
|
/* no brushing without a useful snap setting */
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2008-09-14 14:08:58 -04:00
|
|
|
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(&rv->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();
|
2008-09-14 14:08:58 -04:00
|
|
|
playlist->add_region (RegionFactory::create (rv->region()), (nframes64_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 ()
|
|
|
|
{
|
2008-09-10 11:03:30 -04:00
|
|
|
if (get_microseconds() - last_track_height_step_timestamp < 250000) {
|
2005-09-25 14:42:24 -04:00
|
|
|
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
|
|
|
|
2009-05-30 14:25:59 -04:00
|
|
|
void
|
|
|
|
Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event, RegionView* region_view)
|
|
|
|
{
|
|
|
|
assert (region_view);
|
|
|
|
|
|
|
|
_region_motion_group->raise_to_top ();
|
|
|
|
|
|
|
|
assert (_drag == 0);
|
|
|
|
|
|
|
|
if (Config->get_edit_mode() == Splice) {
|
|
|
|
_drag = new RegionSpliceDrag (this, item, region_view, selection->regions.by_layer());
|
|
|
|
} else {
|
|
|
|
_drag = new RegionMoveDrag (this, item, region_view, selection->regions.by_layer(), false, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
_drag->start_grab (event);
|
|
|
|
|
|
|
|
begin_reversible_command (_("move region(s)"));
|
|
|
|
|
|
|
|
/* sync the canvas to what we think is its current state */
|
2009-06-12 15:05:16 -04:00
|
|
|
update_canvas_now();
|
2009-05-30 14:25:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event, RegionView* region_view)
|
|
|
|
{
|
|
|
|
assert (region_view);
|
|
|
|
assert (_drag == 0);
|
|
|
|
|
|
|
|
_region_motion_group->raise_to_top ();
|
|
|
|
_drag = new RegionMoveDrag (this, item, region_view, selection->regions.by_layer(), false, true);
|
|
|
|
_drag->start_grab(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::start_region_brush_grab (ArdourCanvas::Item* item, GdkEvent* event, RegionView* region_view)
|
|
|
|
{
|
|
|
|
assert (region_view);
|
|
|
|
assert (_drag == 0);
|
|
|
|
|
|
|
|
if (Config->get_edit_mode() == Splice) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_drag = new RegionMoveDrag (this, item, region_view, selection->regions.by_layer(), true, false);
|
|
|
|
_drag->start_grab (event);
|
|
|
|
|
|
|
|
begin_reversible_command (_("Drag region brush"));
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Start a grab where a time range is selected, track(s) are selected, and the
|
|
|
|
* user clicks and drags a region with a modifier in order to create a new region containing
|
|
|
|
* the section of the clicked region that lies within the time range.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
|
|
|
{
|
|
|
|
if (clicked_regionview == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* lets try to create new Region for the selection */
|
|
|
|
|
|
|
|
vector<boost::shared_ptr<Region> > new_regions;
|
|
|
|
create_region_from_selection (new_regions);
|
|
|
|
|
|
|
|
if (new_regions.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX fix me one day to use all new regions */
|
|
|
|
|
|
|
|
boost::shared_ptr<Region> region (new_regions.front());
|
|
|
|
|
|
|
|
/* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
latest_regionviews.clear();
|
|
|
|
sigc::connection c = clicked_routeview->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
|
|
|
|
|
|
|
|
/* 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"));
|
|
|
|
|
|
|
|
boost::shared_ptr<Playlist> playlist = clicked_axisview->playlist();
|
|
|
|
|
|
|
|
XMLNode *before = &(playlist->get_state());
|
|
|
|
clicked_routeview->playlist()->add_region (region, selection->time[clicked_selection].start);
|
|
|
|
XMLNode *after = &(playlist->get_state());
|
|
|
|
session->add_command(new MementoCommand<Playlist>(*playlist, before, after));
|
|
|
|
|
|
|
|
commit_reversible_command ();
|
|
|
|
|
|
|
|
c.disconnect ();
|
|
|
|
|
|
|
|
if (latest_regionviews.empty()) {
|
|
|
|
/* something went wrong */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* we need to deselect all other regionviews, and select this one
|
|
|
|
i'm ignoring undo stuff, because the region creation will take care of it
|
|
|
|
*/
|
|
|
|
selection->set (latest_regionviews);
|
|
|
|
|
|
|
|
assert (_drag == 0);
|
|
|
|
_drag = new RegionMoveDrag (this, latest_regionviews.front()->get_canvas_group(), latest_regionviews.front(), latest_regionviews, false, false);
|
|
|
|
_drag->start_grab (event);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Editor::break_drag ()
|
|
|
|
{
|
|
|
|
if (_drag) {
|
|
|
|
_drag->break_drag ();
|
|
|
|
}
|
|
|
|
}
|