Cleanup of region drag code to be a bit more efficient and shorter. Fixes crashes when dragging regions to the wrong track type.

git-svn-id: svn://localhost/ardour2/branches/3.0@7744 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Carl Hetherington 2010-09-06 12:34:11 +00:00
parent 1206b2973d
commit ea2648503b
14 changed files with 327 additions and 606 deletions

View file

@ -26,7 +26,7 @@ bool
CanvasHit::on_event(GdkEvent* ev) CanvasHit::on_event(GdkEvent* ev)
{ {
if (!CanvasNoteEvent::on_event (ev)) { if (!CanvasNoteEvent::on_event (ev)) {
return _region.get_trackview().editor().canvas_note_event (ev, this); return _region.get_time_axis_view().editor().canvas_note_event (ev, this);
} }
return true; return true;
} }

View file

@ -23,7 +23,7 @@ bool
CanvasNote::on_event(GdkEvent* ev) CanvasNote::on_event(GdkEvent* ev)
{ {
if (!CanvasNoteEvent::on_event (ev)) { if (!CanvasNoteEvent::on_event (ev)) {
return _region.get_trackview().editor().canvas_note_event (ev, this); return _region.get_time_axis_view().editor().canvas_note_event (ev, this);
} }
return true; return true;

View file

@ -80,7 +80,7 @@ EditNoteDialog::EditNoteDialog (MidiRegionView* rv, Gnome::Canvas::CanvasNoteEve
table->attach (_time_clock, 1, 2, r, r + 1); table->attach (_time_clock, 1, 2, r, r + 1);
++r; ++r;
_time_clock.set_session (_region_view->get_trackview().session ()); _time_clock.set_session (_region_view->get_time_axis_view().session ());
_time_clock.set_mode (AudioClock::BBT); _time_clock.set_mode (AudioClock::BBT);
_time_clock.set (_region_view->time_converter().to (ev->note()->time ()), true); _time_clock.set (_region_view->time_converter().to (ev->note()->time ()), true);
@ -90,7 +90,7 @@ EditNoteDialog::EditNoteDialog (MidiRegionView* rv, Gnome::Canvas::CanvasNoteEve
table->attach (_length_clock, 1, 2, r, r + 1); table->attach (_length_clock, 1, 2, r, r + 1);
++r; ++r;
_length_clock.set_session (_region_view->get_trackview().session ()); _length_clock.set_session (_region_view->get_time_axis_view().session ());
_length_clock.set_mode (AudioClock::BBT); _length_clock.set_mode (AudioClock::BBT);
_length_clock.set (_region_view->time_converter().to (ev->note()->length ()), true); _length_clock.set (_region_view->time_converter().to (ev->note()->length ()), true);

View file

@ -332,12 +332,40 @@ Drag::abort ()
_editor->hide_verbose_canvas_cursor (); _editor->hide_verbose_canvas_cursor ();
} }
struct EditorOrderTimeAxisViewSorter {
bool operator() (TimeAxisView* a, TimeAxisView* b) {
RouteTimeAxisView* ra = dynamic_cast<RouteTimeAxisView*> (a);
RouteTimeAxisView* rb = dynamic_cast<RouteTimeAxisView*> (b);
assert (ra && rb);
return ra->route()->order_key (N_ ("editor")) < rb->route()->order_key (N_ ("editor"));
}
};
RegionDrag::RegionDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v) RegionDrag::RegionDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v)
: Drag (e, i), : Drag (e, i),
_primary (p) _primary (p)
{ {
_editor->visible_order_range (&_visible_y_low, &_visible_y_high);
/* Make a list of non-hidden tracks to refer to during the drag */
TrackViewList track_views = _editor->track_views;
track_views.sort (EditorOrderTimeAxisViewSorter ());
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
if (!(*i)->hidden()) {
_time_axis_views.push_back (*i);
TimeAxisView::Children children_list = (*i)->get_child_list ();
for (TimeAxisView::Children::iterator j = children_list.begin(); j != children_list.end(); ++j) {
_time_axis_views.push_back (j->get());
}
}
}
for (list<RegionView*>::const_iterator i = v.begin(); i != v.end(); ++i) { for (list<RegionView*>::const_iterator i = v.begin(); i != v.end(); ++i) {
_views.push_back (DraggingView (*i)); _views.push_back (DraggingView (*i, this));
} }
RegionView::RegionViewGoingAway.connect (death_connection, invalidator (*this), ui_bind (&RegionDrag::region_going_away, this, _1), gui_context()); RegionView::RegionViewGoingAway.connect (death_connection, invalidator (*this), ui_bind (&RegionDrag::region_going_away, this, _1), gui_context());
@ -356,10 +384,25 @@ RegionDrag::region_going_away (RegionView* v)
} }
} }
/** Given a non-hidden TimeAxisView, return the index of it into the _time_axis_views vector */
int
RegionDrag::find_time_axis_view (TimeAxisView* t) const
{
int i = 0;
int const N = _time_axis_views.size ();
while (i < N && _time_axis_views[i] != t) {
++i;
}
if (i == N) {
return -1;
}
return i;
}
RegionMotionDrag::RegionMotionDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v, bool b) RegionMotionDrag::RegionMotionDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v, bool b)
: RegionDrag (e, i, p, v), : RegionDrag (e, i, p, v),
_dest_trackview (0),
_dest_layer (0),
_brushing (b), _brushing (b),
_total_x_delta (0) _total_x_delta (0)
{ {
@ -368,143 +411,17 @@ RegionMotionDrag::RegionMotionDrag (Editor* e, ArdourCanvas::Item* i, RegionView
void void
RegionMotionDrag::start_grab (GdkEvent* event, Gdk::Cursor *) RegionMotionDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
{ {
Drag::start_grab (event); Drag::start_grab (event, cursor);
_editor->show_verbose_time_cursor (_last_frame_position, 10); _editor->show_verbose_time_cursor (_last_frame_position, 10);
pair<TimeAxisView*, int> const tv = _editor->trackview_by_y_position (_drags->current_pointer_y ());
_last_pointer_time_axis_view = find_time_axis_view (tv.first);
_last_pointer_layer = tv.first->layer_display() == Overlaid ? 0 : tv.second;
} }
RegionMotionDrag::TimeAxisViewSummary
RegionMotionDrag::get_time_axis_view_summary ()
{
int32_t children = 0;
TimeAxisViewSummary sum;
_editor->visible_order_range (&sum.visible_y_low, &sum.visible_y_high);
/* get a bitmask representing the visible tracks */
for (TrackViewList::iterator i = _editor->track_views.begin(); i != _editor->track_views.end(); ++i) {
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
TimeAxisView::Children children_list;
/* zeroes are audio/MIDI tracks. ones are other types. */
if (!rtv->hidden()) {
if (!rtv->is_track()) {
/* not an audio nor MIDI track */
sum.tracks = sum.tracks |= (0x01 << rtv->order());
}
sum.height_list[rtv->order()] = (*i)->current_height();
children = 1;
if ((children_list = rtv->get_child_list()).size() > 0) {
for (TimeAxisView::Children::iterator j = children_list.begin(); j != children_list.end(); ++j) {
sum.tracks = sum.tracks |= (0x01 << (rtv->order() + children));
sum.height_list[rtv->order() + children] = (*j)->current_height();
children++;
}
}
}
}
return sum;
}
bool
RegionMotionDrag::compute_y_delta (
TimeAxisView const * last_pointer_view, TimeAxisView* current_pointer_view,
int32_t last_pointer_layer, int32_t current_pointer_layer,
TimeAxisViewSummary const & tavs,
int32_t* pointer_order_span, int32_t* pointer_layer_span,
int32_t* canvas_pointer_order_span
)
{
if (_brushing) {
*pointer_order_span = 0;
*pointer_layer_span = 0;
return true;
}
bool clamp_y_axis = false;
/* the change in track order between this callback and the last */
*pointer_order_span = last_pointer_view->order() - current_pointer_view->order();
/* the change in layer between this callback and the last;
only meaningful if pointer_order_span == 0 (ie we've not moved tracks) */
*pointer_layer_span = last_pointer_layer - current_pointer_layer;
if (*pointer_order_span != 0) {
/* find the actual pointer span, in terms of the number of visible tracks;
to do this, we reduce |pointer_order_span| by the number of hidden tracks
over the span */
*canvas_pointer_order_span = *pointer_order_span;
if (last_pointer_view->order() >= current_pointer_view->order()) {
for (int32_t y = current_pointer_view->order(); y < last_pointer_view->order(); y++) {
if (tavs.height_list[y] == 0) {
*canvas_pointer_order_span--;
}
}
} else {
for (int32_t y = last_pointer_view->order(); y <= current_pointer_view->order(); y++) {
if (tavs.height_list[y] == 0) {
*canvas_pointer_order_span++;
}
}
}
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
RegionView* rv = i->view;
if (rv->region()->locked()) {
continue;
}
double ix1, ix2, iy1, iy2;
rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
rv->get_canvas_frame()->i2w (ix1, iy1);
iy1 += _editor->vertical_adjustment.get_value() - _editor->canvas_timebars_vsize;
/* get the new trackview for this particular region */
pair<TimeAxisView*, int> const tvp = _editor->trackview_by_y_position (iy1);
assert (tvp.first);
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tvp.first);
/* XXX: not sure that we should be passing canvas_pointer_order_span in here,
as surely this is a per-region thing... */
clamp_y_axis = y_movement_disallowed (
rtv->order(), last_pointer_view->order(), *canvas_pointer_order_span, tavs
);
if (clamp_y_axis) {
break;
}
}
} else if (_dest_trackview == current_pointer_view) {
if (current_pointer_layer == last_pointer_layer) {
/* No movement; clamp */
clamp_y_axis = true;
}
}
if (!clamp_y_axis) {
_dest_trackview = current_pointer_view;
_dest_layer = current_pointer_layer;
}
return clamp_y_axis;
}
double double
RegionMotionDrag::compute_x_delta (GdkEvent const * event, nframes64_t* pending_region_position) RegionMotionDrag::compute_x_delta (GdkEvent const * event, nframes64_t* pending_region_position)
{ {
@ -539,7 +456,10 @@ RegionMotionDrag::compute_x_delta (GdkEvent const * event, nframes64_t* pending_
double dx = 0; double dx = 0;
if ((*pending_region_position != _last_frame_position) && x_move_allowed ()) { /* in locked edit mode, reverse the usual meaning of _x_constrained */
bool const x_move_allowed = Config->get_edit_mode() == Lock ? _x_constrained : !_x_constrained;
if ((*pending_region_position != _last_frame_position) && x_move_allowed) {
/* x movement since last time */ /* x movement since last time */
dx = (static_cast<double> (*pending_region_position) - _last_frame_position) / _editor->frames_per_unit; dx = (static_cast<double> (*pending_region_position) - _last_frame_position) / _editor->frames_per_unit;
@ -565,67 +485,78 @@ RegionMotionDrag::compute_x_delta (GdkEvent const * event, nframes64_t* pending_
return dx; return dx;
} }
bool
RegionMotionDrag::y_movement_allowed (int delta_track, layer_t delta_layer) const
{
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
int const n = i->time_axis_view + delta_track;
if (n < 0 || n >= int (_time_axis_views.size())) {
/* off the top or bottom track */
return false;
}
RouteTimeAxisView const * to = dynamic_cast<RouteTimeAxisView const *> (_time_axis_views[n]);
if (to == 0 || !to->is_track() || to->track()->data_type() != i->view->region()->data_type()) {
/* not a track, or the wrong type */
return false;
}
int const l = i->layer + delta_layer;
if (delta_track == 0 && (l < 0 || l >= int (to->view()->layers()))) {
/* Off the top or bottom layer; note that we only refuse if the track hasn't changed.
If it has, the layers will be munged later anyway, so it's ok.
*/
return false;
}
}
/* all regions being dragged are ok with this change */
return true;
}
void void
RegionMotionDrag::motion (GdkEvent* event, bool first_move) RegionMotionDrag::motion (GdkEvent* event, bool first_move)
{ {
double y_delta = 0; /* Find the TimeAxisView that the pointer is now over */
pair<TimeAxisView*, int> const tv = _editor->trackview_by_y_position (_drags->current_pointer_y ());
TimeAxisViewSummary tavs = get_time_axis_view_summary (); /* Bail early if we're not over a track */
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv.first);
vector<int32_t>::iterator j; if (!rtv || !rtv->is_track()) {
_editor->hide_verbose_canvas_cursor ();
/* *pointer* variables reflect things about the pointer; as we may be moving
multiple regions, much detail must be computed per-region */
/* current_pointer_view will become the TimeAxisView that we're currently pointing at, and
current_pointer_layer the current layer on that TimeAxisView; in this code layer numbers
are with respect to how the view's layers are displayed; if we are in Overlaid mode, layer
is always 0 regardless of what the region's "real" layer is */
RouteTimeAxisView* current_pointer_view;
layer_t current_pointer_layer;
if (!check_possible (&current_pointer_view, &current_pointer_layer)) {
return; return;
} }
/* TimeAxisView that we were pointing at last time we entered this method */ /* Note: time axis views in this method are often expressed as an index into the _time_axis_views vector */
TimeAxisView const * const last_pointer_view = _dest_trackview;
/* the order of the track that we were pointing at last time we entered this method */
int32_t const last_pointer_order = last_pointer_view->order ();
/* the layer that we were pointing at last time we entered this method */
layer_t const last_pointer_layer = _dest_layer;
int32_t pointer_order_span; /* Here's the current pointer position in terms of time axis view and layer */
int32_t pointer_layer_span; int const current_pointer_time_axis_view = find_time_axis_view (tv.first);
int32_t canvas_pointer_order_span; layer_t const current_pointer_layer = tv.first->layer_display() == Overlaid ? 0 : tv.second;
bool const clamp_y_axis = compute_y_delta ( /* Work out the change in x */
last_pointer_view, current_pointer_view, framepos_t pending_region_position;
last_pointer_layer, current_pointer_layer, tavs,
&pointer_order_span, &pointer_layer_span,
&canvas_pointer_order_span
);
nframes64_t pending_region_position;
double const x_delta = compute_x_delta (event, &pending_region_position); double const x_delta = compute_x_delta (event, &pending_region_position);
/************************************************************* /* Work out the change in y */
PREPARE TO MOVE int delta_time_axis_view = current_pointer_time_axis_view - _last_pointer_time_axis_view;
************************************************************/ int delta_layer = current_pointer_layer - _last_pointer_layer;
if (x_delta == 0 && pointer_order_span == 0 && pointer_layer_span == 0 && !first_move) { if (!y_movement_allowed (delta_time_axis_view, delta_layer)) {
/* this y movement is not allowed, so do no y movement this time */
delta_time_axis_view = 0;
delta_layer = 0;
}
if (x_delta == 0 && delta_time_axis_view == 0 && delta_layer == 0 && !first_move) {
/* haven't reached next snap point, and we're not switching /* haven't reached next snap point, and we're not switching
trackviews nor layers. nothing to do. trackviews nor layers. nothing to do.
*/ */
return; return;
} }
/*************************************************************
MOTION
************************************************************/
pair<set<boost::shared_ptr<Playlist> >::iterator,bool> insert_result; pair<set<boost::shared_ptr<Playlist> >::iterator,bool> insert_result;
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) { for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
RegionView* rv = i->view; RegionView* rv = i->view;
@ -633,6 +564,8 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
continue; continue;
} }
if (first_move) {
/* here we are calculating the y distance from the /* here we are calculating the y distance from the
top of the first track view to the top of the region top of the first track view to the top of the region
area of the track view that we're working on */ area of the track view that we're working on */
@ -655,8 +588,6 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
/* compensate for the ruler section and the vertical scrollbar position */ /* compensate for the ruler section and the vertical scrollbar position */
iy1 += _editor->get_trackview_group_vertical_offset (); iy1 += _editor->get_trackview_group_vertical_offset ();
if (first_move) {
// hide any dependent views // hide any dependent views
rv->get_time_axis_view().hide_dependent_views (*rv); rv->get_time_axis_view().hide_dependent_views (*rv);
@ -674,108 +605,50 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
rv->fake_set_opaque (true); rv->fake_set_opaque (true);
} }
/* current view for this particular region */ /* Work out the change in y position of this region view */
pair<TimeAxisView*, int> pos = _editor->trackview_by_y_position (iy1);
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (pos.first);
if (pointer_order_span != 0 && !clamp_y_axis) { double y_delta = 0;
/* INTER-TRACK MOVEMENT */ /* If we have moved tracks, we'll fudge the layer delta so that the
region gets moved back onto layer 0 on its new track; this avoids
/* move through the height list to the track that the region is currently on */ confusion when dragging regions from non-zero layers onto different
vector<int32_t>::iterator j = tavs.height_list.begin (); tracks.
int32_t x = 0; */
while (j != tavs.height_list.end () && x != rtv->order ()) { int this_delta_layer = delta_layer;
++x; if (delta_time_axis_view != 0) {
++j; this_delta_layer = - i->layer;
} }
y_delta = 0; /* Move this region to layer 0 on its old track */
int32_t temp_pointer_order_span = canvas_pointer_order_span; StreamView* lv = _time_axis_views[i->time_axis_view]->view ();
if (j != tavs.height_list.end ()) {
/* Account for layers in the original and
destination tracks. If we're moving around in layers we assume
that only one track is involved, so it's ok to use *pointer*
variables here. */
StreamView* lv = last_pointer_view->view ();
assert (lv);
/* move to the top of the last trackview */
if (lv->layer_display() == Stacked) { if (lv->layer_display() == Stacked) {
y_delta -= (lv->layers() - last_pointer_layer - 1) * lv->child_height (); y_delta -= (lv->layers() - i->layer - 1) * lv->child_height ();
} }
StreamView* cv = current_pointer_view->view (); /* Now move it to its right layer on the current track */
assert (cv); StreamView* cv = _time_axis_views[i->time_axis_view + delta_time_axis_view]->view ();
/* move to the right layer on the current trackview */
if (cv->layer_display() == Stacked) { if (cv->layer_display() == Stacked) {
y_delta += (cv->layers() - current_pointer_layer - 1) * cv->child_height (); y_delta += (cv->layers() - (i->layer + this_delta_layer) - 1) * cv->child_height ();
} }
/* And for being on a non-topmost layer on the new /* Move tracks */
track */ if (delta_time_axis_view > 0) {
for (int j = 0; j < delta_time_axis_view; ++j) {
while (temp_pointer_order_span > 0) { y_delta += _time_axis_views[i->time_axis_view + j]->current_height ();
/* we're moving up canvas-wise,
so we need to find the next track height
*/
if (j != tavs.height_list.begin()) {
j--;
} }
} else {
if (x != last_pointer_order) { /* start by subtracting the height of the track above where we are now */
if ((*j) == 0) { for (int j = 1; j <= -delta_time_axis_view; ++j) {
++temp_pointer_order_span; y_delta -= _time_axis_views[i->time_axis_view - j]->current_height ();
} }
} }
y_delta -= (*j); /* Set height */
temp_pointer_order_span--; rv->set_height (_time_axis_views[i->time_axis_view + delta_time_axis_view]->view()->child_height ());
}
while (temp_pointer_order_span < 0) { /* Update the DraggingView */
i->time_axis_view += delta_time_axis_view;
y_delta += (*j); i->layer += this_delta_layer;
if (x != last_pointer_order) {
if ((*j) == 0) {
--temp_pointer_order_span;
}
}
if (j != tavs.height_list.end()) {
j++;
}
temp_pointer_order_span++;
}
/* find out where we'll be when we move and set height accordingly */
pair<TimeAxisView*, int> const pos = _editor->trackview_by_y_position (iy1 + y_delta);
RouteTimeAxisView const * temp_rtv = dynamic_cast<RouteTimeAxisView*> (pos.first);
rv->set_height (temp_rtv->view()->child_height());
/* if you un-comment the following, the region colours will follow
the track colours whilst dragging; personally
i think this can confuse things, but never mind.
*/
//const GdkColor& col (temp_rtv->view->get_region_color());
//rv->set_color (const_cast<GdkColor&>(col));
}
}
if (pointer_order_span == 0 && pointer_layer_span != 0 && !clamp_y_axis) {
/* INTER-LAYER MOVEMENT in the same track */
y_delta = rtv->view()->child_height () * pointer_layer_span;
}
if (_brushing) { if (_brushing) {
_editor->mouse_brush_insert_region (rv, pending_region_position); _editor->mouse_brush_insert_region (rv, pending_region_position);
@ -794,20 +667,82 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
if (x_delta != 0 && !_brushing) { if (x_delta != 0 && !_brushing) {
_editor->show_verbose_time_cursor (_last_frame_position, 10); _editor->show_verbose_time_cursor (_last_frame_position, 10);
} }
_last_pointer_time_axis_view += delta_time_axis_view;
_last_pointer_layer += delta_layer;
} }
void void
RegionMoveDrag::motion (GdkEvent* event, bool first_move) RegionMoveDrag::motion (GdkEvent* event, bool first_move)
{ {
if (_copy && first_move) { if (_copy && first_move) {
copy_regions (event);
/* duplicate the regionview(s) and region(s) */
list<DraggingView> new_regionviews;
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
RegionView* rv = i->view;
AudioRegionView* arv = dynamic_cast<AudioRegionView*>(rv);
MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(rv);
const boost::shared_ptr<const Region> original = rv->region();
boost::shared_ptr<Region> region_copy = RegionFactory::create (original);
region_copy->set_position (original->position(), this);
RegionView* nrv;
if (arv) {
boost::shared_ptr<AudioRegion> audioregion_copy
= boost::dynamic_pointer_cast<AudioRegion>(region_copy);
nrv = new AudioRegionView (*arv, audioregion_copy);
} else if (mrv) {
boost::shared_ptr<MidiRegion> midiregion_copy
= boost::dynamic_pointer_cast<MidiRegion>(region_copy);
nrv = new MidiRegionView (*mrv, midiregion_copy);
} else {
continue;
}
nrv->get_canvas_group()->show ();
new_regionviews.push_back (DraggingView (nrv, this));
/* swap _primary to the copy */
if (rv == _primary) {
_primary = nrv;
}
/* ..and deselect the one we copied */
rv->set_selected (false);
}
if (!new_regionviews.empty()) {
/* reflect the fact that we are dragging the copies */
_views = new_regionviews;
swap_grab (new_regionviews.front().view->get_canvas_group (), 0, event ? event->motion.time : 0);
/*
sync the canvas to what we think is its current state
without it, the canvas seems to
"forget" to update properly after the upcoming reparent()
..only if the mouse is in rapid motion at the time of the grab.
something to do with regionview creation taking so long?
*/
_editor->update_canvas_now();
}
} }
RegionMotionDrag::motion (event, first_move); RegionMotionDrag::motion (event, first_move);
} }
void void
RegionMoveDrag::finished (GdkEvent* /*event*/, bool movement_occurred) RegionMoveDrag::finished (GdkEvent *, bool movement_occurred)
{ {
if (!movement_occurred) { if (!movement_occurred) {
/* just a click */ /* just a click */
@ -823,7 +758,7 @@ RegionMoveDrag::finished (GdkEvent* /*event*/, bool movement_occurred)
} }
bool const changed_position = (_last_frame_position != (nframes64_t) (_primary->region()->position())); bool const changed_position = (_last_frame_position != (nframes64_t) (_primary->region()->position()));
bool const changed_tracks = (_dest_trackview != &_primary->get_time_axis_view()); bool const changed_tracks = (_time_axis_views[_views.front().time_axis_view] != &_views.front().view->get_time_axis_view());
framecnt_t const drag_delta = _primary->region()->position() - _last_frame_position; framecnt_t const drag_delta = _primary->region()->position() - _last_frame_position;
_editor->update_canvas_now (); _editor->update_canvas_now ();
@ -831,7 +766,6 @@ RegionMoveDrag::finished (GdkEvent* /*event*/, bool movement_occurred)
if (_copy) { if (_copy) {
finished_copy ( finished_copy (
find_time_axis_views_and_layers (),
changed_position, changed_position,
changed_tracks, changed_tracks,
drag_delta drag_delta
@ -840,7 +774,6 @@ RegionMoveDrag::finished (GdkEvent* /*event*/, bool movement_occurred)
} else { } else {
finished_no_copy ( finished_no_copy (
find_time_axis_views_and_layers (),
changed_position, changed_position,
changed_tracks, changed_tracks,
drag_delta drag_delta
@ -851,7 +784,6 @@ RegionMoveDrag::finished (GdkEvent* /*event*/, bool movement_occurred)
void void
RegionMoveDrag::finished_copy ( RegionMoveDrag::finished_copy (
map<RegionView*, pair<RouteTimeAxisView*, int> > const & final,
bool const changed_position, bool const changed_position,
bool const changed_tracks, bool const changed_tracks,
framecnt_t const drag_delta framecnt_t const drag_delta
@ -881,23 +813,20 @@ RegionMoveDrag::finished_copy (
/* insert the regions into their new playlists */ /* insert the regions into their new playlists */
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) { for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
nframes64_t where;
if (i->view->region()->locked()) { if (i->view->region()->locked()) {
continue; continue;
} }
nframes64_t where;
if (changed_position && !_x_constrained) { if (changed_position && !_x_constrained) {
where = i->view->region()->position() - drag_delta; where = i->view->region()->position() - drag_delta;
} else { } else {
where = i->view->region()->position(); where = i->view->region()->position();
} }
map<RegionView*, pair<RouteTimeAxisView*, int> >::const_iterator j = final.find (i->view);
assert (j != final.end());
RegionView* new_view = insert_region_into_playlist ( RegionView* new_view = insert_region_into_playlist (
i->view->region(), j->second.first, j->second.second, where, modified_playlists i->view->region(), dynamic_cast<RouteTimeAxisView*> (_time_axis_views[i->time_axis_view]), i->layer, where, modified_playlists
); );
if (new_view == 0) { if (new_view == 0) {
@ -934,7 +863,6 @@ RegionMoveDrag::finished_copy (
void void
RegionMoveDrag::finished_no_copy ( RegionMoveDrag::finished_no_copy (
map<RegionView*, pair<RouteTimeAxisView*, int> > const & final,
bool const changed_position, bool const changed_position,
bool const changed_tracks, bool const changed_tracks,
framecnt_t const drag_delta framecnt_t const drag_delta
@ -960,11 +888,8 @@ RegionMoveDrag::finished_no_copy (
RegionView* rv = i->view; RegionView* rv = i->view;
map<RegionView*, pair<RouteTimeAxisView*, int> >::const_iterator j = final.find (rv); RouteTimeAxisView* const dest_rtv = dynamic_cast<RouteTimeAxisView*> (_time_axis_views[i->time_axis_view]);
assert (j != final.end()); layer_t const dest_layer = i->layer;
RouteTimeAxisView* dest_rtv = j->second.first;
layer_t dest_layer = j->second.second;
if (rv->region()->locked()) { if (rv->region()->locked()) {
++i; ++i;
@ -1226,212 +1151,12 @@ RegionMotionDrag::aborted ()
_editor->update_canvas_now (); _editor->update_canvas_now ();
} }
bool
RegionMotionDrag::x_move_allowed () const
{
if (Config->get_edit_mode() == Lock) {
/* in locked edit mode, reverse the usual meaning of _x_constrained */
return _x_constrained;
}
return !_x_constrained;
}
void
RegionMotionDrag::copy_regions (GdkEvent* event)
{
/* duplicate the regionview(s) and region(s) */
list<DraggingView> new_regionviews;
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
RegionView* rv = i->view;
AudioRegionView* arv = dynamic_cast<AudioRegionView*>(rv);
MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(rv);
const boost::shared_ptr<const Region> original = rv->region();
boost::shared_ptr<Region> region_copy = RegionFactory::create (original);
region_copy->set_position (original->position(), this);
RegionView* nrv;
if (arv) {
boost::shared_ptr<AudioRegion> audioregion_copy
= boost::dynamic_pointer_cast<AudioRegion>(region_copy);
nrv = new AudioRegionView (*arv, audioregion_copy);
} else if (mrv) {
boost::shared_ptr<MidiRegion> midiregion_copy
= boost::dynamic_pointer_cast<MidiRegion>(region_copy);
nrv = new MidiRegionView (*mrv, midiregion_copy);
} else {
continue;
}
nrv->get_canvas_group()->show ();
new_regionviews.push_back (DraggingView (nrv));
/* swap _primary to the copy */
if (rv == _primary) {
_primary = nrv;
}
/* ..and deselect the one we copied */
rv->set_selected (false);
}
if (new_regionviews.empty()) {
return;
}
/* reflect the fact that we are dragging the copies */
_views = new_regionviews;
swap_grab (new_regionviews.front().view->get_canvas_group (), 0, event ? event->motion.time : 0);
/*
sync the canvas to what we think is its current state
without it, the canvas seems to
"forget" to update properly after the upcoming reparent()
..only if the mouse is in rapid motion at the time of the grab.
something to do with regionview creation taking so long?
*/
_editor->update_canvas_now();
}
bool
RegionMotionDrag::check_possible (RouteTimeAxisView** tv, layer_t* layer)
{
/* Which trackview is this ? */
pair<TimeAxisView*, int> const tvp = _editor->trackview_by_y_position (_drags->current_pointer_y ());
(*tv) = dynamic_cast<RouteTimeAxisView*> (tvp.first);
(*layer) = tvp.second;
if (*tv && (*tv)->layer_display() == Overlaid) {
*layer = 0;
}
/* The region motion is only processed if the pointer is over
an audio track.
*/
if (!(*tv) || !(*tv)->is_track()) {
/* To make sure we hide the verbose canvas cursor when the mouse is
not held over and audiotrack.
*/
_editor->hide_verbose_canvas_cursor ();
return false;
}
return true;
}
/** @param new_order New track order.
* @param old_order Old track order.
* @param visible_y_low Lowest visible order.
* @return true if y movement should not happen, otherwise false.
*/
bool
RegionMotionDrag::y_movement_disallowed (int new_order, int old_order, int y_span, TimeAxisViewSummary const & tavs) const
{
if (new_order != old_order) {
/* this isn't the pointer track */
if (y_span > 0) {
/* moving up the canvas */
if ( (new_order - y_span) >= tavs.visible_y_low) {
int32_t n = 0;
/* work out where we'll end up with this y span, taking hidden TimeAxisViews into account */
int32_t visible_tracks = 0;
while (visible_tracks < y_span ) {
visible_tracks++;
while (tavs.height_list[new_order - (visible_tracks - n)] == 0) {
/* passing through a hidden track */
n--;
}
}
if (tavs.tracks[new_order - (y_span - n)] != 0x00) {
/* moving to a non-track; disallow */
return true;
}
} else {
/* moving beyond the lowest visible track; disallow */
return true;
}
} else if (y_span < 0) {
/* moving down the canvas */
if ((new_order - y_span) <= tavs.visible_y_high) {
int32_t visible_tracks = 0;
int32_t n = 0;
while (visible_tracks > y_span ) {
visible_tracks--;
while (tavs.height_list[new_order - (visible_tracks - n)] == 0) {
/* passing through a hidden track */
n++;
}
}
if (tavs.tracks[new_order - (y_span - n)] != 0x00) {
/* moving to a non-track; disallow */
return true;
}
} else {
/* moving beyond the highest visible track; disallow */
return true;
}
}
} else {
/* this is the pointer's track */
if ((new_order - y_span) > tavs.visible_y_high) {
/* we will overflow */
return true;
} else if ((new_order - y_span) < tavs.visible_y_low) {
/* we will overflow */
return true;
}
}
return false;
}
RegionMoveDrag::RegionMoveDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v, bool b, bool c) RegionMoveDrag::RegionMoveDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v, bool b, bool c)
: RegionMotionDrag (e, i, p, v, b), : RegionMotionDrag (e, i, p, v, b),
_copy (c) _copy (c)
{ {
TimeAxisView* const tv = &_primary->get_time_axis_view ();
_dest_trackview = tv;
if (tv->layer_display() == Overlaid) {
_dest_layer = 0;
} else {
_dest_layer = _primary->region()->layer ();
}
double speed = 1; double speed = 1;
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv); RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (&_primary->get_time_axis_view ());
if (rtv && rtv->is_track()) { if (rtv && rtv->is_track()) {
speed = rtv->track()->speed (); speed = rtv->track()->speed ();
} }
@ -1457,44 +1182,19 @@ RegionInsertDrag::RegionInsertDrag (Editor* e, boost::shared_ptr<Region> r, Rout
_primary->get_canvas_group()->show (); _primary->get_canvas_group()->show ();
_primary->set_position (pos, 0); _primary->set_position (pos, 0);
_views.push_back (DraggingView (_primary)); _views.push_back (DraggingView (_primary, this));
_last_frame_position = pos; _last_frame_position = pos;
_item = _primary->get_canvas_group (); _item = _primary->get_canvas_group ();
_dest_trackview = v;
_dest_layer = _primary->region()->layer ();
} }
map<RegionView*, pair<RouteTimeAxisView*, int> >
RegionMotionDrag::find_time_axis_views_and_layers ()
{
map<RegionView*, pair<RouteTimeAxisView*, int> > tav;
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
double ix1, ix2, iy1, iy2;
RegionView* rv = i->view;
rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
rv->get_canvas_frame()->i2w (ix1, iy1);
iy1 += _editor->vertical_adjustment.get_value() - _editor->canvas_timebars_vsize;
pair<TimeAxisView*, int> tv = _editor->trackview_by_y_position (iy1);
tav[rv] = make_pair (dynamic_cast<RouteTimeAxisView*> (tv.first), tv.second);
}
return tav;
}
void void
RegionInsertDrag::finished (GdkEvent* /*event*/, bool /*movement_occurred*/) RegionInsertDrag::finished (GdkEvent *, bool)
{ {
_editor->update_canvas_now (); _editor->update_canvas_now ();
map<RegionView*, pair<RouteTimeAxisView*, int> > final = find_time_axis_views_and_layers (); RouteTimeAxisView* dest_rtv = dynamic_cast<RouteTimeAxisView*> (_time_axis_views[_views.front().time_axis_view]);
RouteTimeAxisView* dest_rtv = final[_primary].first;
_primary->get_canvas_group()->reparent (*dest_rtv->view()->canvas_item()); _primary->get_canvas_group()->reparent (*dest_rtv->view()->canvas_item());
_primary->get_canvas_group()->property_y() = 0; _primary->get_canvas_group()->property_y() = 0;
@ -1535,10 +1235,25 @@ struct RegionSelectionByPosition {
void void
RegionSpliceDrag::motion (GdkEvent* event, bool) RegionSpliceDrag::motion (GdkEvent* event, bool)
{ {
RouteTimeAxisView* tv; /* Which trackview is this ? */
layer_t layer;
if (!check_possible (&tv, &layer)) { pair<TimeAxisView*, int> const tvp = _editor->trackview_by_y_position (_drags->current_pointer_y ());
RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*> (tvp.first);
layer_t layer = tvp.second;
if (tv && tv->layer_display() == Overlaid) {
layer = 0;
}
/* The region motion is only processed if the pointer is over
an audio track.
*/
if (!tv || !tv->is_track()) {
/* To make sure we hide the verbose canvas cursor when the mouse is
not held over and audiotrack.
*/
_editor->hide_verbose_canvas_cursor ();
return; return;
} }
@ -1591,9 +1306,9 @@ RegionSpliceDrag::motion (GdkEvent* event, bool)
} }
void void
RegionSpliceDrag::finished (GdkEvent* /*event*/, bool) RegionSpliceDrag::finished (GdkEvent* event, bool movement_occurred)
{ {
RegionMoveDrag::finished (event, movement_occurred);
} }
void void
@ -1748,7 +1463,7 @@ TrimDrag::TrimDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<Region
} }
void void
TrimDrag::start_grab (GdkEvent* event, Gdk::Cursor *) TrimDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
{ {
double speed = 1.0; double speed = 1.0;
TimeAxisView* tvp = &_primary->get_time_axis_view (); TimeAxisView* tvp = &_primary->get_time_axis_view ();
@ -3028,7 +2743,6 @@ FeatureLineDrag::FeatureLineDrag (Editor* e, ArdourCanvas::Item* i)
void void
FeatureLineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/) FeatureLineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
{ {
Drag::start_grab (event); Drag::start_grab (event);
_line = reinterpret_cast<SimpleLine*> (_item); _line = reinterpret_cast<SimpleLine*> (_item);
@ -3197,9 +2911,9 @@ RubberbandSelectDrag::aborted ()
} }
void void
TimeFXDrag::start_grab (GdkEvent* event, Gdk::Cursor *) TimeFXDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
{ {
Drag::start_grab (event); Drag::start_grab (event, cursor);
_editor->show_verbose_time_cursor (adjusted_current_frame (event), 10); _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10);
} }
@ -4074,9 +3788,11 @@ AutomationRangeDrag::aborted ()
_line->reset (); _line->reset ();
} }
DraggingView::DraggingView (RegionView* v) DraggingView::DraggingView (RegionView* v, RegionDrag* parent)
: view (v) : view (v)
{ {
time_axis_view = parent->find_time_axis_view (&v->get_time_axis_view ());
layer = v->region()->layer ();
initial_y = v->get_canvas_group()->property_y (); initial_y = v->get_canvas_group()->property_y ();
initial_playlist = v->region()->playlist (); initial_playlist = v->region()->playlist ();
} }

View file

@ -221,11 +221,18 @@ private:
nframes64_t _last_pointer_frame; ///< adjusted_frame the last time a motion occurred nframes64_t _last_pointer_frame; ///< adjusted_frame the last time a motion occurred
}; };
class RegionDrag;
/** Container for details about a region being dragged */
struct DraggingView struct DraggingView
{ {
DraggingView (RegionView* v); DraggingView (RegionView *, RegionDrag *);
RegionView* view; ///< the view RegionView* view; ///< the view
/** index into RegionDrag::_time_axis_views of the view that this region is currently beind displayed on */
int time_axis_view;
/** layer that this region is currently being displayed on */
ARDOUR::layer_t layer;
double initial_y; ///< the initial y position of the view before any reparenting double initial_y; ///< the initial y position of the view before any reparenting
boost::shared_ptr<ARDOUR::Playlist> initial_playlist; boost::shared_ptr<ARDOUR::Playlist> initial_playlist;
}; };
@ -242,7 +249,17 @@ protected:
RegionView* _primary; ///< the view that was clicked on (or whatever) to start the drag RegionView* _primary; ///< the view that was clicked on (or whatever) to start the drag
std::list<DraggingView> _views; ///< information about all views that are being dragged std::list<DraggingView> _views; ///< information about all views that are being dragged
/** a list of the non-hidden TimeAxisViews sorted by editor order key */
std::vector<TimeAxisView*> _time_axis_views;
int find_time_axis_view (TimeAxisView *) const;
int _visible_y_low;
int _visible_y_high;
friend class DraggingView;
private: private:
void region_going_away (RegionView *); void region_going_away (RegionView *);
PBD::ScopedConnection death_connection; PBD::ScopedConnection death_connection;
}; };
@ -267,33 +284,15 @@ public:
virtual bool regions_came_from_canvas () const = 0; virtual bool regions_came_from_canvas () const = 0;
protected: protected:
struct TimeAxisViewSummary {
TimeAxisViewSummary () : height_list(512) {}
std::bitset<512> tracks;
std::vector<int32_t> height_list;
int visible_y_low;
int visible_y_high;
};
void copy_regions (GdkEvent *);
bool y_movement_disallowed (int, int, int, TimeAxisViewSummary const &) const;
std::map<RegionView*, std::pair<RouteTimeAxisView*, int> > find_time_axis_views_and_layers ();
double compute_x_delta (GdkEvent const *, nframes64_t *); double compute_x_delta (GdkEvent const *, nframes64_t *);
bool compute_y_delta ( bool y_movement_allowed (int, ARDOUR::layer_t) const;
TimeAxisView const *, TimeAxisView*, int32_t, int32_t, TimeAxisViewSummary const &,
int32_t *, int32_t *, int32_t *
);
TimeAxisViewSummary get_time_axis_view_summary ();
bool x_move_allowed () const;
TimeAxisView* _dest_trackview;
ARDOUR::layer_t _dest_layer;
bool check_possible (RouteTimeAxisView **, ARDOUR::layer_t *);
bool _brushing; bool _brushing;
nframes64_t _last_frame_position; ///< last position of the thing being dragged nframes64_t _last_frame_position; ///< last position of the thing being dragged
double _total_x_delta; double _total_x_delta;
int _last_pointer_time_axis_view;
ARDOUR::layer_t _last_pointer_layer;
}; };
@ -323,14 +322,12 @@ private:
typedef std::set<boost::shared_ptr<ARDOUR::Playlist> > PlaylistSet; typedef std::set<boost::shared_ptr<ARDOUR::Playlist> > PlaylistSet;
void finished_no_copy ( void finished_no_copy (
std::map<RegionView*, std::pair<RouteTimeAxisView*, int> > const &,
bool const, bool const,
bool const, bool const,
ARDOUR::framecnt_t const ARDOUR::framecnt_t const
); );
void finished_copy ( void finished_copy (
std::map<RegionView*, std::pair<RouteTimeAxisView*, int> > const &,
bool const, bool const,
bool const, bool const,
ARDOUR::framecnt_t const ARDOUR::framecnt_t const

View file

@ -4131,7 +4131,7 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs)
} }
} }
TimeAxisView* tv = &(*x)->get_trackview(); TimeAxisView* tv = &(*x)->get_time_axis_view();
vector<PlaylistMapping>::iterator z; vector<PlaylistMapping>::iterator z;
for (z = pmap.begin(); z != pmap.end(); ++z) { for (z = pmap.begin(); z != pmap.end(); ++z) {
@ -4154,7 +4154,7 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs)
continue; continue;
} }
TimeAxisView& tv = (*x)->get_trackview(); TimeAxisView& tv = (*x)->get_time_axis_view();
boost::shared_ptr<Playlist> npl; boost::shared_ptr<Playlist> npl;
RegionSelection::iterator tmp; RegionSelection::iterator tmp;

View file

@ -430,7 +430,7 @@ Editor::mapped_get_equivalent_regions (RouteTimeAxisView& tv, uint32_t, RegionVi
void void
Editor::get_equivalent_regions (RegionView* basis, vector<RegionView*>& equivalent_regions, PBD::PropertyID property) const Editor::get_equivalent_regions (RegionView* basis, vector<RegionView*>& equivalent_regions, PBD::PropertyID property) const
{ {
mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_get_equivalent_regions), basis, &equivalent_regions), &basis->get_trackview(), property); mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_get_equivalent_regions), basis, &equivalent_regions), &basis->get_time_axis_view(), property);
/* add clicked regionview since we skipped all other regions in the same track as the one it was in */ /* add clicked regionview since we skipped all other regions in the same track as the one it was in */
@ -448,7 +448,7 @@ Editor::get_equivalent_regions (RegionSelection & basis, PBD::PropertyID prop) c
mapover_tracks ( mapover_tracks (
sigc::bind (sigc::mem_fun (*this, &Editor::mapped_get_equivalent_regions), *i, &eq), sigc::bind (sigc::mem_fun (*this, &Editor::mapped_get_equivalent_regions), *i, &eq),
&(*i)->get_trackview(), prop &(*i)->get_time_axis_view(), prop
); );
for (vector<RegionView*>::iterator j = eq.begin(); j != eq.end(); ++j) { for (vector<RegionView*>::iterator j = eq.begin(); j != eq.end(); ++j) {

View file

@ -253,10 +253,10 @@ struct RegionSortByTrack {
/* really, track and position */ /* really, track and position */
if (a->get_trackview().order() == b->get_trackview().order()) { if (a->get_time_axis_view().order() == b->get_time_axis_view().order()) {
return a->region()->position() < b->region()->position(); return a->region()->position() < b->region()->position();
} else { } else {
return a->get_trackview().order() < b->get_trackview().order(); return a->get_time_axis_view().order() < b->get_time_axis_view().order();
} }
} }
}; };
@ -298,7 +298,7 @@ bool
RegionSelection::involves (const TimeAxisView& tv) const RegionSelection::involves (const TimeAxisView& tv) const
{ {
for (RegionSelection::const_iterator i = begin(); i != end(); ++i) { for (RegionSelection::const_iterator i = begin(); i != end(); ++i) {
if (&(*i)->get_trackview() == &tv) { if (&(*i)->get_time_axis_view() == &tv) {
return true; return true;
} }
} }

View file

@ -400,7 +400,7 @@ Selection::add (vector<RegionView*>& v)
if (find (regions.begin(), regions.end(), (*i)) == regions.end()) { if (find (regions.begin(), regions.end(), (*i)) == regions.end()) {
changed = regions.add ((*i)); changed = regions.add ((*i));
if (Config->get_link_region_and_track_selection() && changed) { if (Config->get_link_region_and_track_selection() && changed) {
add (&(*i)->get_trackview()); add (&(*i)->get_time_axis_view());
} }
} }
} }
@ -422,7 +422,7 @@ Selection::add (const RegionSelection& rs)
if (find (regions.begin(), regions.end(), (*i)) == regions.end()) { if (find (regions.begin(), regions.end(), (*i)) == regions.end()) {
changed = regions.add ((*i)); changed = regions.add ((*i));
if (Config->get_link_region_and_track_selection() && changed) { if (Config->get_link_region_and_track_selection() && changed) {
add (&(*i)->get_trackview()); add (&(*i)->get_time_axis_view());
} }
} }
} }
@ -438,7 +438,7 @@ Selection::add (RegionView* r)
if (find (regions.begin(), regions.end(), r) == regions.end()) { if (find (regions.begin(), regions.end(), r) == regions.end()) {
regions.add (r); regions.add (r);
if (Config->get_link_region_and_track_selection()) { if (Config->get_link_region_and_track_selection()) {
add (&r->get_trackview()); add (&r->get_time_axis_view());
} }
RegionsChanged (); RegionsChanged ();
} }
@ -452,7 +452,7 @@ Selection::add (MidiRegionView* mrv)
/* XXX should we do this? */ /* XXX should we do this? */
#if 0 #if 0
if (Config->get_link_region_and_track_selection()) { if (Config->get_link_region_and_track_selection()) {
add (&mrv->get_trackview()); add (&mrv->get_time_axis_view());
} }
#endif #endif
MidiRegionsChanged (); MidiRegionsChanged ();
@ -610,8 +610,8 @@ Selection::remove (RegionView* r)
RegionsChanged (); RegionsChanged ();
} }
if (Config->get_link_region_and_track_selection() && !regions.involves (r->get_trackview())) { if (Config->get_link_region_and_track_selection() && !regions.involves (r->get_time_axis_view())) {
remove (&r->get_trackview()); remove (&r->get_time_axis_view());
} }
} }
@ -627,8 +627,8 @@ Selection::remove (MidiRegionView* mrv)
#if 0 #if 0
/* XXX fix this up ? */ /* XXX fix this up ? */
if (Config->get_link_region_and_track_selection() && !regions.involves (r->get_trackview())) { if (Config->get_link_region_and_track_selection() && !regions.involves (r->get_time_axis_view())) {
remove (&r->get_trackview()); remove (&r->get_time_axis_view());
} }
#endif #endif
} }

