#include "ardour/session.h"
#include "ardour/dB.h"
#include "ardour/region_factory.h"
+#include "ardour/operations.h"
+
#include "editor.h"
#include "i18n.h"
#include "keyboard.h"
_drags.clear ();
+ _editor->set_follow_playhead (_old_follow_playhead, false);
+
_ending = false;
}
void
DragManager::start_grab (GdkEvent* e, Gdk::Cursor* c)
{
+ /* Prevent follow playhead during the drag to be nice to the user */
+ _old_follow_playhead = _editor->follow_playhead ();
+ _editor->set_follow_playhead (false);
+
_current_pointer_frame = _editor->event_frame (e, &_current_pointer_x, &_current_pointer_y);
for (list<Drag*>::const_iterator i = _drags.begin(); i != _drags.end(); ++i) {
_drags.clear ();
_ending = false;
+
+ _editor->set_follow_playhead (_old_follow_playhead, false);
return r;
}
if (!from_autoscroll && !_move_threshold_passed) {
- bool const xp = (::llabs (_drags->current_pointer_frame () - _grab_frame) >= threshold.first);
+ bool const xp = (::llabs (_drags->current_pointer_frame () - _raw_grab_frame) >= threshold.first);
bool const yp = (::fabs ((_drags->current_pointer_y () - _grab_y)) >= threshold.second);
_move_threshold_passed = ((xp && x_movement_matters()) || (yp && y_movement_matters()));
_item->ungrab (0);
}
- aborted ();
+ aborted (_move_threshold_passed);
_editor->stop_canvas_autoscroll ();
_editor->hide_verbose_canvas_cursor ();
if (_x_constrained) {
_editor->begin_reversible_command (_("fixed time region drag"));
} else {
- _editor->begin_reversible_command (_("region drag"));
+ _editor->begin_reversible_command (Operations::region_drag);
}
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ) {
for (PlaylistSet::const_iterator i = playlists.begin(); i != playlists.end(); ++i) {
StatefulDiffCommand* c = new StatefulDiffCommand (*i);
if (!c->empty()) {
- _editor->session()->add_command (new StatefulDiffCommand (*i));
+ _editor->session()->add_command (c);
} else {
delete c;
}
void
-RegionMoveDrag::aborted ()
+RegionMoveDrag::aborted (bool movement_occurred)
{
if (_copy) {
_views.clear ();
} else {
- RegionMotionDrag::aborted ();
+ RegionMotionDrag::aborted (movement_occurred);
}
}
void
-RegionMotionDrag::aborted ()
+RegionMotionDrag::aborted (bool)
{
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
RegionView* rv = i->view;
_editor->update_canvas_now ();
}
-
+
+/** @param b true to brush, otherwise false.
+ * @param c true to make copies of the regions being moved, otherwise false.
+ */
RegionMoveDrag::RegionMoveDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v, bool b, bool c)
: RegionMotionDrag (e, i, p, v, b),
_copy (c)
boost::shared_ptr<Playlist> playlist = dest_rtv->playlist();
- _editor->begin_reversible_command (_("insert region"));
+ _editor->begin_reversible_command (Operations::insert_region);
playlist->clear_changes ();
playlist->add_region (_primary->region (), _last_frame_position);
_editor->session()->add_command (new StatefulDiffCommand (playlist));
}
void
-RegionInsertDrag::aborted ()
+RegionInsertDrag::aborted (bool)
{
delete _primary;
_primary = 0;
}
void
-RegionSpliceDrag::aborted ()
+RegionSpliceDrag::aborted (bool)
{
/* XXX: TODO */
}
{
if (first_move) {
add_region();
+ _view->playlist()->freeze ();
} else {
if (_region) {
framepos_t const f = adjusted_current_frame (event);
{
if (!movement_occurred) {
add_region ();
+ } else {
+ _view->playlist()->thaw ();
}
if (_region) {
}
void
-RegionCreateDrag::aborted ()
+RegionCreateDrag::aborted (bool)
{
+ if (_region) {
+ _view->playlist()->thaw ();
+ }
+
/* XXX */
}
}
void
-NoteResizeDrag::aborted ()
+NoteResizeDrag::aborted (bool)
{
/* XXX: TODO */
}
}
void
-RegionGainDrag::aborted ()
+RegionGainDrag::aborted (bool)
{
/* XXX: TODO */
}
TrimDrag::TrimDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v)
: RegionDrag (e, i, p, v)
- , _have_transaction (false)
{
DEBUG_TRACE (DEBUG::Drags, "New TrimDrag\n");
}
}
_editor->begin_reversible_command (trim_type);
- _have_transaction = true;
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
RegionView* rv = i->view;
rv->fake_set_opaque (false);
rv->enable_display (false);
- rv->region()->clear_changes ();
+ rv->region()->playlist()->clear_owned_changes ();
AudioRegionView* const arv = dynamic_cast<AudioRegionView*> (rv);
_primary->thaw_after_trim ();
} else {
+ set<boost::shared_ptr<Playlist> > diffed_playlists;
+
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
- i->view->thaw_after_trim ();
+ i->view->thaw_after_trim ();
i->view->enable_display (true);
i->view->fake_set_opaque (true);
- if (_have_transaction) {
- _editor->session()->add_command (new StatefulDiffCommand (i->view->region()));
+
+ /* Trimming one region may affect others on the playlist, so we need
+ to get undo Commands from the whole playlist rather than just the
+ region. Use diffed_playlists to make sure we don't diff a given
+ playlist more than once.
+ */
+ boost::shared_ptr<Playlist> p = i->view->region()->playlist ();
+ if (diffed_playlists.find (p) == diffed_playlists.end()) {
+ vector<Command*> cmds;
+ p->rdiff (cmds);
+ _editor->session()->add_commands (cmds);
+ diffed_playlists.insert (p);
}
}
}
}
_editor->motion_frozen_playlists.clear ();
- if (_have_transaction) {
- _editor->commit_reversible_command();
- }
+ _editor->commit_reversible_command();
} else {
/* no mouse movement */
}
void
-TrimDrag::aborted ()
+TrimDrag::aborted (bool movement_occurred)
{
/* Our motion method is changing model state, so use the Undo system
to cancel. Perhaps not ideal, as this will leave an Undo point
finished (0, true);
- if (_have_transaction) {
+ if (movement_occurred) {
_editor->undo ();
}
case EndTrim:
_pointer_frame_offset = raw_grab_frame() - i->initial_end;
break;
+ case ContentsTrim:
+ break;
}
}
MeterMarker* new_marker = new MeterMarker (
*_editor,
*_editor->meter_group,
- *_editor->cursor_group,
ARDOUR_UI::config()->canvasvar_MeterMarker.get(),
name,
*new MeterSection (_marker->meter())
}
void
-MeterMarkerDrag::aborted ()
+MeterMarkerDrag::aborted (bool)
{
_marker->set_position (_marker->meter().frame ());
}
TempoMarker* new_marker = new TempoMarker (
*_editor,
*_editor->tempo_group,
- *_editor->cursor_group,
ARDOUR_UI::config()->canvasvar_TempoMarker.get(),
name,
*new TempoSection (_marker->tempo())
}
void
-TempoMarkerDrag::aborted ()
+TempoMarkerDrag::aborted (bool)
{
_marker->set_position (_marker->tempo().frame());
}
DEBUG_TRACE (DEBUG::Drags, "New CursorDrag\n");
}
+/** Do all the things we do when dragging the playhead to make it look as though
+ * we have located, without actually doing the locate (because that would cause
+ * the diskstream buffers to be refilled, which is too slow).
+ */
+void
+CursorDrag::fake_locate (framepos_t t)
+{
+ _editor->playhead_cursor->set_position (t);
+
+ Session* s = _editor->session ();
+ if (s->timecode_transmission_suspended ()) {
+ framepos_t const f = _editor->playhead_cursor->current_frame;
+ s->send_mmc_locate (f);
+ s->send_full_time_code (f);
+ }
+
+ _editor->show_verbose_time_cursor (t, 10);
+ _editor->UpdateAllTransportClocks (t);
+}
+
void
CursorDrag::start_grab (GdkEvent* event, Gdk::Cursor* c)
{
Drag::start_grab (event, c);
- if (!_stop) {
- framepos_t where = _editor->event_frame (event, 0, 0);
-
- _editor->snap_to_with_modifier (where, event);
- _editor->playhead_cursor->set_position (where);
- }
+ framepos_t where = _editor->event_frame (event, 0, 0);
+ _editor->snap_to_with_modifier (where, event);
_editor->_dragging_playhead = true;
}
s->request_suspend_timecode_transmission ();
-
- if (s->timecode_transmission_suspended ()) {
- framepos_t const f = _editor->playhead_cursor->current_frame;
- s->send_mmc_locate (f);
- s->send_full_time_code (f);
+ while (!s->timecode_transmission_suspended ()) {
+ /* twiddle our thumbs */
}
}
-
- _editor->show_verbose_time_cursor (_editor->playhead_cursor->current_frame, 10);
- _editor->UpdateAllTransportClocks (_editor->playhead_cursor->current_frame);
+
+ fake_locate (where);
}
void
return;
}
- _editor->playhead_cursor->set_position (adjusted_frame);
-
- _editor->show_verbose_time_cursor (_editor->playhead_cursor->current_frame, 10);
-
- Session* s = _editor->session ();
- if (s && s->timecode_transmission_suspended ()) {
- framepos_t const f = _editor->playhead_cursor->current_frame;
- s->send_mmc_locate (f);
- s->send_full_time_code (f);
- }
+ fake_locate (adjusted_frame);
-
#ifdef GTKOSX
_editor->update_canvas_now ();
#endif
- _editor->UpdateAllTransportClocks (_editor->playhead_cursor->current_frame);
}
void
}
void
-CursorDrag::aborted ()
+CursorDrag::aborted (bool)
{
if (_editor->_dragging_playhead) {
_editor->session()->request_resume_timecode_transmission ();
}
void
-FadeInDrag::aborted ()
+FadeInDrag::aborted (bool)
{
for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (i->view);
}
void
-FadeOutDrag::aborted ()
+FadeOutDrag::aborted (bool)
{
for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (i->view);
_points.push_back (Gnome::Art::Point (0, 0));
_points.push_back (Gnome::Art::Point (0, physical_screen_height (_editor->get_window())));
-
- _line = new ArdourCanvas::Line (*_editor->timebar_group);
- _line->property_width_pixels() = 1;
- _line->property_points () = _points;
- _line->hide ();
-
- _line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_MarkerDragLine.get();
}
MarkerDrag::~MarkerDrag ()
framepos_t next = newframe;
- if (newframe == last_pointer_frame()) {
- return;
- }
-
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
move_both = true;
}
copy_location->set_end (new_end);
} else if (new_start < copy_location->end()) {
copy_location->set_start (new_start);
- } else {
+ } else if (newframe > 0) {
_editor->snap_to (next, 1, true);
copy_location->set_end (next);
copy_location->set_start (newframe);
XMLNode &after = _editor->session()->locations()->get_state();
_editor->session()->add_command(new MementoCommand<Locations>(*(_editor->session()->locations()), &before, &after));
_editor->commit_reversible_command ();
-
- _line->hide();
}
void
-MarkerDrag::aborted ()
+MarkerDrag::aborted (bool)
{
/* XXX: TODO */
}
void
MarkerDrag::update_item (Location* location)
{
- double const x1 = _editor->frame_to_pixel (location->start());
-
- _points.front().set_x(x1);
- _points.back().set_x(x1);
- _line->property_points() = _points;
+ /* noop */
}
ControlPointDrag::ControlPointDrag (Editor* e, ArdourCanvas::Item* i)
}
void
-ControlPointDrag::aborted ()
+ControlPointDrag::aborted (bool)
{
_point->line().reset ();
}
}
void
-LineDrag::aborted ()
+LineDrag::aborted (bool)
{
_line->reset ();
}
{
Drag::start_grab (event);
- _line = reinterpret_cast<SimpleLine*> (_item);
+ _line = reinterpret_cast<Line*> (_item);
assert (_line);
/* need to get x coordinate in terms of parent (AudioRegionView) origin. */
/* store grab start in parent frame */
_region_view_grab_x = cx;
- _before = _line->property_x1();
+ _before = *(float*) _item->get_data ("position");
_arv = reinterpret_cast<AudioRegionView*> (_item->get_data ("regionview"));
-
+
_max_x = _editor->frame_to_pixel(_arv->get_duration());
}
cx = 0;
}
- _line->property_x1() = cx;
- _line->property_x2() = cx;
+ ArdourCanvas::Points points;
+
+ double x1 = 0, x2 = 0, y1 = 0, y2 = 0;
+
+ _line->get_bounds(x1, y2, x2, y2);
+
+ points.push_back(Gnome::Art::Point(cx, 2.0)); // first x-coord needs to be a non-normal value
+ points.push_back(Gnome::Art::Point(cx, y2 - y1));
- _before = _line->property_x1();
+ _line->property_points() = points;
+
+ float *pos = new float;
+ *pos = cx;
+
+ _line->set_data ("position", pos);
+
+ _before = cx;
}
void
FeatureLineDrag::finished (GdkEvent*, bool)
{
_arv = reinterpret_cast<AudioRegionView*> (_item->get_data ("regionview"));
- _arv->update_transient(_before, _line->property_x1());
+ _arv->update_transient(_before, _before);
}
void
-FeatureLineDrag::aborted ()
+FeatureLineDrag::aborted (bool)
{
//_line->reset ();
}
Selection::Operation op = ArdourKeyboard::selection_type (event->button.state);
- bool committed;
_editor->begin_reversible_command (_("rubberband selection"));
if (grab_frame() < last_pointer_frame()) {
- committed = _editor->select_all_within (grab_frame(), last_pointer_frame() - 1, y1, y2, _editor->track_views, op, false);
+ _editor->select_all_within (grab_frame(), last_pointer_frame() - 1, y1, y2, _editor->track_views, op, false);
} else {
- committed = _editor->select_all_within (last_pointer_frame(), grab_frame() - 1, y1, y2, _editor->track_views, op, false);
+ _editor->select_all_within (last_pointer_frame(), grab_frame() - 1, y1, y2, _editor->track_views, op, false);
}
- if (!committed) {
- _editor->commit_reversible_command ();
- }
+ _editor->commit_reversible_command ();
} else {
if (!getenv("ARDOUR_SAE")) {
}
void
-RubberbandSelectDrag::aborted ()
+RubberbandSelectDrag::aborted (bool)
{
_editor->rubberband_rect->hide ();
}
}
void
-TimeFXDrag::aborted ()
+TimeFXDrag::aborted (bool)
{
_primary->get_time_axis_view().hide_timestretch ();
}
}
void
-ScrubDrag::aborted ()
+ScrubDrag::aborted (bool)
{
/* XXX: TODO */
}
}
void
-SelectionDrag::aborted ()
+SelectionDrag::aborted (bool)
{
/* XXX: TODO */
}
}
void
-RangeMarkerBarDrag::aborted ()
+RangeMarkerBarDrag::aborted (bool)
{
/* XXX: TODO */
}
_editor->temporal_zoom_by_frame (last_pointer_frame(), grab_frame(), "mouse zoom");
}
} else {
- _editor->temporal_zoom_to_frame (_zoom_out, grab_frame());
+ if (Keyboard::the_keyboard().key_is_down (GDK_Shift_L)) {
+ _editor->tav_zoom_step (_zoom_out);
+ } else {
+ _editor->temporal_zoom_to_frame (_zoom_out, grab_frame());
+ }
}
_editor->zoom_rect->hide();
}
void
-MouseZoomDrag::aborted ()
+MouseZoomDrag::aborted (bool)
{
_editor->zoom_rect->hide ();
}
}
void
-NoteDrag::aborted ()
+NoteDrag::aborted (bool)
{
/* XXX: TODO */
}
}
void
-AutomationRangeDrag::aborted ()
+AutomationRangeDrag::aborted (bool)
{
for (list<Line>::iterator i = _lines.begin(); i != _lines.end(); ++i) {
i->line->clear_always_in_view ();
initial_end = v->region()->position () + v->region()->length ();
}
-ProgramChangeDrag::ProgramChangeDrag (Editor* e, CanvasProgramChange* i, MidiRegionView* r)
+PatchChangeDrag::PatchChangeDrag (Editor* e, CanvasPatchChange* i, MidiRegionView* r)
: Drag (e, i)
, _region_view (r)
- , _program_change (i)
+ , _patch_change (i)
, _cumulative_dx (0)
{
- DEBUG_TRACE (DEBUG::Drags, "New ProgramChangeDrag\n");
+ DEBUG_TRACE (DEBUG::Drags, "New PatchChangeDrag\n");
}
void
-ProgramChangeDrag::motion (GdkEvent* ev, bool)
+PatchChangeDrag::motion (GdkEvent* ev, bool)
{
framepos_t f = adjusted_current_frame (ev);
boost::shared_ptr<Region> r = _region_view->region ();
framecnt_t const dxf = f - grab_frame();
double const dxu = _editor->frame_to_unit (dxf);
- _program_change->move (dxu - _cumulative_dx, 0);
+ _patch_change->move (dxu - _cumulative_dx, 0);
_cumulative_dx = dxu;
}
void
-ProgramChangeDrag::finished (GdkEvent* ev, bool movement_occurred)
+PatchChangeDrag::finished (GdkEvent* ev, bool movement_occurred)
{
if (!movement_occurred) {
return;
f = max (f, r->position ());
f = min (f, r->last_frame ());
- _region_view->move_program_change (
- MidiRegionView::PCEvent (_program_change->event_time(), _program_change->program(), _program_change->channel()),
+ _region_view->move_patch_change (
+ *_patch_change,
_region_view->frames_to_beats (f - r->position() - r->start())
);
}
void
-ProgramChangeDrag::aborted ()
+PatchChangeDrag::aborted (bool)
{
- _program_change->move (-_cumulative_dx, 0);
+ _patch_change->move (-_cumulative_dx, 0);
}
void
-ProgramChangeDrag::setup_pointer_frame_offset ()
+PatchChangeDrag::setup_pointer_frame_offset ()
{
boost::shared_ptr<Region> region = _region_view->region ();
- _pointer_frame_offset = raw_grab_frame() - _region_view->beats_to_frames (_program_change->event_time()) - region->position() + region->start();
+ _pointer_frame_offset = raw_grab_frame() - _region_view->beats_to_frames (_patch_change->patch()->time()) - region->position() + region->start();
}