diff options
-rw-r--r-- | gtk2_ardour/audio_streamview.cc | 10 | ||||
-rw-r--r-- | gtk2_ardour/draginfo.h | 2 | ||||
-rw-r--r-- | gtk2_ardour/editor.cc | 16 | ||||
-rw-r--r-- | gtk2_ardour/editor.h | 9 | ||||
-rw-r--r-- | gtk2_ardour/editor_canvas.cc | 6 | ||||
-rw-r--r-- | gtk2_ardour/editor_canvas_events.cc | 8 | ||||
-rw-r--r-- | gtk2_ardour/editor_mouse.cc | 433 | ||||
-rw-r--r-- | gtk2_ardour/editor_ops.cc | 14 | ||||
-rw-r--r-- | gtk2_ardour/editor_rulers.cc | 5 | ||||
-rw-r--r-- | gtk2_ardour/route_time_axis.cc | 16 | ||||
-rw-r--r-- | gtk2_ardour/route_time_axis.h | 1 | ||||
-rw-r--r-- | gtk2_ardour/streamview.cc | 18 | ||||
-rw-r--r-- | gtk2_ardour/streamview.h | 8 | ||||
-rw-r--r-- | gtk2_ardour/time_axis_view.cc | 38 | ||||
-rw-r--r-- | gtk2_ardour/time_axis_view.h | 11 |
15 files changed, 375 insertions, 220 deletions
diff --git a/gtk2_ardour/audio_streamview.cc b/gtk2_ardour/audio_streamview.cc index f79955b100..85812b43d6 100644 --- a/gtk2_ardour/audio_streamview.cc +++ b/gtk2_ardour/audio_streamview.cc @@ -308,7 +308,7 @@ AudioStreamView::add_crossfade (boost::shared_ptr<Crossfade> crossfade) for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { if ((*i)->crossfade == crossfade) { - if (!crossfades_visible || layer_display == Stacked) { + if (!crossfades_visible || _layer_display == Stacked) { (*i)->hide(); } else { (*i)->show (); @@ -340,7 +340,7 @@ AudioStreamView::add_crossfade (boost::shared_ptr<Crossfade> crossfade) cv->set_valid (true); crossfade->Invalidated.connect (mem_fun (*this, &AudioStreamView::remove_crossfade)); crossfade_views.push_back (cv); - if (!Config->get_xfades_visible() || !crossfades_visible || layer_display == Stacked) { + if (!Config->get_xfades_visible() || !crossfades_visible || _layer_display == Stacked) { cv->hide (); } } @@ -373,7 +373,7 @@ AudioStreamView::redisplay_diskstream () for (xi = crossfade_views.begin(); xi != crossfade_views.end(); ++xi) { (*xi)->set_valid (false); - if ((*xi)->visible() && layer_display != Stacked) { + if ((*xi)->visible() && _layer_display != Stacked) { (*xi)->show (); } } @@ -806,7 +806,7 @@ void AudioStreamView::reveal_xfades_involving (AudioRegionView& rv) { for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { - if ((*i)->crossfade->involves (rv.audio_region()) && (*i)->visible() && layer_display != Stacked) { + if ((*i)->crossfade->involves (rv.audio_region()) && (*i)->visible() && _layer_display != Stacked) { (*i)->show (); } } @@ -836,7 +836,7 @@ AudioStreamView::update_contents_height () StreamView::update_contents_height (); for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { - if (layer_display == Overlaid) { + if (_layer_display == Overlaid) { (*i)->show (); (*i)->set_height (height); } else { diff --git a/gtk2_ardour/draginfo.h b/gtk2_ardour/draginfo.h index 6d3a6b8de3..e0fccb7f70 100644 --- a/gtk2_ardour/draginfo.h +++ b/gtk2_ardour/draginfo.h @@ -57,7 +57,9 @@ struct DragInfo { void (Editor::*motion_callback)(ArdourCanvas::Item*, GdkEvent*); void (Editor::*finished_callback)(ArdourCanvas::Item*, GdkEvent*); TimeAxisView* source_trackview; + ARDOUR::layer_t source_layer; TimeAxisView* dest_trackview; + ARDOUR::layer_t dest_layer; bool x_constrained; bool y_constrained; bool copy; diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 051eb6dd8a..5121fe0425 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -2722,19 +2722,23 @@ Editor::get_state () -TimeAxisView * +/** @param y y offset from the top of all trackviews. + * @return pair: TimeAxisView that y is over, layer index. + * TimeAxisView may be 0. Layer index is the layer number if the TimeAxisView is valid and is + * in stacked region display mode, otherwise 0. + */ +std::pair<TimeAxisView *, layer_t> Editor::trackview_by_y_position (double y) { for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) { - TimeAxisView *tv; - - if ((tv = (*iter)->covers_y_position (y)) != 0) { - return tv; + std::pair<TimeAxisView*, int> const r = (*iter)->covers_y_position (y); + if (r.first) { + return r; } } - return 0; + return std::make_pair ( (TimeAxisView *) 0, 0); } void diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 834313f9ae..732aea59ad 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -25,6 +25,7 @@ #include <set> #include <string> #include <sys/time.h> +#include <bitset> #include <glibmm/ustring.h> @@ -51,6 +52,7 @@ #include <ardour/location.h> #include <ardour/audioregion.h> #include <ardour/track.h> +#include <ardour/types.h> #include "audio_clock.h" #include "gtk-custom-ruler.h" @@ -1071,7 +1073,7 @@ class Editor : public PublicEditor /* track views */ TrackViewList track_views; - TimeAxisView *trackview_by_y_position (double ypos); + std::pair<TimeAxisView*, ARDOUR::layer_t> trackview_by_y_position (double); static Gdk::Cursor* cross_hair_cursor; static Gdk::Cursor* trimmer_cursor; @@ -1442,7 +1444,7 @@ class Editor : public PublicEditor void region_drag_finished_callback (ArdourCanvas::Item*, GdkEvent*); void create_region_drag_motion_callback (ArdourCanvas::Item*, GdkEvent*); void create_region_drag_finished_callback (ArdourCanvas::Item*, GdkEvent*); - bool check_region_drag_possible (RouteTimeAxisView**); + bool check_region_drag_possible (RouteTimeAxisView**, ARDOUR::layer_t*); void possibly_copy_regions_during_grab (GdkEvent*); void region_drag_splice_motion_callback (ArdourCanvas::Item*, GdkEvent*); void region_drag_splice_finished_callback (ArdourCanvas::Item*, GdkEvent*); @@ -2361,6 +2363,9 @@ public: bool idle_resize(); friend gboolean _idle_resize (gpointer); std::vector<TimeAxisView*> pending_resizes; + + void visible_order_range (int*, int*) const; + bool y_movement_disallowed (int, int, int, int, int, std::bitset<512> const &, std::vector<int32_t> const &) const; }; #endif /* __ardour_editor_h__ */ diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc index 62de67cd22..89cf608989 100644 --- a/gtk2_ardour/editor_canvas.cc +++ b/gtk2_ardour/editor_canvas.cc @@ -462,10 +462,10 @@ Editor::idle_drop_paths (vector<ustring> paths, nframes64_t frame, double ypos) void Editor::drop_paths_part_two (const vector<ustring>& paths, nframes64_t frame, double ypos) { - TimeAxisView* tvp; AudioTimeAxisView* tv; - if ((tvp = trackview_by_y_position (ypos)) == 0) { + std::pair<TimeAxisView*, int> const tvp = trackview_by_y_position (ypos); + if (tvp.first == 0) { /* drop onto canvas background: create new tracks */ @@ -477,7 +477,7 @@ Editor::drop_paths_part_two (const vector<ustring>& paths, nframes64_t frame, do do_embed (paths, Editing::ImportDistinctFiles, ImportAsTrack, frame); } - } else if ((tv = dynamic_cast<AudioTimeAxisView*>(tvp)) != 0) { + } else if ((tv = dynamic_cast<AudioTimeAxisView*> (tvp.first)) != 0) { /* check that its an audio track, not a bus */ diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc index b05d4e6c4c..478fc1afe4 100644 --- a/gtk2_ardour/editor_canvas_events.cc +++ b/gtk2_ardour/editor_canvas_events.cc @@ -93,7 +93,9 @@ Editor::track_canvas_scroll (GdkEventScroll* ev) } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) { if (!current_stepping_trackview) { step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500); - if (!(current_stepping_trackview = trackview_by_y_position (ev->y + vertical_adjustment.get_value() - canvas_timebars_vsize))) { + std::pair<TimeAxisView*, int> const p = trackview_by_y_position (ev->y + vertical_adjustment.get_value() - canvas_timebars_vsize); + current_stepping_trackview = p.first; + if (!current_stepping_trackview) { return false; } } @@ -126,7 +128,9 @@ Editor::track_canvas_scroll (GdkEventScroll* ev) } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) { if (!current_stepping_trackview) { step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500); - if (!(current_stepping_trackview = trackview_by_y_position (ev->y + vertical_adjustment.get_value() - canvas_timebars_vsize))) { + std::pair<TimeAxisView*, int> const p = trackview_by_y_position (ev->y + vertical_adjustment.get_value() - canvas_timebars_vsize); + current_stepping_trackview = p.first; + if (!current_stepping_trackview) { return false; } } diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 0e101957f2..c51e650f6f 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -2571,7 +2571,7 @@ Editor::marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) Marker* dragged_marker = (Marker*) drag_info.data; Marker* marker; Location *real_location; - Location *copy_location; + Location *copy_location = 0; if (drag_info.pointer_frame_offset <= drag_info.current_pointer_frame) { newframe = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; @@ -3385,7 +3385,9 @@ Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event) drag_info.last_frame_position = (nframes64_t) (clicked_regionview->region()->position() / speed); drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; drag_info.source_trackview = &clicked_regionview->get_time_axis_view(); + drag_info.source_layer = clicked_regionview->region()->layer(); drag_info.dest_trackview = drag_info.source_trackview; + drag_info.dest_layer = drag_info.source_layer; // we want a move threshold drag_info.want_move_threshold = true; show_verbose_time_cursor (drag_info.last_frame_position, 10); @@ -3404,6 +3406,7 @@ Editor::start_create_region_grab (ArdourCanvas::Item* item, GdkEvent* event) drag_info.data = clicked_axisview; drag_info.source_trackview = clicked_axisview; drag_info.dest_trackview = drag_info.source_trackview; + drag_info.dest_layer = drag_info.source_layer; drag_info.motion_callback = &Editor::create_region_drag_motion_callback; drag_info.finished_callback = &Editor::create_region_drag_finished_callback; @@ -3433,6 +3436,7 @@ Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event) drag_info.source_trackview = &clicked_regionview->get_time_axis_view(); drag_info.dest_trackview = drag_info.source_trackview; + drag_info.dest_layer = drag_info.source_layer; drag_info.last_frame_position = (nframes64_t) (clicked_regionview->region()->position() / speed); drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; // we want a move threshold @@ -3469,6 +3473,7 @@ Editor::start_region_brush_grab (ArdourCanvas::Item* item, GdkEvent* event) drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; drag_info.source_trackview = &clicked_regionview->get_time_axis_view(); drag_info.dest_trackview = drag_info.source_trackview; + drag_info.dest_layer = drag_info.source_layer; // we want a move threshold drag_info.want_move_threshold = true; drag_info.brushing = true; @@ -3545,12 +3550,13 @@ Editor::possibly_copy_regions_during_grab (GdkEvent* event) } bool -Editor::check_region_drag_possible (RouteTimeAxisView** tv) +Editor::check_region_drag_possible (RouteTimeAxisView** tv, layer_t* layer) { /* Which trackview is this ? */ - TimeAxisView* tvp = trackview_by_y_position (drag_info.current_pointer_y); - (*tv) = dynamic_cast<RouteTimeAxisView*>(tvp); + std::pair<TimeAxisView*, int> const tvp = trackview_by_y_position (drag_info.current_pointer_y); + (*tv) = dynamic_cast<RouteTimeAxisView*> (tvp.first); + (*layer) = tvp.second; /* The region motion is only processed if the pointer is over an audio track. @@ -3577,8 +3583,9 @@ void Editor::region_drag_splice_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { RouteTimeAxisView* tv; + layer_t layer; - if (!check_region_drag_possible (&tv)) { + if (!check_region_drag_possible (&tv, &layer)) { return; } @@ -3640,75 +3647,206 @@ Editor::region_drag_splice_finished_callback (ArdourCanvas::Item* item, GdkEvent } void +Editor::visible_order_range (int* low, int* high) const +{ + *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 (); + } + } + } +} + +/** @param new_order New track order. + * @param old_order Old track order. + * @param visible_y_low Lowest visible order. + * @param visible_y_high Highest visible order. + * @param tracks Bitset of tracks indexed by order; 0 means a audio/MIDI track, 1 means something else. + * @param heigh_list Heights of tracks indexed by order. + * @return true if y movement should not happen, otherwise false. + */ +bool +Editor::y_movement_disallowed ( + int new_order, int old_order, int y_span, int visible_y_low, int visible_y_high, + bitset<512> const & tracks, vector<int32_t> const & height_list + ) 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) >= 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 (height_list[new_order - (visible_tracks - n)] == 0) { + /* passing through a hidden track */ + n--; + } + } + + if (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) <= visible_y_high) { + + int32_t visible_tracks = 0; + int32_t n = 0; + while (visible_tracks > y_span ) { + visible_tracks--; + + while (height_list[new_order - (visible_tracks - n)] == 0) { + /* passing through a hidden track */ + n++; + } + } + + if (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) > visible_y_high) { + /* we will overflow */ + return true; + } else if ((new_order - y_span) < visible_y_low) { + /* we will overflow */ + return true; + } + } + + return false; +} + + +void Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { double x_delta; double y_delta = 0; nframes64_t pending_region_position = 0; - int32_t pointer_y_span = 0, canvas_pointer_y_span = 0, original_pointer_order; - int32_t visible_y_high = 0, visible_y_low = 512; //high meaning higher numbered.. not the height on the screen + int32_t pointer_y_span = 0, canvas_pointer_y_span = 0; + int32_t layer_span = 0; + bool clamp_y_axis = false; - vector<int32_t> height_list(512) ; vector<int32_t>::iterator j; - RouteTimeAxisView* tv; possibly_copy_regions_during_grab (event); - if (!check_region_drag_possible (&tv)) { + /* tv will become the TimeAxisView that we're currently pointing at, and + current_layer the current layer on that TimeAxisView */ + RouteTimeAxisView* tv; + layer_t current_layer; + if (!check_region_drag_possible (&tv, ¤t_layer)) { return; } - original_pointer_order = drag_info.dest_trackview->order (); + /* the order of the track that we were pointing at last time we entered this method */ + int32_t const last_pointer_order = drag_info.dest_trackview->order (); + /* the layer that we were pointing at last time we entered this method */ + layer_t const last_pointer_layer = drag_info.dest_layer; /************************************************************ - Y-Delta Computation + Y DELTA COMPUTATION ************************************************************/ + /* Height of TimeAxisViews, indexed by order */ + /* XXX: hard-coded limit of TimeAxisViews */ + vector<int32_t> height_list (512); + if (drag_info.brushing) { clamp_y_axis = true; pointer_y_span = 0; goto y_axis_done; } - if ((pointer_y_span = (drag_info.dest_trackview->order() - tv->order())) != 0) { + /* the change in track order between this callback and the last */ + pointer_y_span = drag_info.dest_trackview->order() - tv->order(); + /* the change in layer between this callback and the last */ + layer_span = drag_info.dest_layer - current_layer; + + if (pointer_y_span != 0) { int32_t children = 0; - // XXX hard coding track limit, oh my, so very very bad - bitset <1024> tracks (0x00); + /* XXX: hard-coded limit of tracks */ + bitset <512> tracks (0x00); + + int visible_y_high; + int visible_y_low; + visible_order_range (&visible_y_low, &visible_y_high); + /* get a bitmask representing the visible tracks */ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { - RouteTimeAxisView* rtv2 = dynamic_cast<RouteTimeAxisView*> (*i); + RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i); TimeAxisView::Children children_list; - /* zeroes are audio tracks. ones are other types. */ + /* zeroes are audio/MIDI tracks. ones are other types. */ - if (!rtv2->hidden()) { + if (!rtv->hidden()) { - if (visible_y_high < rtv2->order()) { - visible_y_high = rtv2->order(); - } - if (visible_y_low > rtv2->order()) { - visible_y_low = rtv2->order(); - } - - if (!rtv2->is_track()) { - tracks = tracks |= (0x01 << rtv2->order()); + if (!rtv->is_track()) { + /* not an audio nor MIDI track */ + tracks = tracks |= (0x01 << rtv->order()); } - height_list[rtv2->order()] = (*i)->current_height(); + height_list[rtv->order()] = (*i)->current_height(); children = 1; - if ((children_list = rtv2->get_child_list()).size() > 0) { + if ((children_list = rtv->get_child_list()).size() > 0) { for (TimeAxisView::Children::iterator j = children_list.begin(); j != children_list.end(); ++j) { - tracks = tracks |= (0x01 << (rtv2->order() + children)); - height_list[rtv2->order() + children] = (*j)->current_height(); + tracks = tracks |= (0x01 << (rtv->order() + children)); + height_list[rtv->order() + children] = (*j)->current_height(); children++; } } } } - /* find the actual span according to the canvas */ + + /* find the actual span, in terms of the number of visible tracks; + to do this, we reduce |pointer_y_span| by the number of hidden tracks */ canvas_pointer_y_span = pointer_y_span; if (drag_info.dest_trackview->order() >= tv->order()) { @@ -3726,94 +3864,48 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) } for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { - RegionView* rv2 = (*i); - double ix1, ix2, iy1, iy2; - int32_t n = 0; + + RegionView* rv = (*i); - if (rv2->region()->locked()) { + if (rv->region()->locked()) { continue; } - rv2->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2); - rv2->get_canvas_frame()->i2w (ix1, iy1); + double ix1, ix2, iy1, iy2; + rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2); + rv->get_canvas_frame()->i2w (ix1, iy1); iy1 += vertical_adjustment.get_value() - canvas_timebars_vsize; - TimeAxisView* tvp2 = trackview_by_y_position (iy1); - RouteTimeAxisView* rtv2 = dynamic_cast<RouteTimeAxisView*>(tvp2); + std::pair<TimeAxisView*, int> const tvp = trackview_by_y_position (iy1); + assert (tvp.first); + RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tvp.first); - if (rtv2->order() != original_pointer_order) { - /* this isn't the pointer track */ - - if (canvas_pointer_y_span > 0) { - - /* moving up the canvas */ - if ((rtv2->order() - canvas_pointer_y_span) >= visible_y_low) { - - int32_t visible_tracks = 0; - while (visible_tracks < canvas_pointer_y_span ) { - visible_tracks++; - - while (height_list[rtv2->order() - (visible_tracks - n)] == 0) { - /* we're passing through a hidden track */ - n--; - } - } - - if (tracks[rtv2->order() - (canvas_pointer_y_span - n)] != 0x00) { - clamp_y_axis = true; - } - - } else { - clamp_y_axis = true; - } - - } else if (canvas_pointer_y_span < 0) { - - /*moving down the canvas*/ + /* I know this method has a slightly excessive argument list, but I think + it's nice to separate the code out all the same, since it has such a simple result, + and it makes it clear that there are no other side-effects. + */ + clamp_y_axis = y_movement_disallowed ( + rtv->order(), last_pointer_order, canvas_pointer_y_span, visible_y_low, visible_y_high, + tracks, height_list + ); - if ((rtv2->order() - (canvas_pointer_y_span - n)) <= visible_y_high) { // we will overflow - - - int32_t visible_tracks = 0; - - while (visible_tracks > canvas_pointer_y_span ) { - visible_tracks--; - - while (height_list[rtv2->order() - (visible_tracks - n)] == 0) { - n++; - } - } - if ( tracks[rtv2->order() - ( canvas_pointer_y_span - n)] != 0x00) { - clamp_y_axis = true; - - } - } else { - - clamp_y_axis = true; - } - } - - } else { - - /* this is the pointer's track */ - if ((rtv2->order() - pointer_y_span) > visible_y_high) { // we will overflow - clamp_y_axis = true; - } else if ((rtv2->order() - pointer_y_span) < visible_y_low) { // we will underflow - clamp_y_axis = true; - } - } if (clamp_y_axis) { break; } } - } else if (drag_info.dest_trackview == tv) { - clamp_y_axis = true; - } + } else if (drag_info.dest_trackview == tv) { + + if (current_layer == last_pointer_layer) { + /* No movement; clamp */ + clamp_y_axis = true; + } + } y_axis_done: if (!clamp_y_axis) { - drag_info.dest_trackview = tv; + drag_info.dest_trackview = tv; + drag_info.dest_layer = current_layer; } /************************************************************ @@ -3861,8 +3953,6 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) pending_region_position = drag_info.last_frame_position; } - // printf ("3: pending_region_position= %lu %lu\n", pending_region_position, drag_info.last_frame_position ); - bool x_move_allowed; if (Config->get_edit_mode() == Lock) { @@ -3888,16 +3978,15 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) x_delta = -((double) (drag_info.last_frame_position - pending_region_position) / frames_per_unit); for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { - RegionView* rv2 = (*i); + RegionView* rv = (*i); // If any regionview is at zero, we need to know so we can stop further leftward motion. double ix1, ix2, iy1, iy2; - rv2->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2); - rv2->get_canvas_frame()->i2w (ix1, iy1); + rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2); + rv->get_canvas_frame()->i2w (ix1, iy1); if (-x_delta > ix1 + horizontal_adjustment.get_value()) { - // do_move = false; x_delta = 0; pending_region_position = drag_info.last_frame_position; break; @@ -3922,9 +4011,9 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) PREPARE TO MOVE ************************************************************/ - if (x_delta == 0 && (pointer_y_span == 0)) { + if (x_delta == 0 && pointer_y_span == 0 && layer_span == 0) { /* haven't reached next snap point, and we're not switching - trackviews. nothing to do. + trackviews nor layers. nothing to do. */ return; } @@ -3947,7 +4036,6 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) for (list<RegionView*>::const_iterator i = layered_regions.begin(); i != layered_regions.end(); ++i) { RegionView* rv = (*i); - int32_t temp_pointer_y_span = pointer_y_span; if (rv->region()->locked()) { continue; @@ -3994,68 +4082,73 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) rv->fake_set_opaque (true); } - TimeAxisView* tvp2 = trackview_by_y_position (iy1); - RouteTimeAxisView* canvas_rtv = dynamic_cast<RouteTimeAxisView*>(tvp2); - RouteTimeAxisView* temp_rtv; + std::pair<TimeAxisView*, int> pos = trackview_by_y_position (iy1); + RouteTimeAxisView* canvas_rtv = dynamic_cast<RouteTimeAxisView*> (pos.first); - if ((pointer_y_span != 0) && !clamp_y_axis) { - y_delta = 0; - int32_t x = 0; - for (j = height_list.begin(); j!= height_list.end(); j++) { - if (x == canvas_rtv->order()) { - /* we found the track the region is on */ - if (x != original_pointer_order) { - /*this isn't from the same track we're dragging from */ - temp_pointer_y_span = canvas_pointer_y_span; - } - while (temp_pointer_y_span > 0) { - /* we're moving up canvas-wise, - so we need to find the next track height - */ - if (j != height_list.begin()) { - j--; - } - if (x != original_pointer_order) { - /* we're not from the dragged track, so ignore hidden tracks. */ - if ((*j) == 0) { - temp_pointer_y_span++; - } - } - y_delta -= (*j); - temp_pointer_y_span--; - } + if (pointer_y_span != 0 && !clamp_y_axis) { - while (temp_pointer_y_span < 0) { - y_delta += (*j); - if (x != original_pointer_order) { - if ((*j) == 0) { - temp_pointer_y_span--; - } - } - - if (j != height_list.end()) { - j++; - } - temp_pointer_y_span++; - } - /* find out where we'll be when we move and set height accordingly */ + /* INTER-TRACK MOVEMENT */ + + /* move through the height list to the track that the region is going to */ + vector<int32_t>::iterator j = height_list.begin (); + int32_t x = 0; + while (j != height_list.end () && x != canvas_rtv->order ()) { + ++x; + ++j; + } - tvp2 = trackview_by_y_position (iy1 + y_delta); - temp_rtv = dynamic_cast<RouteTimeAxisView*>(tvp2); - rv->set_height (temp_rtv->current_height()); + y_delta = 0; + int32_t temp_pointer_y_span = pointer_y_span; - /* 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. + if (j != height_list.end ()) { + + while (temp_pointer_y_span > 0) { + /* we're moving up canvas-wise, + so we need to find the next track height */ - - //const GdkColor& col (temp_rtv->view->get_region_color()); - //rv->set_color (const_cast<GdkColor&>(col)); - break; + if (j != height_list.begin()) { + j--; + } + + y_delta -= (*j); + temp_pointer_y_span--; + } + + while (temp_pointer_y_span < 0) { + + y_delta += (*j); + + if (j != height_list.end()) { + j++; + } + + temp_pointer_y_span++; } - x++; + + /* find out where we'll be when we move and set height accordingly */ + + std::pair<TimeAxisView*, int> const pos = 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_y_span == 0 && layer_span != 0 && !clamp_y_axis) { + + /* INTER-LAYER MOVEMENT in the same track */ + assert (tv->view ()); + y_delta = tv->view()->child_height () * layer_span; + } + + if (drag_info.brushing) { mouse_brush_insert_region (rv, pending_region_position); } else { @@ -4092,6 +4185,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event pair<PlaylistSet::iterator,bool> insert_result, frozen_insert_result; nframes64_t drag_delta; bool changed_tracks, changed_position; + std::pair<TimeAxisView*, int> tvp; /* first_move is set to false if the regionview has been moved in the motion handler. @@ -4147,7 +4241,8 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event begin_reversible_command (op_string); changed_position = (drag_info.last_frame_position != (nframes64_t) (clicked_regionview->region()->position())); - changed_tracks = (trackview_by_y_position (drag_info.current_pointer_y) != &clicked_regionview->get_time_axis_view()); + tvp = trackview_by_y_position (drag_info.current_pointer_y); + changed_tracks = (tvp.first != &clicked_regionview->get_time_axis_view()); drag_delta = clicked_regionview->region()->position() - drag_info.last_frame_position; @@ -4161,8 +4256,8 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event rv->get_canvas_frame()->i2w (ix1, iy1); iy1 += vertical_adjustment.get_value() - canvas_timebars_vsize; - TimeAxisView* dest_tv = trackview_by_y_position (iy1); - RouteTimeAxisView* dest_rtv = dynamic_cast<RouteTimeAxisView*>(dest_tv); + std::pair<TimeAxisView*, int> const dest_tv = trackview_by_y_position (iy1); + RouteTimeAxisView* dest_rtv = dynamic_cast<RouteTimeAxisView*> (dest_tv.first); nframes64_t where; diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index 61ea85568f..467b8539f9 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -2261,7 +2261,6 @@ Editor::insert_region_list_drag (boost::shared_ptr<Region> region, int x, int y) { double wx, wy; double cx, cy; - TimeAxisView *tv; nframes64_t where; RouteTimeAxisView *rtv = 0; boost::shared_ptr<Playlist> playlist; @@ -2281,12 +2280,13 @@ Editor::insert_region_list_drag (boost::shared_ptr<Region> region, int x, int y) /* clearly outside canvas area */ return; } - - if ((tv = trackview_by_y_position (cy)) == 0) { + + std::pair<TimeAxisView*, int> tv = trackview_by_y_position (cy); + if (tv.first == 0) { return; } - if ((rtv = dynamic_cast<RouteTimeAxisView*>(tv)) == 0) { + if ((rtv = dynamic_cast<RouteTimeAxisView*> (tv.first)) == 0) { return; } @@ -2307,7 +2307,6 @@ void Editor::insert_route_list_drag (boost::shared_ptr<Route> route, int x, int y) { double wx, wy; double cx, cy; - TimeAxisView *tv; nframes_t where; RouteTimeAxisView *dest_rtv = 0; RouteTimeAxisView *source_rtv = 0; @@ -2323,11 +2322,12 @@ Editor::insert_route_list_drag (boost::shared_ptr<Route> route, int x, int y) { where = event_frame (&event, &cx, &cy); - if ((tv = trackview_by_y_position (cy)) == 0) { + std::pair<TimeAxisView*, int> const tv = trackview_by_y_position (cy); + if (tv.first == 0) { return; } - if ((dest_rtv = dynamic_cast<RouteTimeAxisView*>(tv)) == 0) { + if ((dest_rtv = dynamic_cast<RouteTimeAxisView*> (tv.first)) == 0) { return; } diff --git a/gtk2_ardour/editor_rulers.cc b/gtk2_ardour/editor_rulers.cc index a4344c3ffa..0d355832f2 100644 --- a/gtk2_ardour/editor_rulers.cc +++ b/gtk2_ardour/editor_rulers.cc @@ -843,8 +843,9 @@ Editor::update_ruler_visibility () } gdouble bottom_track_pos = vertical_adjustment.get_value() + canvas_height - canvas_timebars_vsize; - if (trackview_by_y_position(bottom_track_pos) != 0) { - trackview_by_y_position(bottom_track_pos)->clip_to_viewport (); + std::pair<TimeAxisView*, int> const p = trackview_by_y_position (bottom_track_pos); + if (p.first) { + p.first->clip_to_viewport (); } ruler_label_vbox.set_size_request (-1, (int)(timebar_height * visible_rulers)); diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc index 6166360542..5035814fa2 100644 --- a/gtk2_ardour/route_time_axis.cc +++ b/gtk2_ardour/route_time_axis.cc @@ -2171,8 +2171,22 @@ RouteTimeAxisView::update_rec_display () void RouteTimeAxisView::set_layer_display (LayerDisplay d) { - _view->set_layer_display (d); + if (_view) { + _view->set_layer_display (d); + } } + +LayerDisplay +RouteTimeAxisView::layer_display () const +{ + if (_view) { + return _view->layer_display (); + } + + /* we don't know, since we don't have a _view, so just return something */ + return Overlaid; +} + boost::shared_ptr<AutomationTimeAxisView> diff --git a/gtk2_ardour/route_time_axis.h b/gtk2_ardour/route_time_axis.h index 35c4b48a16..9e40c511a6 100644 --- a/gtk2_ardour/route_time_axis.h +++ b/gtk2_ardour/route_time_axis.h @@ -85,6 +85,7 @@ public: void get_inverted_selectables (Selection&, list<Selectable*>&); bool show_automation(Evoral::Parameter param); void set_layer_display (LayerDisplay d); + LayerDisplay layer_display () const; boost::shared_ptr<ARDOUR::Region> find_next_region (nframes_t pos, ARDOUR::RegionPoint, int32_t dir); nframes64_t find_next_region_boundary (nframes64_t pos, int32_t dir); diff --git a/gtk2_ardour/streamview.cc b/gtk2_ardour/streamview.cc index 9831bf742f..d8abf0f834 100644 --- a/gtk2_ardour/streamview.cc +++ b/gtk2_ardour/streamview.cc @@ -56,9 +56,9 @@ StreamView::StreamView (RouteTimeAxisView& tv, ArdourCanvas::Group* group) , use_rec_regions (tv.editor().show_waveforms_recording ()) , region_color(_trackview.color()) , stream_base_color(0xFFFFFFFF) - , layers(1) + , _layers (1) , height(tv.height) - , layer_display(Overlaid) + , _layer_display (Overlaid) , last_rec_data_frame(0) { /* set_position() will position the group */ @@ -233,7 +233,7 @@ StreamView::playlist_modified (boost::shared_ptr<Diskstream> ds) /* update layers count and the y positions and heights of our regions */ if (ds->playlist()) { - layers = ds->playlist()->top_layer() + 1; + _layers = ds->playlist()->top_layer() + 1; update_contents_height (); update_coverage_frames (); redisplay_diskstream (); @@ -256,7 +256,7 @@ StreamView::playlist_changed (boost::shared_ptr<Diskstream> ds) undisplay_diskstream (); /* update layers count and the y positions and heights of our regions */ - layers = ds->playlist()->top_layer() + 1; + _layers = ds->playlist()->top_layer() + 1; update_contents_height (); update_coverage_frames (); @@ -430,8 +430,8 @@ StreamView::get_inverted_selectables (Selection& sel, list<Selectable*>& results double StreamView::child_height () const { - if (layer_display == Stacked) { - return height / layers; + if (_layer_display == Stacked) { + return height / _layers; } return height; @@ -445,7 +445,7 @@ StreamView::update_contents_height () const double h = child_height (); for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) { - switch (layer_display) { + switch (_layer_display) { case Overlaid: (*i)->set_y (0); break; @@ -465,7 +465,7 @@ StreamView::update_contents_height () void StreamView::set_layer_display (LayerDisplay d) { - layer_display = d; + _layer_display = d; update_contents_height (); update_coverage_frames (); } @@ -474,6 +474,6 @@ void StreamView::update_coverage_frames () { for (RegionViewList::iterator i = region_views.begin (); i != region_views.end (); ++i) { - (*i)->update_coverage_frames (layer_display); + (*i)->update_coverage_frames (_layer_display); } } diff --git a/gtk2_ardour/streamview.h b/gtk2_ardour/streamview.h index 47c6277578..68498f30eb 100644 --- a/gtk2_ardour/streamview.h +++ b/gtk2_ardour/streamview.h @@ -73,6 +73,7 @@ public: gdouble get_samples_per_unit () { return _samples_per_unit; } void set_layer_display (LayerDisplay); + LayerDisplay layer_display () const { return _layer_display; } ArdourCanvas::Group* background_group() { return _background_group; } ArdourCanvas::Group* canvas_item() { return canvas_group; } @@ -97,6 +98,8 @@ public: virtual void update_contents_height (); virtual void redisplay_diskstream () = 0; + double child_height () const; + ARDOUR::layer_t layers () const { return _layers; } sigc::signal<void,RegionView*> RegionViewAdded; @@ -126,7 +129,6 @@ protected: virtual void playlist_modified (boost::shared_ptr<ARDOUR::Diskstream>); virtual void color_handler () = 0; - double child_height () const; RouteTimeAxisView& _trackview; bool owns_canvas_group; @@ -152,9 +154,9 @@ protected: vector<sigc::connection> playlist_connections; sigc::connection playlist_change_connection; - int layers; + ARDOUR::layer_t _layers; double height; - LayerDisplay layer_display; + LayerDisplay _layer_display; list<sigc::connection> rec_data_ready_connections; jack_nframes_t last_rec_data_frame; diff --git a/gtk2_ardour/time_axis_view.cc b/gtk2_ardour/time_axis_view.cc index 2eac4c53ee..8c56fb6585 100644 --- a/gtk2_ardour/time_axis_view.cc +++ b/gtk2_ardour/time_axis_view.cc @@ -50,6 +50,7 @@ #include "keyboard.h" #include "rgb_macros.h" #include "utils.h" + #include "streamview.h" #include "i18n.h" @@ -70,6 +71,7 @@ uint32_t TimeAxisView::hSmaller = 0; uint32_t TimeAxisView::hSmall = 0; bool TimeAxisView::need_size_info = true; + int const TimeAxisView::_max_order = 512; TimeAxisView::TimeAxisView (ARDOUR::Session& sess, PublicEditor& ed, TimeAxisView* rent, Canvas& canvas) : AxisView (sess), @@ -1191,30 +1193,46 @@ TimeAxisView::color_handler () } } -/** Returns a TimeAxisView* if this object covers y, or one of its children does. +/** @return Pair: TimeAxisView, layer index. + * TimeAxisView is non-0 if this object covers y, or one of its children does. * If the covering object is a child axis, then the child is returned. - * Returns 0 otherwise. + * TimeAxisView is 0 otherwise. + * Layer index is the layer number if the TimeAxisView is valid and is in stacked + * region display mode, otherwise 0. */ -TimeAxisView* +std::pair<TimeAxisView*, layer_t> TimeAxisView::covers_y_position (double y) { if (hidden()) { - return 0; + return std::make_pair ( (TimeAxisView *) 0, 0); } if (_y_position <= y && y < (_y_position + height)) { - return this; + + /* work out the layer index if appropriate */ + layer_t l = 0; + if (layer_display () == Stacked && view ()) { + /* compute layer */ + l = layer_t ((_y_position + height - y) / (view()->child_height ())); + /* clamp to max layers to be on the safe side; sometimes the above calculation + returns a too-high value */ + if (l >= view()->layers ()) { + l = view()->layers() - 1; + } + } + + return std::make_pair (this, l); } - for (Children::iterator i = children.begin(); i != children.end(); ++i) { - TimeAxisView* tv; + for (Children::const_iterator i = children.begin(); i != children.end(); ++i) { - if ((tv = (*i)->covers_y_position (y)) != 0) { - return tv; + std::pair<TimeAxisView*, int> const r = (*i)->covers_y_position (y); + if (r.first) { + return r; } } - return 0; + return std::make_pair ( (TimeAxisView *) 0, 0); } void diff --git a/gtk2_ardour/time_axis_view.h b/gtk2_ardour/time_axis_view.h index e3fbc88514..980ff2cdd8 100644 --- a/gtk2_ardour/time_axis_view.h +++ b/gtk2_ardour/time_axis_view.h @@ -66,6 +66,7 @@ class Selection; class Selectable; class RegionView; class GhostRegion; +class StreamView; /** Abstract base class for time-axis views (horizontal editor 'strips') * @@ -97,6 +98,9 @@ class TimeAxisView : public virtual AxisView, public PBD::Stateful /** @return index of this TimeAxisView within its parent */ int order () const { return _order; } + /** @return maximum allowable value of order */ + static int max_order () { return _max_order; } + ArdourCanvas::Group* canvas_display () { return _canvas_display; } ArdourCanvas::Group* canvas_background () { return _canvas_background; } ArdourCanvas::Group* ghost_group () { return _ghost_group; } @@ -149,7 +153,7 @@ class TimeAxisView : public virtual AxisView, public PBD::Stateful virtual void set_height (uint32_t h); void reset_height(); - TimeAxisView* covers_y_position (double y); + std::pair<TimeAxisView*, ARDOUR::layer_t> covers_y_position (double); /** * Steps through the defined heights for this TrackView. @@ -207,6 +211,9 @@ class TimeAxisView : public virtual AxisView, public PBD::Stateful /* call this on the parent */ virtual XMLNode* get_automation_child_xml_node (Evoral::Parameter param) { return 0; } + + virtual LayerDisplay layer_display () const { return Overlaid; } + virtual StreamView* view () const { return 0; } typedef std::vector<boost::shared_ptr<TimeAxisView> > Children; @@ -342,6 +349,8 @@ private: double _resize_drag_start; int32_t _resize_idle_target; ArdourCanvas::Group* _ghost_group; + + static int const _max_order; }; /* class TimeAxisView */ |