View file

@ -472,7 +472,7 @@ TimeAxisViewItem::set_should_show_selection (bool yn)
/** @return the TimeAxisView that this item is on */ /** @return the TimeAxisView that this item is on */
TimeAxisView& TimeAxisView&
TimeAxisViewItem::get_time_axis_view() TimeAxisViewItem::get_time_axis_view () const
{ {
return trackview; return trackview;
} }

View file

@ -61,7 +61,7 @@ class TimeAxisViewItem : public Selectable, public PBD::ScopedConnectionList
virtual void set_should_show_selection (bool yn); virtual void set_should_show_selection (bool yn);
void set_sensitive (bool yn) { _sensitive = yn; } void set_sensitive (bool yn) { _sensitive = yn; }
bool sensitive () const { return _sensitive; } bool sensitive () const { return _sensitive; }
TimeAxisView& get_time_axis_view(); TimeAxisView& get_time_axis_view () const;
void set_name_text(const Glib::ustring&); void set_name_text(const Glib::ustring&);
virtual void set_height(double h); virtual void set_height(double h);
void set_y (double); void set_y (double);
@ -72,8 +72,6 @@ class TimeAxisViewItem : public Selectable, public PBD::ScopedConnectionList
ArdourCanvas::Item* get_name_highlight(); ArdourCanvas::Item* get_name_highlight();
ArdourCanvas::Pixbuf* get_name_pixbuf(); ArdourCanvas::Pixbuf* get_name_pixbuf();
TimeAxisView& get_trackview() const { return trackview; }
virtual void set_samples_per_unit(double spu); virtual void set_samples_per_unit(double spu);
double get_samples_per_unit(); double get_samples_per_unit();

View file

@ -45,6 +45,10 @@ class AudioTrack : public Track
void use_new_diskstream (); void use_new_diskstream ();
void set_diskstream (boost::shared_ptr<Diskstream>); void set_diskstream (boost::shared_ptr<Diskstream>);
DataType data_type () const {
return DataType::AUDIO;
}
int export_stuff (BufferSet& bufs, sframes_t start_frame, nframes_t nframes, bool enable_processing = true); int export_stuff (BufferSet& bufs, sframes_t start_frame, nframes_t nframes, bool enable_processing = true);
void freeze_me (InterThreadInfo&); void freeze_me (InterThreadInfo&);

View file

@ -48,6 +48,10 @@ public:
void set_diskstream (boost::shared_ptr<Diskstream>); void set_diskstream (boost::shared_ptr<Diskstream>);
void set_record_enabled (bool yn, void *src); void set_record_enabled (bool yn, void *src);
DataType data_type () const {
return DataType::MIDI;
}
void set_latency_delay (nframes_t); void set_latency_delay (nframes_t);
int export_stuff (BufferSet& bufs, nframes_t nframes, sframes_t end_frame); int export_stuff (BufferSet& bufs, nframes_t nframes, sframes_t end_frame);

View file

@ -60,6 +60,8 @@ class Track : public Route, public PublicDiskstream
bool needs_butler() const { return _needs_butler; } bool needs_butler() const { return _needs_butler; }
void toggle_monitor_input (); void toggle_monitor_input ();
virtual DataType data_type () const = 0;
bool can_record(); bool can_record();
virtual void use_new_diskstream () = 0; virtual void use_new_diskstream () = 0;